Некоторое время назад я решал задачу автоматической покупки домена. Нужно было оформить в виде библиотеки (jar и файл настроек), которая использовалась бы в корпоративном приложении на Java. Я начал поиски DNS провайдеров с public API. Желательно, чтобы API были попроще, и домены подешевле — такой баланс оказалось не просто найти.
Было рассмотрено много вариантов, некоторые из которых можно найти тут: stackoverflow. В последствии, я сузил круг до следующих претендентов:
Последний многие советовали, но это хостинг провайдер, а мне нужен был только ДНС – возможности не покупать сервер я там не нашел.
Первый имеет, на мой взгляд, очень удобный API – аутентификация может проходить вообще через HTTP Header X-DNSimple-Token, но есть и традиционный подход с http basic authorization. Формат запроса очень прост – короткие урлы. Ответы можно получать в JSON (XML тоже доступен) – вобщем все радует глаз, кроме цены — .com домен там стоит $14/y. Знающие люди поймут, что это неприемлимо.
Когда начал разбираться с http://www.namecheap.com/ — все оказалось довольно не плохо. И со стороны покупателя — цены в норме, на рынке он больше 10 лет (dnsimple.com через who is дал Creation date: 07 Apr 2010 17:32:00 – мелковат еще, плюс ID доменов, когда я создавал их через API был в районе 3000). И со стороны программиста: запросы в XML, но структура не сильно запутанная. Аутентификация через параметры в самом урле – ничего сложного.
Что мне больше всего понравилось – у них единственных из всех кандидатов оказался правильный sandbox. При регистрации в тестовом окружении у тебя на счету $9000 и ты можешь реально потестировать функции покупки, renew, reactivate и т.д. для домена. В DNsimple, к примеру, я не нашел возможности пользоваться тестовым окружением без того, чтоб вводить номер кредитки – а что это за sandbox, который не может работать без реальных данных?
Кроме того у них при редактировании host records домена есть возможность задать нестандартные значения (не только A, CNAME, AAAA, etc.) – есть еще “URL” – это позволяет делать редирект с вашего домена на некий урл (произвольный), а это как раз требовалось для задачи, и в случае отсутствия такой опции было бы необходимо что-то придумывать со стороны сервера заказчика. Такая фича есть далеко не у всех DNS провайдеров.
И еще этот провайдер довольно часто раздает купоны со скидкой (в API есть возможность использовать эти купоны) и организовывает акции (об одной из них – в конце статьи). Например недавно там были скидки для всех кто переводит свои домены от GoDaddy, в связи с SOPA-позициями последнего.
Полностью он выложен в свободном доступе: github.com кому надо пользуйтесь (заказчику по барабану).
Интерфейс DNSProvider имеет конкретную реализацию: NamecheapProvider, где присутствуют основные функции для работы с доменами – покупка, обновление записей, реактивация. Есть пакет моделей, где находятся объекты основных сущностей: Domain, DomainRecord, RecordType. Все остальное это классы запросов, и xml парсеры ответов.
Базовый класс запроса:
Каждый класс запроса реализует свою getCommand, которая соответствует его назначению:
Интерфейс парсера:
И пример реализации для получения списка доменов из вашего аккаунта:
Друг с другом запрос и разбор ответа сводит класс на дженериках:
Который принимает их через параметры и возвращает результат разбора xml ответа.
Для расширения функциональности нужно добавить функцию в интерфейс, создать класс запроса, класс парсера ответа, и объединить их через вызов ProviderOperator в соотв. функции NamecheapProvider.
www.namecheap.com имеет традицию – каждый год они организовывают твиттер-марафон на определенную тему. В течение 48 часов задаются 48 вопросов. Каждый час дается правильный ответ на предыдущий вопрос и задается следующий. Победителям деньги на счет (для покупки доменов) и пара iPad2 – самый ходовой приз большинства викторин. В этом году марафон решили приурочить к суперкубку. Я в американских видах спорта не силен, но решил для интереса ответить на какой-нибудь вопрос. Номер третий звучал примерно так:
«In what year was Bart Starr elected to the Wisconsin Athletic Hall of Fame»
— не долго думая, пошел в википедию смотреть его биографию. Отдельным обзацом было написано, что это произошло в 1980. Я твитнул это число в ответ. Через час твит с правильным ответом меня немного расстроил – 1981. Ну кто бы сомневался, подумал я, что в википедии даты не точные. Но все-таки решил зайти туда снова и посмотреть – расстроился еще больше. Там было действительно написано 1981. Я подумал, что пора затариваться таблетками для улучшения зрения, повышения внимания и ускорения работы мозга – вобщем все что прописывают старикам, и занялся другими делами.
Однако через пару часов от организатора марафона поступил интересный твит, приблизительно такого содержания:
«Уважаемые участники, мы считаем НЕДОПУСТИМЫМ редактировать википедию, чтобы дезинформировать соперников – это противоречит духу fair play. Уличенный в мошенничестве будет дисквалифицирован»
Я обрадовался — значит рано покупать лекарства.
UPD Всем спасибо за сообщение о поломанной подсветке.
Было рассмотрено много вариантов, некоторые из которых можно найти тут: stackoverflow. В последствии, я сузил круг до следующих претендентов:
Последний многие советовали, но это хостинг провайдер, а мне нужен был только ДНС – возможности не покупать сервер я там не нашел.
Первый имеет, на мой взгляд, очень удобный API – аутентификация может проходить вообще через HTTP Header X-DNSimple-Token, но есть и традиционный подход с http basic authorization. Формат запроса очень прост – короткие урлы. Ответы можно получать в JSON (XML тоже доступен) – вобщем все радует глаз, кроме цены — .com домен там стоит $14/y. Знающие люди поймут, что это неприемлимо.
Когда начал разбираться с http://www.namecheap.com/ — все оказалось довольно не плохо. И со стороны покупателя — цены в норме, на рынке он больше 10 лет (dnsimple.com через who is дал Creation date: 07 Apr 2010 17:32:00 – мелковат еще, плюс ID доменов, когда я создавал их через API был в районе 3000). И со стороны программиста: запросы в XML, но структура не сильно запутанная. Аутентификация через параметры в самом урле – ничего сложного.
Что мне больше всего понравилось – у них единственных из всех кандидатов оказался правильный sandbox. При регистрации в тестовом окружении у тебя на счету $9000 и ты можешь реально потестировать функции покупки, renew, reactivate и т.д. для домена. В DNsimple, к примеру, я не нашел возможности пользоваться тестовым окружением без того, чтоб вводить номер кредитки – а что это за sandbox, который не может работать без реальных данных?
Кроме того у них при редактировании host records домена есть возможность задать нестандартные значения (не только A, CNAME, AAAA, etc.) – есть еще “URL” – это позволяет делать редирект с вашего домена на некий урл (произвольный), а это как раз требовалось для задачи, и в случае отсутствия такой опции было бы необходимо что-то придумывать со стороны сервера заказчика. Такая фича есть далеко не у всех DNS провайдеров.
И еще этот провайдер довольно часто раздает купоны со скидкой (в API есть возможность использовать эти купоны) и организовывает акции (об одной из них – в конце статьи). Например недавно там были скидки для всех кто переводит свои домены от GoDaddy, в связи с SOPA-позициями последнего.
Перейдем к коду
Полностью он выложен в свободном доступе: github.com кому надо пользуйтесь (заказчику по барабану).
Интерфейс DNSProvider имеет конкретную реализацию: NamecheapProvider, где присутствуют основные функции для работы с доменами – покупка, обновление записей, реактивация. Есть пакет моделей, где находятся объекты основных сущностей: Domain, DomainRecord, RecordType. Все остальное это классы запросов, и xml парсеры ответов.
Базовый класс запроса:
public abstract class DNSBaseRequest {
private List<NameValuePair> params = new ArrayList<NameValuePair>();
protected DNSBaseRequest(Properties properties) {
params.add(new BasicNameValuePair("ApiUser", properties.getProperty("api.login")));
params.add(new BasicNameValuePair("ApiKey", properties.getProperty("api.key")));
params.add(new BasicNameValuePair("UserName", properties.getProperty("api.login")));
params.add(new BasicNameValuePair("ClientIp", properties.getProperty("client.ip")));
//each class has its own command - his purpose
params.add(new BasicNameValuePair("Command", getCommand()));
}
protected abstract String getCommand();
....
}
Каждый класс запроса реализует свою getCommand, которая соответствует его назначению:
public class DomainReactivateRequest extends DNSBaseRequest{
public DomainReactivateRequest(String domainName, Properties properties) {
super(properties);
addParam(new BasicNameValuePair("DomainName", domainName));
}
@Override
protected String getCommand() {
return "namecheap.domains.reactivate";
}
}
Интерфейс парсера:
public interface XmlResponseParser<T> {
T parse(String xml);
}
И пример реализации для получения списка доменов из вашего аккаунта:
public class DomainsListParser extends DefaultHandler implements XmlResponseParser<ArrayList<Domain>> {
private static final Logger log = LoggerFactory.getLogger(DomainsListParser.class);
private SAXParser parser;
private ArrayList<Domain> result;
public DomainsListParser() throws Exception{
SAXParserFactory factory = SAXParserFactory.newInstance();
parser = factory.newSAXParser();
result = new ArrayList<Domain>();
}
public ArrayList<Domain> parse(String xml) {
try {
parser.parse(new InputSource(new StringReader(xml)), this);
} catch(Exception e){
log.error("Error in parsing string.", e);
}
return result;
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if ("Domain".equalsIgnoreCase(qName)){
Domain domain = new Domain(Long.parseLong(attributes.getValue("ID")), attributes.getValue("Name"));
domain.setCreateDate(attributes.getValue("Created"));
domain.setExpireDate(attributes.getValue("Expires"));
result.add(domain);
}
}
}
Друг с другом запрос и разбор ответа сводит класс на дженериках:
public class ProviderOperator {
private static final Logger log = LoggerFactory.getLogger(ProviderOperator.class);
private DNSRequestProcessor dnsRequestProcessor;
public ProviderOperator(DNSRequestProcessor dnsRequestProcessor) {
this.dnsRequestProcessor = dnsRequestProcessor;
}
public <T, S extends T> T process(DNSBaseRequest dnsRequest, XmlResponseParser<T> parser, S defaultResult) {
T result = defaultResult;
try {
String xml = dnsRequestProcessor.get(dnsRequest);
log.debug("Response: {}", xml);
result = parser.parse(xml);
} catch (Exception e) {
log.error("Error in parse", e);
}
return result;
}
}
Который принимает их через параметры и возвращает результат разбора xml ответа.
Для расширения функциональности нужно добавить функцию в интерфейс, создать класс запроса, класс парсера ответа, и объединить их через вызов ProviderOperator в соотв. функции NamecheapProvider.
Напоследок интересная история
www.namecheap.com имеет традицию – каждый год они организовывают твиттер-марафон на определенную тему. В течение 48 часов задаются 48 вопросов. Каждый час дается правильный ответ на предыдущий вопрос и задается следующий. Победителям деньги на счет (для покупки доменов) и пара iPad2 – самый ходовой приз большинства викторин. В этом году марафон решили приурочить к суперкубку. Я в американских видах спорта не силен, но решил для интереса ответить на какой-нибудь вопрос. Номер третий звучал примерно так:
«In what year was Bart Starr elected to the Wisconsin Athletic Hall of Fame»
— не долго думая, пошел в википедию смотреть его биографию. Отдельным обзацом было написано, что это произошло в 1980. Я твитнул это число в ответ. Через час твит с правильным ответом меня немного расстроил – 1981. Ну кто бы сомневался, подумал я, что в википедии даты не точные. Но все-таки решил зайти туда снова и посмотреть – расстроился еще больше. Там было действительно написано 1981. Я подумал, что пора затариваться таблетками для улучшения зрения, повышения внимания и ускорения работы мозга – вобщем все что прописывают старикам, и занялся другими делами.
Однако через пару часов от организатора марафона поступил интересный твит, приблизительно такого содержания:
«Уважаемые участники, мы считаем НЕДОПУСТИМЫМ редактировать википедию, чтобы дезинформировать соперников – это противоречит духу fair play. Уличенный в мошенничестве будет дисквалифицирован»
Я обрадовался — значит рано покупать лекарства.
UPD Всем спасибо за сообщение о поломанной подсветке.