Atozed Forums

Full Version: Capturing HTML POST with Delphi? (Indy)
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hello,
I want to get the post value that I send in html with delphi. I am using idHTTPServer. My goal is to get the data sent by POST. But there is a problem. I send it as "form-data" with a tool like the picture below. Capturing the POST request. Unfortunately, when I make the same request as HTML, it doesn't see POST. How do I achieve this?

Code:
procedure TForm1.serviceCommandGet(AContext: TIdContext;
  ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
var
receiveStream: TStream;
begin
if ARequestInfo.URI = '/test.php' then
begin
if ARequestInfo.Command = 'POST' then
begin
  receiveStream := ARequestInfo.PostStream;
  if Assigned(receiveStream) then
  begin
   LOG.Lines.Add(ReadStringFromStream(receiveStream));
  end;
  AResponseInfo.ResponseNo := 200;
end;
end;
end;

HTML POST Request (Delphi doesn't see that request. My goal is to get that wish.)

Code:
<form method="post" action="http://localhost:99/test.php">
    <input type="hidden" name="test" value="04545">
     <input type="submit" value="send"/>
</form>

[Image: z5dqN.png]

It captures POST, which is in form-data format.
but does not see the POST request sent via HTML.
(Copying my answer to your same question on StackOverflow):

First off, let me start by just saying this:

- if ARequestInfo.Command = 'POST' then should be changed to either

  if TextIsSame(ARequestInfo.Command, 'POST') then

  or better

  if ARequestInfo.CommandType = hcPOST then

- OnCommand... event handlers are fired in the context of a worker thread, so any access to your UI MUST be synchronized with the main UI thread.

Now then, the HTML you have shown will post the webform values to an HTTP server using the "application/x-www-webform-urlencoded" media type.  In the TIdHTTPServer.OnCommandGet event, the ARequestInfo.PostStream property is not used with that media type and will be nil.  The posted webform values will instead be available in their original unparsed format in the ARequestInfo.FormParams and ARequestInfo.UnparsedParams properties, and in a parsed format in the ARequestInfo.Params property if the TIdHTTPServer.ParseParams property is True (which it is by default).

Try this instead:

Code:
procedure TForm1.serviceCommandGet(AContext: TIdContext;
  ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
var
  testValue: string;
begin
  if ARequestInfo.URI <> '/test.php' then
  begin
    AResponseInfo.ResponseNo := 404;
    Exit;
  end;
  if ARequestInfo.CommandType <> hcPOST then
  begin
    AResponseInfo.ResponseNo := 405;
    Exit;
  end;
  testValue := ARequestInfo.Params.Values['test'];
  TThread.Queue(nil,
    procedure
    begin
      LOG.Lines.Add('test: ' + testValue);
    end
  );
  AResponseInfo.ResponseNo := 200;
end;

That being said, "form-data" in your test tool refers to the "multipart/form-data" media type.  In HTML, if you want to post your webform using that media type, you have to explicitly state that in the enctype parameter of the <form> element, eg:

Code:
<form method="post" action="http://localhost:99/test.php" enctype="multipart/form-data">
    <input type="hidden" name="test" value="04545">
    <input type="submit" value="send"/>
</form>

In which case, TIdHTTPServer does not currently support parsing "multipart/form-data" posts, so ARequestInfo.PostStream will not be nil, providing the raw bytes of the webform so you can parse the data manually as needed.

You can differentiate the media type used for posting the webform by looking at the ARequestInfo.ContentType property, eg:

Code:
procedure TForm1.serviceCommandGet(AContext: TIdContext;
  ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
var
  testValue: string;
  data: string;
begin
  if ARequestInfo.URI <> '/test.php' then
  begin
    AResponseInfo.ResponseNo := 404;
    Exit;
  end;
  if ARequestInfo.CommandType <> hcPOST then
  begin
    AResponseInfo.ResponseNo := 405;
    Exit;
  end;
  if IsHeaderMediaType(ARequestInfo.ContentType, 'application/x-www-form-urlencoded') then
  begin
    testValue := ARequestInfo.Params.Values['test'];
    TThread.Queue(nil,
      procedure
      begin
        LOG.Lines.Add('test: ' + testValue);
      end
    );
    AResponseInfo.ResponseNo := 200;
  end
  else if IsHeaderMediaType(ARequestInfo.ContentType, 'multipart/form-data') then
  begin
    data := ReadStringFromStream(ARequestInfo.PostStream);
    TThread.Queue(nil,
      procedure
      begin
        LOG.Lines.Add('form-data: ' + data);
      end
    );
    AResponseInfo.ResponseNo := 200;
  end else
  begin
    AResponseInfo.ResponseNo := 415;
  end;
end;
Thank you so much master