delphihttp-postidhttprad-studio

Capturing HTML POST with Delphi?


I want to get the post value that I send in HTML with Delphi. I am using TIdHTTPServer.

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.

image

Unfortunately, when I make the same request as HTML, it doesn't see POST. How do I achieve this?

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.)

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

Solution

  • First off, let me start by just saying this:

    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:

    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:

    <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:

    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;