danieleteti / delphimvcframework

DMVCFramework (for short) is a popular and powerful framework for WEB API in Delphi. Supports RESTful and JSON-RPC WEB APIs development.
Apache License 2.0
1.26k stars 363 forks source link

TMVCWebRequest.ContentParam issue with Indy multipart/form-data request #758

Open aigazy opened 5 months ago

aigazy commented 5 months ago

Hello.

I have found that when I use Indy component to send a multipart/form-data request to the dmvcframework server, TMVCWebRequest.ContentParam function couldn't return the value of the content parameter.

I send a request using the TIdHTTP component, adding a form field as following: FFormData.AddFormField(AField, AValue, 'utf-8').ContentTransfer := '8bit'; Because I need to support UTF8 symbols in my endpoint.

I logged a request on the server side. Content type: multipart/form-data;boundary=--------061924103740983

Request body:

----------061924103740983
Content-Disposition: form-data; name="organization_id"
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: 8bit

5
----------061924103740983
Content-Disposition: form-data; name="first_name"
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: 8bit

Асқар
----------061924103740983
Content-Disposition: form-data; name="last_name"
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: 8bit

Ахмедов
----------061924103740983
Content-Disposition: form-data; name="job"
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: 8bit

Тестер
----------061924103740983
Content-Disposition: form-data; name="registered_at"
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: 8bit

2024-06-19 10:37:40
----------061924103740983

When I try to get the content param value, it returns empty string: var Param := Context.Request.ContentParam('organization_id') So I think that content param parser not working properly here.

aigazy commented 5 months ago

@danieleteti could you please take a look at this issue?

danieleteti commented 5 months ago

Why use a multipart/form-data when you actually need a application/x-www-form-urlencoded? (at least in the sample you wrote)

Send the params as follows:

  var lForm := TStringList.Create;
  try
    lForm.Values['field1'] := 'value1';
    lForm.Values['field2'] := 'value2';
    IdHTTP1.Post('http://localhost:8080/api/myformdata', lForm);
  finally
    lForm.Free;
  end;

and read params as follows:


type
  [MVCPath('/api')]
  TMyController = class(TMVCController)
  public
    [MVCPath('/myformdata')]
    [MVCHTTPMethod([httpPOST])]
    [MVCConsumes(TMVCMediaType.APPLICATION_FORM_URLENCODED)]
    function ReceiveFormData: IMVCResponse;
  end;

implementation

function TMyController.ReceiveFormData: IMVCResponse;
begin
  LogI(Context.Request.ContentParam('field1'));
  LogI(Context.Request.ContentParam('field2'));
end;

You can also use MVCFromContentField attribute to read content fields directly from action parameters.

aigazy commented 5 months ago

Because I need to send also files using multipart/form-data. Just try to send multipart/form-data request from the Indy component to the dmvcframework api server. If you will use a following charset and content transfer params:

FFormData.AddFormField(AField, AValue, 'utf-8').ContentTransfer := '8bit';

Server could not parse content params from the request.