Notes on Using JavaScript Fetch with F3

78 views
Skip to first unread message

ethanpil

unread,
Nov 24, 2022, 9:04:40 PM11/24/22
to Fat-Free Framework
I have been wrangling with Fat Free and Fetch for the past couple of hours. I think sharing these notes will be helpful for others who may have the same issues. I also think the documentation might need to addresses this, and perhaps even the core framework might want to adjust for this. 

When POSTing data with the JS Fetch API, F3 will not populate the POST global unless the content type is  application/x-www-form-urlencoded

An example with BLANK $f3->get('POST')

        const requestOptions = {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ sig: sigImage })
        };
        fetch("/api/endpoint", requestOptions)
            .then(response => response.json())
            .then(data => console.log(data) );           
        });


An example with working $f3->get('POST')

        const requestOptions = {
            method: 'POST',
            headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
            body: JSON.stringify({ sig: sigImage })
        };
        fetch("/api/endpoint", requestOptions)
            .then(response => response.json())
            .then(data => console.log(data) );           
        });

Actually its a limitation (feature?) of PHP and anything that is POSTed that isnt "x-www-form-urlencoded" can't be reacd without  $x =  file_get_contents("php://input")

I recommend reading this page for more information:  https://codepen.io/dericksozo/post/fetch-api-json-php

As I mentioned I think there can be a significant value add to the framework (for tiny price) to automatically handle these kinds of requests as they are only getting more common... (Or at least a note in the official documentation.)

Any thoughts? Thanks for a great Framework providing decades of productivity for many of us!

ved

unread,
Nov 24, 2022, 11:43:17 PM11/24/22
to Fat-Free Framework
Hi,

This is by design I believe since you may access requests that are not x-www-form-urlencoded by accessing $f3->get('BODY'), so if you're using json something line "$var = json_decode($f3->get('BODY'),true)" should get you essentially the same data as on the post array.

Cheers

ethanpil

unread,
Nov 25, 2022, 12:30:26 PM11/25/22
to Fat-Free Framework
Unfortunately  $f3->get('BODY') does not provide access to  requests that are not x-www-form-urlencoded, hence my entire note above.

ved

unread,
Nov 25, 2022, 1:40:14 PM11/25/22
to Fat-Free Framework
Hey,

Well, it works correctly on my end and I've used it many times with many different API's

Here's a quick test if it helps:

<?php

require 'vendor/autoload.php';
$f3 = \Base::instance();

$f3->route('GET /',
    function() {
        echo <<<END
        <button onclick="test()">Test</button>
        <script>
        function test() {

            const requestOptions = {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ testkey: 'testval' })
            };
            fetch("/test", requestOptions)

                .then(response => response.json())
                .then(data => console.log(data));
           
        }        
        </script>
        END;
    }
);

$f3->route('POST /test',
    function($f3) {        
        // decode json from client
        $params = json_decode($f3->get('BODY'), true);
        // add a parameter
        $params['response'] = "this came from server";
        // reply back
        header('Content-type: application/json');
        echo json_encode($params);
    }
);
$f3->run();



The above runs correctly on my setup, and pressing the test button will correctly send and receive data from the post route.

Hope it helps,
Cheers

ikkez

unread,
Dec 3, 2022, 5:15:42 PM12/3/22
to Fat-Free Framework
I also noticed this a while ago and I must say, it's something that I would have expected to be handled automatically.. we should probably add something like: if it's application/json and a POST request, just parse BODY automatically and populate POST var with it.

ved

unread,
Dec 4, 2022, 9:18:39 AM12/4/22
to Fat-Free Framework
Hey,

Not sure if that should be done automatically, although I do understand the intention.

But as it is now, I believe is the correct "standard" behavior for the framework according to specs. That is, we expect GET variables in the GET array and POSTED variables in the POST array. 

If we now automatically json decode the body and add them to the post array we'll get this non-standard behavior that, although it may be what most people will want to do (that is, get the json parsed as a usable array), it may not be always necessary as the endpoint may not want to do the decoding and instead (for example) pass the request down the infra-line or between internal servers to a message queue, loggers, code-based load balancing, etc.

I would suggest perhaps introducing some sort of PARSEBODY framework variable to enable this automatic json parsing so that the default behavior remains the same. Or perhaps add JSON to go along with GET, POST, REQUEST and decode it in there. 

Just my $0.02 ;-)

Cheers

ethanpil

unread,
Nov 27, 2023, 4:48:20 PM11/27/23
to Fat-Free Framework
Following up on this... Coming up on another project and will need to use a similar process. Wondering if we have any movement. Looks like not...

ved

unread,
Nov 27, 2023, 5:58:15 PM11/27/23
to Fat-Free Framework
Hey,

Most js apps and api's don't really work with posted form data and just pass straight json asynchronously so it's largely an unnecessary step.
If you want form data in the POST array, you can pass the necessary content-type header as you've shown on your first post or just json_decode the BODY variable.
A toggle could be useful but it's not really that much of a show-stopper I think, unless I misunderstood your initial issue (?)

Cheers

ethanpil

unread,
Nov 27, 2023, 6:51:46 PM11/27/23
to Fat-Free Framework
I was hoping to hear something more along the lines of the approach proposed by  @Ikkez
:)

ved

unread,
Nov 27, 2023, 8:47:31 PM11/27/23
to Fat-Free Framework
Sure,

It's not a part of the framework but you can probably implement it yourself, it's just something like this (untested):


if($f3->get('SERVER.CONTENT_TYPE') == 'application/json' && $f3->get('VERB') == 'POST') {
    $f3->set('POST', json_decode($f3->get('BODY'), true));
}


Cheers

Reply all
Reply to author
Forward
0 new messages