klein / klein.php

A fast & flexible router
MIT License
2.66k stars 290 forks source link

Grab JSON from response after POST? #347

Open kaiwetlesen opened 7 years ago

kaiwetlesen commented 7 years ago

Hi, What trickery do I need to do to grab JSON data out of a POST request? It does not seem that the data comes in on $request->parameters() as that returns a completely empty collection. What am I doing wrong? I'm sure that's what it is.

bmd commented 7 years ago

Here's a pattern I've used

<?php
// in bootstrap.php
$app->register('contentParser', function () use ($request) {
    /** @var $request \Klein\Request */
    // this can be literally any factory that will return the json parser
    return \App\Http\Parsers\RequestParserFactory::make($request->headers()->get('Content-Type'));
});

if (in_array($request->method(), ['PUT', 'POST', 'PATCH'])) {
    $request->paramsPost()->merge($app->contentParser->parse($request->body()));
}
<?php
// the parser itself, returned by a factory, or just something you hardcode

namespace App\Http\Parsers

use App\Exceptions\InvalidRequestException

class JsonRequestParser extends AbstractRequestParser
{

    /**
     * Parse a json-encoded request body to an array
     * of parameters.
     *
     * @param  string $body
     * @return array
     * @throws InvalidRequestException
     */
    public function parse($body)
    {
        if (!$body) {
            return $body;
        }

        $decoded = json_decode($body, true);

        if (json_last_error() === JSON_ERROR_NONE) {
            return $decoded;
        }

        Log::error("Invalid json request body: {$body}");
        throw new InvalidRequestException("Request content-type was declared as JSON, but could not decode request body as valid JSON. Error: " . json_last_error_msg());
    }
}