【问题标题】:HTTP client error 403HTTP 客户端错误 403
【发布时间】:2014-11-25 13:44:55
【问题描述】:

我遇到以下问题:当我单击站点上的按钮 (http://domain-location.com) 时,我收到了返回给我的信息,并且 URL 更改为 http://domain-location.com?key=value。 我想创建一个示例 http 客户端来轻松接收信息。这是我的代码:

function DoRequest(aVal: string): string;
 const DOMAIN = 'http://domain-location.com';
 var
   request: TIdHTTP;
   responseStream: TMemoryStream;
   responseLoader: TStringList;
   urlRequest: string;
 begin
   request := TIdHTTP.Create(nil);
   responseStream := TMemoryStream.Create;
   responseLoader := TStringList.Create;

   try
     try
       // accept ranges didn't help
       // request.Response.AcceptRanges := 'text/json';
       // request.Response.AcceptRanges := 'text/xml';
       urlRequest := DOMAIN + '?key=' + aVal;
       request.Get(urlRequest, responseStream);
       responseStream.Position := 0;
       responseLoader.LoadFromStream(responseStream);
       Result := responseLoader.Text;
     except on E: Exception do
       Result := e.Message;
     end;
   finally
     responseLoader.Free;
     responseStream.Free;
     request.Free;
   end;
 end;

编辑在第一个答案之后,我编辑了我的函数(仍然无法正常工作):

 function DoRequest(aVal: string): string;
 const DOMAIN = 'http://domain-location.com';
 var
   request: TIdHTTP;
   responseStream: TMemoryStream;
   responseLoader: TStringList;
   urlRequest: string;
   uri: TIdURI;
 begin
   request := TIdHTTP.Create(nil);
   responseStream := TMemoryStream.Create;
   responseLoader := TStringList.Create;
   request.CookieManager := TIdCookieManager.Create(request);
   uri := TIdURI.Create(DOMAIN);

   try
     try
       // accept ranges didn't help
       // request.Response.AcceptRanges := 'text/json';
       // request.Response.AcceptRanges := 'text/xml';
       urlRequest := DOMAIN + '?key=' + aVal;
       request.CookieManager.AddServerCookie('cookie1', uri);
       request.CookieManager.AddServerCookie('cookie2', uri);
       request.CookieManager.AddServerCookie('cookie3', uri);
       request.Get(urlRequest, responseStream);
       responseStream.Position := 0;
       responseLoader.LoadFromStream(responseStream);
       Result := responseLoader.Text;
     except on E: Exception do
       Result := e.Message;
     end;
   finally
     responseLoader.Free;
     responseStream.Free;
     request.Free;
   end;
 end;

在我提出请求后,结果是:HTTP1.1 403 Forbidden。 我检查了页面,我点击的按钮是这样的:

<form action="http:/domiain.com" method="GET">
   <input type="text" name="key">
   <input type="submit" value="Click">
</form>

当我输入http://domain-location.com?key=value 时没有问题。 知道如何解决吗?

【问题讨论】:

  • 传递的aVal参数值URL是否编码?如果没有,并且需要它,请用urlRequest := DOMAIN + '?key=' + TIdURI.ParamsEncode(aVal); 包装它。
  • @TLama,但如果 OP 声明 When I type http://domain-location.com?key=value there is no problem,那么网络浏览器肯定不会发送额外的 application/x-www-form-urlencoded - 我假设他在网络浏览器中“输入”它。 Id 检查 cookie/UserAgent。应该嗅探 HTTP 请求以查看确切发布/接收的内容...
  • @TLama 或其他一些 HTTP 标头...请参阅 403 forbidden 的常见情况。
  • 欢迎 :) 实际上是一条评论。而不是编辑您自己的问题,请发布答案并接受它。我也不确定,是否需要request.Get(DOMAIN, TStream(nil)); 行?如果是,则还涉及 cookie。

标签: delphi httpclient http-status-code-403 indy10


【解决方案1】:

问题出在 UserAgent 上:

function DoRequest(aVal: string): string;
  const DOMAIN = 'http://domain-location.com';
var
  request: TIdHTTP;
  urlRequest: string;
begin
  request := TIdHTTP.Create(nil);

  try
    try
      request.Request.UserAgent := 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36';
      urlRequest := DOMAIN + '?key=' + aVal;
      Result := request.Get(urlRequest);
    except on E: Exception do
      Result := e.Message;
    end;
  finally
    request.Free;
  end;
end;

【讨论】:

    【解决方案2】:

    如果涉及 cookie,那么您应该首先GET 原始 HTML 页面,以便服务器可以在“单击”按钮时发送任何需要回发的 cookie,然后您可以GET 下一页和让TIdHTTP 发布它收到的任何 cookie。

    试试这个:

    function DoRequest(const aVal: string): string;
    const
      DOMAIN = 'http://domain-location.com';
    var
      request: TIdHTTP;
    begin
      try
        request := TIdHTTP.Create(nil);
        try
          request.Get(DOMAIN, TStream(nil)); // get cookies, discard HTML
          Result := request.Get(DOMAIN + '?key=' + TIdURI.ParamsEncode(aVal));
        finally
          request.Free;
        end;
      except
        on E: Exception do
          Result := e.Message;
      end;
    end;
    

    【讨论】:

    • TStream(nil) 是怎么回事?一个简单的request.Get(DOMAIN) 不应该完成这项工作,或者你以这种方式强制过载还是什么?
    • request.Get(DOMAIN) 调用function Get(AURL: string): string 方法,返回响应数据的解码String。在此示例中,未使用该数据,因此准备 String 是浪费开销。我改为调用procedure Get(AURL: string; AResponseContent: TStream) 方法,将TStream 参数设置为nil,以丢弃响应数据并避免分配内存和执行解码逻辑的开销。
    • 我测试过了。此行引发异常request.Get(DOMAIN, TStream(nil));
    【解决方案3】:

    检查您的浏览器发送的实际请求。 403 表明正在进行某种身份验证。这可能是您的浏览器拥有的令牌或 cookie,并随请求一起发送,但您的示例客户端应用程序可能没有。打开浏览器调试面板,检查浏览器发出的 get 请求,并将其与应用程序发出的请求进行比较。我敢打赌会有一些不同。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-10-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-25
      • 2016-01-23
      相关资源
      最近更新 更多