I'm having some troubles trying to post xml to a web service using Indy.
My client is a class in delphi using Indy 10.0.52 and my api server is django-tastypie. My stack on the server is:
Django==1.5.1
defusedxml==0.4.1
django-tastypie==0.10.0
lxml==3.2.3
mimeparse==0.1.3
Other clients (like plain curl, python, js) are posting to the same resources without problems. For example:
$ 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
But using Indy I always get: '501 not implemented'. This is my procedure:
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' is a member instance of Indy TIdHTTP.
Can somebody please point me to what i'm doing wrong?
You are not resetting your stream's Position
back to 0 before posting it, you are not even posting the XML stream at all (you commented it out). You are also not taking character encoding into account, or replicating the same properties that you are passing to curl.
Try this:
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;