Can't get GET/DELETE parameters inside middleware (POST and PUT works fine)

Hi,

I’m building a project using slim 4 and everything is working fine (routes, controllers, database connections) and so I’ve started to implement a custom made authentication service in which the user is given a valid hash and should provide it in every request (GET, POST, PUT, DELETE).

Here is an example of the middleware that is implemented:

<?php

namespace App\Middleware;

use Psr\Http\Message\ResponseFactoryInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use App\Domain\User\Service\AuthenticationValidationService;

final class AuthenticationMiddleware implements MiddlewareInterface
{
    private ResponseFactoryInterface $responseFactory;
    private AuthenticationValidationService $service;

    public function __construct(ResponseFactoryInterface $responseFactory, AuthenticationValidationService $service)
    {
        $this->responseFactory = $responseFactory;
        $this->service = $service;
    }

    public function process(
        ServerRequestInterface $request,
        RequestHandlerInterface $handler
    ): ResponseInterface {
            $data = (array)$request->getParsedBody();
            
            $hash = $data['hash'];
            $auth = $this->service->validateHash($hash);            
            if ($auth) {
               //TODO: append userId associated with the hash to the request
                return $handler->handle($request);
            } else {
                $response = $this->responseFactory->createResponse();
                $response->getBody()->write('Unauthorized');
                return $response->withStatus(401);
            }
    }
}

this is how its registered in my routes:

<?php

// Define app routes

use Slim\App;
use Slim\Routing\RouteCollectorProxy;

return function (App $app) {
    // Redirect to Swagger documentation
    $app->get('/', \App\Action\Home\HomeAction::class)->setName('home');

    // API
    $app->group(
        '/api',
        function (RouteCollectorProxy $app) {
            $app->get('/user/{user_id}', \App\Action\User\UserReaderAction::class);
            $app->post('/user', \App\Action\User\UserCreatorAction::class);
            $app->put('/user/{user_id}', \App\Action\User\UserUpdaterAction::class);
            $app->delete('/user/{user_id}', \App\Action\User\UserDeleterAction::class);
        }
    )->add(\App\Middleware\AuthenticationMiddleware::class);

    $app->post('/api/user/login', \App\Action\User\UserLoginAction::class);
};

These are my middlewares:

<?php

use App\Middleware\ValidationExceptionMiddleware;
use Selective\BasePath\BasePathMiddleware;
use Slim\App;
use Slim\Middleware\ErrorMiddleware;

return function (App $app) {
    $app->addBodyParsingMiddleware();
    $app->add(ValidationExceptionMiddleware::class);
    $app->addRoutingMiddleware();
    $app->add(BasePathMiddleware::class);
    $app->add(ErrorMiddleware::class);
};

Consider that the function validateHash() returns true if the hash is valid and false otherwise. This function is working fine.

Everything works properly for POST and PUT.

But for GET and DELETE, $data = (array)$request->getParsedBody(); returns null.

  • example request that doesn’t work: …/api/user/1?hash=$2y$10$RK (GET)
  • example request that works: …/api/user/1 (PUT) + JSON
    {
    “hash” : “$2y$10$RKojluryIrPwyMdvNbxqNONVi0iQDhtWndHp8td/hkL1VhXcJJ7fi”,
    “last_name”: “admin”,
    “first_name”: “admin”
    }

What am I missing here? The main difference is that through GET/DELETE, parameters are passed inside the URL and POST/PUT are passed as json. Which is the appropriate way to read these request parameters regardless their method?

Furthermore, after validating the hash which is the better way to append the userId associated with the hash to the request before passing it to the handler?

Cheers!

As mentioned in the docs, the getParsedBody() method returns the parsed (form data, json) request (body) data from a POST request. A PUT request is actually not directly supported and needs a little bit more setup.

The GET and DELETE methods are using the query string for parameters. So in the case, you can get the query parameters as an associative array on the Request object using the $request->getQueryParams() method instead.