IDHTTP.Post error

BeHunter picture BeHunter · Apr 10, 2013 · Viewed 7.3k times · Source
procedure Texport_plan.cxB_LoadClick(Sender: TObject);
var
  HTTP: TIdHTTP;
  Query: String;
  Buffer: TMemoryStream;
  loadData: Sting;
  responseData: String; 
begin 
  try
    HTTP := TIdHTTP.Create(nil);
    HTTP.Request.ContentEncoding := 'utf-8';
    HTTP.Request.ContentType := 'text/xml';
    Application.ProcessMessages;

    Query := 'http://priem.edu.ru:8000/import/ImportService.svc/import';
    loadData := '<Root></Root>'

    Buffer := TMemoryStream.Create;
    loadData.SaveToStream(Buffer);
    responseData := HTTP.Post(Query, Buffer);
  except
    on E: EIdHTTPProtocolException do
      ShowMessage(E.Message);
  end;
end;

This returns HTTP/1.1 400 Bad Request. If use get from http://priem.edu.ru:8000/import/ImportService.svc/test/import i get right xml document in response. Why could this happen? I checked all i can find in google...but nothing helps.

Im using RAD Delphi XE3

UPD: Test client works fine...C# + webclient class. May be something more exists for delphi...not only IdHTTP?

Answer

jachguate picture jachguate · Apr 11, 2013

Edit

It turned out that the assignment order of the Charset and ContentType is important.

If you use a ContentType containing the xml, xml-external-parsed-entity words or ending with +xml, the Charset is forcibly set to the value 'us-ascii' and to 'ISO-8859-1' in all other cases.

The behavior is undocumented, so you're free to think it is a bug or an implementation detail.

Comments from Remy in the body of TIdEntityHeaderInfo.SetContentType (IdHTTPHeaderInfo.pas) say:

// RLebeau: per RFC 3023 Sections 3.1, 3.3, 3.6, and 8.5:
//
// Conformant with [RFC2046], if a text/xml entity is received with
// the charset parameter omitted, MIME processors and XML processors
// MUST use the default charset value of "us-ascii"[ASCII]. In cases
// where the XML MIME entity is transmitted via HTTP, the default
// charset value is still "us-ascii". (Note: There is an
// inconsistency between this specification and HTTP/1.1, which uses
// ISO-8859-1[ISO8859] as the default for a historical reason. Since
// XML is a new format, a new default should be chosen for better
// I18N. US-ASCII was chosen, since it is the intersection of UTF-8
// and ISO-8859-1 and since it is already used by MIME.)

To change the charset, you must set it after setting the ContentType value, like this:

HTTP.Request.ContentType := 'text/xml';
HTTP.Request.Charset := 'utf-8';

Original answer
(still valid)

You're indicating your content is encoded in utf-8, but Delphi strings are utf-16 encoded by default.

I have no Delphi at hand to check if the string helper have a overloaded version of the SaveToStream method which supports encodings, but I bet it have, so you can try:

loadData.SaveToStream(Buffer, TEncoding.UTF8);

before sending your data.