【问题标题】:Delphi Indy post error 501Delphi Indy 发布错误 501
【发布时间】:2013-11-19 15:04:39
【问题描述】:

我在尝试使用 Indy 将 xml 发布到 Web 服务时遇到了一些麻烦。

我的客户端是使用 Indy 10.0.52 的 delphi 类,我的 api 服务器是 django-tastypie。 我在服务器上的堆栈是:

Django==1.5.1
defusedxml==0.4.1
django-tastypie==0.10.0
lxml==3.2.3
mimeparse==0.1.3

其他客户端(如普通 curl、python、js)可以毫无问题地发布到相同的资源。 例如:

$ curl --dump-header - -H "Content-Type: application/xml" -H "Authentication: Basic 875488" -k -X POST --data '<object>...</object>' https://www....object/?format=xml
HTTP/1.1 201 CREATED
Date: Tue, 19 Nov 2013 10:28:01 GMT
Server: Apache/2.2.14 (Ubuntu)
Access-Control-Allow-Headers: Origin,Authorization,Content-Type,Accept
Vary: Accept,Accept-Encoding
Location: https://www....object/12
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST,GET,OPTIONS,PUT,DELETE
Content-Length: 0
Content-Type: text/html; charset=utf-8

但是使用 Indy 我总是得到:'501 not implemented'。 这是我的程序:

procedure TRestObject.post( postURL:String; doc:IXMLDocument );
var
  aStream : TMemoryStream;
  data : TStringStream;
  xmlString, urlString : String;
begin
  aStream := TMemoryStream.Create;
  data := TStringStream.Create('');
  try
    http.HandleRedirects := True;
    http.ReadTimeout := 50000;
    // encoding
    xmlString := doc.XML.Strings[1];
    urlString := URLencode(xmlString);
    showmessage(xmlString);
    //showmessage(urlString);
    data.WriteString( urlString );
    aStream.Write( urlString[1], Length(urlString) * SizeOf(Char) );
    with http do
    begin
      try
        Response.KeepAlive := False;
        //Post( postURL, data, aStream );
        Post( postURL, aStream );
      except
        on E: EIdException do
          showmessage('Exception (class '+ E.ClassName +'): ' + E.Message);
        on E: EIdHTTPProtocolException do
          showmessage('Protocol Exception (HTTP status '+ IntToStr(E.ErrorCode) +'): ' + E.Message);
        on E: EIdSocketError do
          showmessage('Socket Error ('+ IntToStr(E.LastError) +'): ' + E.Message);
      end;
    end;
  finally
    aStream.Free;
    data.Free;
  end;
end;

'http' 是 Indy TIdHTTP 的成员实例。

谁能指出我做错了什么?

【问题讨论】:

  • @Lex:感谢编辑!

标签: xml delphi indy10 tastypie


【解决方案1】:

在发布之前,您没有将流的 Position 重置为 0,甚至根本没有发布 XML 流(您已将其注释掉)。您也没有考虑字符编码,或者复制您传递给 curl 的相同属性。

试试这个:

procedure TRestObject.post( postURL:String; doc:IXMLDocument );
var
  aStream: TMemoryStream;
  data : TStringStream;
  xmlString : String;
begin
  aStream := TMemoryStream.Create;
  try
    http.HandleRedirects := True;
    http.ReadTimeout := 50000;
    // encoding
    xmlString := doc.XML.Text;
    ShowMessage(xmlString);
    data := TStringStream.Create(xmlString, TEncoding.UTF8);
    try
      http.Request.ContentType := 'application/xml';
      http.Request.Connection := 'close';
      try
        http.Post( postURL, data, aStream );
      except
        on E: EIdHTTPProtocolException do
          ShowMessage('Protocol Exception (HTTP status '+ IntToStr(E.ErrorCode) +'): ' + E.Message);
        on E: EIdSocketError do
          ShowMessage('Socket Error ('+ IntToStr(E.LastError) +'): ' + E.Message);
        on E: Exception do
          ShowMessage('Exception (class '+ E.ClassName +'): ' + E.Message);
      end;
    finally
      data.Free;
    end;
  finally
    aStream.Free;
  end;
end;

【讨论】:

  • 还是不行。仍然收到 501 错误...将 XML 放入“数据”的方法是我第一次尝试的方法之一。但它没有用,这就是我尝试使用字符串流的原因。一篇文章被评论(使用“数据”的一篇),第二篇是使用字符串流发送 XML 的一篇。
  • 身份验证参数是在创建“http”成员对象期间提供的,因为伴随方法“TrestObject.get”在同一台服务器上工作,所以它可以工作。
  • 然后您需要使用数据包嗅探器,例如 Wireshark,来捕获 curl 和 TIdHTTP 的实际 HTTP 请求,比较它们的差异,然后相应地更新您的 TIdHTTP 代码。您可能只是缺少属性设置,或者在某处设置了错误/格式错误的值。关于身份验证,您可能需要将相关的IdAuthentication... 单元添加到您的uses 子句以启用除Basic 之外的TIdHTTP 身份验证方案,例如NTLM。
  • 好的,答案 501 是由于内容编码错误...谢谢大家。
猜你喜欢
  • 2020-01-29
  • 2014-07-08
  • 1970-01-01
  • 2014-10-16
  • 1970-01-01
  • 1970-01-01
  • 2013-09-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多