我试图使用第三方网络API,它希望请求正文是一个XML文档,但服务器正在接收的XML因为格式不正确而被拒绝,因为Indy已经取代了ANSI代码的一堆字符。
我正在使用XE2和Indy 10.5.8.0。
我已经注意到Indy正在将CRLF转换为&,因此将所有这些转换为源XML。现在,当我传递给.Post的TStringList包含:
<?xml version="1.0" encoding="utf-8"?><AdCourierAPI>
服务器正在看:
%3C%3Fxml+version=%221.0%22+encoding%3D%22utf-8%22%3F%3E%3CAdCourierAPI%3E
如何阻止Indy这样做?我需要更改编码吗?
以下是其中一种API方法的代码:
function TBroadBeanAPI.ListChannels(const AUserName, APassword: String): String;
var
HTTP: TIdHTTP;
SSL: TIdSSLIOHandlerSocketOpenSSL;
ASource: TStringList;
XMLRequest: String;
begin
HTTP := TIdHTTP.Create(nil);
SSL := TIdSSLIOHandlerSocketOpenSSL.Create(HTTP);
ASource := TStringList.Create;
Result := '';
try
HTTP.IOHandler := SSL;
HTTP.Request.ContentType := 'text/xml';
HTTP.Request.Charset := 'utf-8';
XMLRequest := '<?xml version="1.0" encoding="utf-8"?>'+
'<AdCourierAPI>'+
' <Method>ListChannels</Method>'+
' <APIKey>'+APIKEY+'</APIKey>'+
' <Account>'+
' <UserName>'+AUserName+'</UserName>'+
' <Password>'+APassword+'</Password>'+
' </Account>'+
'</AdCourierAPI>';
ASource.Text := XMLRequest;
Result := HTTP.Post(APIURL, ASource);
finally
SSL.Free;
HTTP.Free;
ASource.Free;
end;
end;
答案 0 :(得分:3)
您使用的是Post()
的错误版本。
您正在使用Post()
的重载版本接受TStrings
作为输入。该版本旨在以application/x-www-form-urlencoded
格式发布HTML网络表单,其中TStrings
应包含根据W3C提交网络表单规则进行编码的name=value
字符串。这就是为什么你看到你的XML被编码的原因。
您需要使用接受Post()
作为输入的TStream
的其他重载版本。 TStream
数据将按原样传输。
试试这个:
function TBroadBeanAPI.ListChannels(const AUserName, APassword: String): String;
var
HTTP: TIdHTTP;
SSL: TIdSSLIOHandlerSocketOpenSSL;
ASource: TStringStream;
XMLRequest: String;
begin
Result := '';
HTTP := TIdHTTP.Create(nil);
try
SSL := TIdSSLIOHandlerSocketOpenSSL.Create(HTTP);
HTTP.IOHandler := SSL;
HTTP.Request.ContentType := 'text/xml';
HTTP.Request.Charset := 'utf-8';
XMLRequest := '<?xml version="1.0" encoding="utf-8"?>'+
'<AdCourierAPI>'+
' <Method>ListChannels</Method>'+
' <APIKey>'+APIKEY+'</APIKey>'+
' <Account>'+
' <UserName>'+AUserName+'</UserName>'+
' <Password>'+APassword+'</Password>'+
' </Account>'+
'</AdCourierAPI>';
ASource := TStringStream.Create(XMLRequest, TEncoding.UTF8);
try
Result := HTTP.Post(APIURL, ASource);
finally
ASource.Free;
end;
finally
HTTP.Free;
end;
end;
另外,在构建XML时,您没有对APIKEY
,AUserName
或APassword
进行编码。如果它们包含保留字符,则必须按照XML格式规则对它们进行转义/编码。所以要小心。您应该使用真正的XML引擎来构建XML,而不是使用字符串连接。否则,至少要添加符合XML的编码函数,以便连接格式正确的字符串。
答案 1 :(得分:0)
答案是关闭TIdHTTP对象的HTTPOptions中的[hoForceEncodeParams]。这可以这样做:
HTTP.HTTPOptions := [];