zendframework / zend-diactoros

PSR-7 HTTP Message implementation
BSD 3-Clause "New" or "Revised" License
1.56k stars 152 forks source link

Unable to handle formData #264

Closed Wikiki closed 6 years ago

Wikiki commented 7 years ago

Hi,

I'm trying to use formData to have a generic function to send form using Ajax but without any success. I use the following javascript code data: new FormData( _this[ 0 ] ) to send all data using FormData. I set the request header Content-type: multipart/form-databut when trying to get the content via $request->getParsedBody()the content is empty. I get a 0 length array.

If I look at the request parameters (in my browser) I have the following request payload:

-----------------------------20852767153126299651626821193
Content-Disposition: form-data; name="username"

mylogin
-----------------------------20852767153126299651626821193
Content-Disposition: form-data; name="password"

mypassword
-----------------------------20852767153126299651626821193--

Do you now how I can manage this ?

Regards

Ocramius commented 7 years ago

Form data should be sent as application/x-www-form-urlencoded in order for your PHP SAPI of choice to understand it.

See also https://stackoverflow.com/questions/4007969/application-x-www-form-urlencoded-or-multipart-form-data

Wikiki commented 7 years ago

Thanks for the information. But unfortunately, even if I set request header to application/x-www-form-urlencodedit doesn't work :-(

This modification set the payload as a Form-data content instead of a classic request payload (in the request parameters in my browser) but I still can't able to get the content with $request->getParsedBody();

Ocramius commented 7 years ago

Can you make an example HTML with the XHR request setup?

Wikiki commented 7 years ago

You can find a sample here: https://codepen.io/wikiki/pen/RZgvOL

Ocramius commented 7 years ago

I must say that I never used FormData: the same request works perfectly fine when using a string for the request body:

xhr.send("foo=foo&bar=bar");
adamlundrigan commented 7 years ago

@Wikiki I think the problem is your use of application/x-www-form-urlencoded. From the FormData page on MDN:

It uses the same format a form would use if the encoding type were set to "multipart/form-data".

Try setting the Content-type header to multipart/form-data instead.

Wikiki commented 7 years ago

Hi @adamlundrigan,

I already tried both content-type but none of those work :-(

Wikiki commented 6 years ago

Any idea ?

hkulekci commented 6 years ago

You can use below two example. Both of them works with zend-expressive so it may work with zend-diactoros.

With application/x-www-form-urlencoded:

    var data = {'grant_type': 'password', 'username': 'test', 'password': '123456'};
    var urlEncodedData = '';
    var urlEncodedDataPairs = [];
    var xhr = new XMLHttpRequest();
    xhr.open( 'post', 'http://127.0.0.1:8080/access_token', true );
    xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
    for(name in data) {
        urlEncodedDataPairs.push(encodeURIComponent(name) + '=' + encodeURIComponent(data[name]));
    }
    urlEncodedData = urlEncodedDataPairs.join('&').replace(/%20/g, '+');
    xhr.send(urlEncodedData);

With multipart/form-data:

    var formData = new FormData();

    formData.append("grant_type", "password");
    formData.append("username", "test");
    formData.append("accountnum", 123456);

    var request = new XMLHttpRequest();
    request.open("POST", "http://127.0.0.1:8080/access_token");
    request.send(formData);

We can add these two example to documentation, if not exists. What do you think?

Wikiki commented 6 years ago

Hi @hkulekci,

Thanks but my question is not about how to use formData on javaScript side but how to handle data on PHP side using diactoros. Currently if I send formData the $request var does not contains my data sent.

If you can ensure these example work with diactoros then it could be helpfull to add them to the documentation.

Regards

hkulekci commented 6 years ago

@Wikiki you can use $request->getParsedBody(); for both of them. I used blow sample code:

<?php
require 'vendor/autoload.php';

$server = Zend\Diactoros\Server::createServer(
    function ($request, $response, $done) {
        $response->getBody()->write(json_encode($request->getParsedBody()));
    },
    $_SERVER,
    $_GET,
    $_POST,
    $_COOKIE,
    $_FILES
);

$server->listen();
Wikiki commented 6 years ago

Thanks, I'll try and let you know. That's the kind of code I've used without success. But maybe it ok now.

Wikiki commented 6 years ago

Late feedback....sorry. but it's perfectly work today. So you can close this issue. Thanks for your help