2012-07-31 2 views
1

Может ли кто-нибудь указать в правильном направлении? Я пытаюсь выполнить поиск в Интернете, новый новый Bing API, но с приведенным ниже кодом я продолжаю получать «HTTP/1.1 400 Bad Request». Тот же запрос хорошо работает в браузере (оставляя имя пользователя пустым и предоставляя ключ под паролем внутри окна подсказки).Bing Search API Аутентификация на рынке Azure Marketplace (Delphi + Indy)

var 
    IdHTTP1 : TIdHTTP; 
    uri : string; 
    myIOhandler : TIdSSLIOHandlerSocketOpenSSL; 
begin 
    myIOhandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil); 
    with myIOhandler do 
    begin 
     SSLOptions.Method := sslvTLSv1; 
     SSLOptions.Mode := sslmUnassigned; 
     SSLOptions.VerifyMode := []; 
     SSLOptions.VerifyDepth := 0; 
     host := ''; 
    end; 

    IdHTTP1:= TIdHTTP.Create(nil); 
    IdHTTP1.Request.UserAgent:= 'Mozilla/3.0 (compatible; IndyLibrary)'; 
    IdHTTP1.Request.Accept := 'text/javascript'; 
    IdHTTP1.Request.ContentType := 'application/json'; 
    IdHTTP1.Request.ContentEncoding := 'utf-8'; 

    IdHTTP1.HandleRedirects:= True; 
    IdHTTP1.ConnectTimeout:= 10000; 
    IdHTTP1.ReadTimeout:= 10000; 
    IdHTTP1.Request.CacheControl := 'no-cache'; 
    IdHTTP1.Request.BasicAuthentication:= True; 
    IdHTTP1.Request.Authentication:= TIdBasicAuthentication.Create; 
    IdHTTP1.Request.Authentication.Username:= ''; 
    IdHTTP1.Request.Authentication.Password:= APIKey;//Encode64(APIKey);//Encode64(APIKey+':'+APIKey) 
    IdHTTP1.IOHandler:= myIOHandler; 

    uri:= 'https://api.datamarket.azure.com/Bing/SearchWeb/Web?'+ 
      'Query=%27'+ query_text +'%27&$format=JSON&$top=50&$skip=0'; 
    s:= IdHTTP1.Get(uri); 

Документация MS очень бедна.

+0

Вы уверены, что HTTP Basic Auth должен работать с пустым именем пользователя? И правильно ли запрос_текст «закодирован в URL»? – mjn

+0

В соответствии с Документом для руководства по миграции: «Оставьте поле имени пользователя пустым и введите свой ключ учетной записи в поле пароля». –

+0

Просто для тестирования я не использую никаких символов, которые нуждаются в кодировке. Я поговорю об этом позже. Эта же строка работает в браузере. –

ответ

3

TIdHTTP обрабатывает Basic аутентификации автоматически. Просто установите IdHTTP1.Request.BasicAuthentication := True, а затем заполните IdHTTP1.Request.Username и IdHTTP1.Request.Password. Вам не нужно иметь дело с TIdBasicAuthentication напрямую.

Если вы хотите, чтобы поддерживать другие аутентификации, такие как NTLM, просто добавьте relavant IdAuthentication... блока (ы), или IdAllAuthentication блока, к вашему пункту uses.

Вы также можете реализовать свой собственный класс TIdAuthentication -derived, если вы хотите поддерживать пользовательские аутентификации, которые Indy не поддерживает. Вы можете позвонить по телефону RegisterAuthenticationMethod(), так что TIdHTTP может использовать ваш пользовательский класс автоматически, или вы можете использовать событие TIdHTTP.OnSelectAuthorization, чтобы назначить класс вручную по запросу.

1

Я думаю, что проблема заключается в имени пользователя. С базовой аутентификации, вы должны послать заголовок, который выглядит следующим образом:

Authorization: Basic BASE64ENC(username:password) 

Поскольку имя пользователя пуст, в вашем случае, вы на самом деле отправки этого:

Authorization: Basic BASE64ENC(:password) 

Даже если документация говорит, чтобы оставить имя пользователя пустое, это относится только к тому, когда вы посещаете страницу через браузер. Посмотрите на примеры кода к концу документа, вы увидите, что во многих из этих примеров, как имя пользователя и пароль являются ключевыми клиентами:

bingContainer.Credentials = new NetworkCredential(accountKey, accountKey); 

Я предлагаю вам сделать то же самое в вашем код:

IdHTTP1.Request.Authentication:= TIdBasicAuthentication.Create; 
IdHTTP1.Request.Authentication.Username:= APIKey; 
IdHTTP1.Request.Authentication.Password:= APIKey; 
+0

Благодарим вас за предложение, но оно не работает. Я собираюсь заменить мои библиотеки OpenSSL и настроить параметры SSL, возможно, они имеют к этому какое-то отношение. –

+2

TIdHTTP автоматически обрабатывает базовую аутентификацию. Просто установите 'IdHTTP1.Request.BasicAuthentication: = True', а затем заполните свойства' IdHTTP1.Request.Username' и 'IdHTTP1.Request.Password'.Вам не нужно напрямую обращаться к 'TIdBasicAuthentication'. –

+0

@RemyLebeau: Это сработало! Отправьте его как ответ, пожалуйста. –

Смежные вопросы