将 https 请求从 java 翻译成 delphi

Translate of https request from java to delphi

具有以下java代码:

    // Set your API key: remember to change this to your live API key in production
    String apiKeyUserName = "your api username";
    String apiKeyPassword = "your api password";

    // Set the query params
    DefaultHttpClient httpclient = new DefaultHttpClient();

    List<NameValuePair> params = new ArrayList<NameValuePair>();
    params.add(new BasicNameValuePair("fromPostcode", "2000"));
    params.add(new BasicNameValuePair("toPostcode", "3000"));
    params.add(new BasicNameValuePair("networkId", "01"));
    params.add(new BasicNameValuePair("lodgementDate", "2013-08-01"));
    String query = URLEncodedUtils.format(params, "UTF-8");

    String urlPrefix = "api.auspost.com.au";
    String validateURL = "https://" + urlPrefix + "/DeliveryDates.xml?";

    HttpGet httpGet = new HttpGet(validateURL + query);
    httpGet.addHeader("Cookie", "OBBasicAuth=fromDialog");
    httpGet.addHeader(BasicScheme.authenticate(
        new UsernamePasswordCredentials(apiKeyUserName, apiKeyPassword),
        "US-ASCII",false));

HttpResponse response = httpclient.execute(httpGet);

想将其翻译成 Delphi。对于我使用 TIdHttp 的请求,如下所示:

procedure RequestDeliveryDate;
var
  IdHTTP: TIdHTTP;
  LHandler: TIdSSLIOHandlerSocketOpenSSL;
  lResponse: String;
  requestURL: String;
begin
  IdHTTP := TIdHTTP.Create();
  IdHTTP.Request.BasicAuthentication := True;
  IdHTTP.Request.Username := 'your api username';
  IdHTTP.Request.Password := 'your api password';
  IdHTTP.Request.CharSet := 'utf-8';

  LHandler := TIdSSLIOHandlerSocketOpenSSL.Create();
  IdHTTP.IOHandler := LHandler;

  requestURL := 'https://api.auspost.com.au/DeliveryDates.xml?fromPostcode=2000' +
                                                            '&toPostcode=3000' +
                                                            '&networkId=01' +
                                                            '&lodgementDate=2018-02-23' +
                                                            '&numberOfDates=01';
  screen.Cursor := crHourGlass;
  try
    lResponse := IdHTTP.Get(requestURL);
    screen.Cursor := crDefault;
  except
    on E: Exception do
    begin
      screen.Cursor := crDefault;
      ShowMessage(E.Message);
    end;
  end;
  IdHTTP.Free;
end;

假设我确实提供了正确的 api 用户名和密码。当我调用上面的代码时,出现以下错误: “此服务器无法验证您是否有权访问所请求的文档。 您提供了错误的凭据(例如密码错误),或者您的浏览器不了解如何提供所需的凭据。"

我做错了什么?有什么建议吗?

正如@ElliottFrisch 在评论中所述,您没有发送 Cookie header。有两种方法可以做到这一点:

  • 使用 CustomHeaders 属性:

    IdHTTP.Request.CustomHeaders.AddValue('Cookie', 'OBBasicAuth=fromDialog');
    
  • 使用 CookieManager 属性 伪造一个实际的 cookie,然后让 TIdHTTP 为您生成 Cookie header(是务必预先分配一个 TIdCookieManager 组件,并设置 TIdHTTP. AllowCookies=True):

    url := TIdURI.Create('https://api.auspost.com.au/DeliveryDates.xml');
    try
      IdHTTP.CookieManager.AddServerCookie('OBBasicAuth=fromDialog', url);
    finally
      url.Free;
    end;
    

您还泄露了 TIdSSLIOHandlerSocketOpenSSL object。我建议将 TIdHTTP 分配为它的 Owner。并且对 IdHTTP.Free 的调用应该在 try..finally 中,以备不时之需。

试试这个:

procedure RequestDeliveryDate;
var
  IdHTTP: TIdHTTP;
  LHandler: TIdSSLIOHandlerSocketOpenSSL;
  requestURL, query, lResponse: String;
  //url: TIdURI;
begin
  requestURL := 'https://api.auspost.com.au/DeliveryDates.xml';
  query := '?fromPostcode=2000' +
           '&toPostcode=3000' +
           '&networkId=01' +
           '&lodgementDate=2018-02-23' +
           '&numberOfDates=01';

  try
    IdHTTP := TIdHTTP.Create;
    try
      IdHTTP.Request.BasicAuthentication := True;
      IdHTTP.Request.Username := 'your api username';
      IdHTTP.Request.Password := 'your api password';

      IdHTTP.Request.CustomHeaders.AddValue('Cookie', 'OBBasicAuth=fromDialog');    
      {
      url := TIdURI.Create(requestURL);
      try
        IdHTTP.CookieManager.AddServerCookie('OBBasicAuth=fromDialog', url);
      finally
        url.Free;
      end;
      }

      LHandler := TIdSSLIOHandlerSocketOpenSSL.Create(IdHTTP);
      IdHTTP.IOHandler := LHandler;

      screen.Cursor := crHourGlass;
      try
        lResponse := IdHTTP.Get(requestURL + query);
      finally
        screen.Cursor := crDefault;
      end;
    finally
      IdHTTP.Free;
    end;
  except
    on E: Exception do
      ShowMessage(E.Message);
  end;
end;