roadrunner-server / roadrunner

🤯 High-performance PHP application server, process manager written in Go and powered with plugins
https://docs.roadrunner.dev
MIT License
7.86k stars 408 forks source link

[bug] Missing POST data with header "Content-Type" that includes ";charset=..." #112

Closed tarampampam closed 5 years ago

tarampampam commented 5 years ago
App Version
RR v1.3.3
PHP v7.2.14
Laravel Framework v5.7.24

OS: Linux Mint 18.3

Short description

Using RR data in POST request is not available, if Content-Type header includes charset declaration like ...;charset=UTF-8.

How reproduce this case

$ composer create-project laravel/laravel rr-post-test && cd rr-post-test
$ composer require spiral/roadrunner symfony/psr-http-message-bridge
$ touch worker.php .rr.local.yml

app/Http/Kernel.php:

    /**
     * The application's route middleware groups.
     *
     * @var array
     */
    protected $middlewareGroups = [
        'web' => [
            // ...
            //\App\Http\Middleware\VerifyCsrfToken::class, // <-- COMMENT this line
            // ...
        ],
    ];

.rr.local.yml:

rpc:
  enable: true
  listen: tcp://127.0.0.1:6001

http:
  address: 0.0.0.0:7000
  maxRequest: 128
  uploads:
    forbid: [".php", ".exe", ".bat"]
  workers:
    command: "php worker.php" # Allowed flags - `--force-https`, `--not-reset-connections`
    relay: "pipes"
    pool:
      numWorkers: 2
      maxJobs: 1
      allocateTimeout: 60
      destroyTimeout:  60

static:
  enable: true
  dir: "public"
  forbid: [".php"]

worker.php:

#!/usr/bin/env php
<?php

use Illuminate\Contracts\Http\Kernel;
use Illuminate\Foundation\Application;
use Symfony\Bridge\PsrHttpMessage\Factory\DiactorosFactory;
use Symfony\Bridge\PsrHttpMessage\Factory\HttpFoundationFactory;

\ini_set('display_errors', 'stderr');
require __DIR__ . '/vendor/autoload.php';

global $argv, $_SERVER;

$relay                 = new Spiral\Goridge\StreamRelay(STDIN, STDOUT);
$psr7                  = new Spiral\RoadRunner\PSR7Client(new Spiral\RoadRunner\Worker($relay));
$httpFoundationFactory = new HttpFoundationFactory;

/** @var Application $app */
$app = require __DIR__ . '/bootstrap/app.php';

/** @var Kernel $kernel */
$kernel = $app->make(Kernel::class);

while ($req = $psr7->acceptRequest()) {
    try {
        $request = Illuminate\Http\Request::createFromBase($httpFoundationFactory->createRequest($req));

        $response = $kernel->handle($request);

        $psr7factory  = new DiactorosFactory;
        $psr7response = $psr7factory->createResponse($response);
        $psr7->respond($psr7response);

        $kernel->terminate($request, $response);

        \gc_collect_cycles(); // keep the memory low (this will slow down your application a bit)
    } catch (\Throwable $e) {
        $psr7->getWorker()->error((string) $e);
    }
}

routes/web.php:

<?php

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;

Route::post('/post-test', function (Request $request) {
    return 'val = ' . $request->input('val') . ' val2 = ' . $request->input('val2') . PHP_EOL;
});

Now, open two terminals and start 2 servers (rr on 7000 port and "native" serve on 8000):

$ rr serve -v -d -c ./.rr.local.yml
$ ./artisan serve

After that lets try to send some request to the "native" server:

$ curl -Ss -X POST -d 'val=1%4023&val2=a' -H 'Content-Type:application/x-www-form-urlencoded; charset=UTF-8' http://127.0.0.1:8000/post-test
val = 1@23 val2 = a

All is ok, we see all sended values! Then, try make same request to the rr:

$ curl -Ss -X POST -d 'val=1%4023&val2=a' -H 'Content-Type:application/x-www-form-urlencoded; charset=UTF-8' http://127.0.0.1:7000/post-test
val =  val2 = 

And as we can see - nothing is here.

In rr terminal all looks fine:

DEBU[0000] [rpc]: started                               
DEBU[0000] [http]: started                              
INFO[0008] 127.0.0.1 {56.0ms} 200 POST http://127.0.0.1:7000/post-test 

Update

$ curl -Ss -X POST -d 'val=1%4023&val2=a' -H 'Content-Type:application/x-www-form-urlencoded' http://127.0.0.1:7000/post-test 
val = 1@23 val2 = a

$ curl -Ss -X POST -d 'val=1%4023&val2=a' -H 'Content-Type:application/x-www-form-urlencoded;' http://127.0.0.1:7000/post-test
val =  val2 = 

$ curl -Ss -X POST -d 'val=1%4023&val2=a' -H 'Content-Type:application/x-www-form-urlencoded;;' http://127.0.0.1:7000/post-test
val =  val2 = 

I think - trouble with headers that contains ; char (on RR daemon side).

ps. Sorry for my english

Alex-Bond commented 5 years ago

@tarampampam try to use my integration https://github.com/UPDG/roadrunner-laravel Ping me if problem persists.

tarampampam commented 5 years ago

@Alex-Bond I tried, but problem persists

Alex-Bond commented 5 years ago

@tarampampam got it. I will look into it soon. Sorry about that.

tarampampam commented 5 years ago

Also, if charset=... is not presens - all works fine:

$ curl -Ss -X POST -d 'val=1%4023&val2=a' -H 'Content-Type:application/x-www-form-urlencoded' http://127.0.0.1:7000/post-test 
val = 1@23 val2 = a

$ curl -Ss -X POST -d 'val=1%4023&val2=a' -H 'Content-Type:application/x-www-form-urlencoded;' http://127.0.0.1:7000/post-test
val =  val2 = 

$ curl -Ss -X POST -d 'val=1%4023&val2=a' -H 'Content-Type:application/x-www-form-urlencoded;;' http://127.0.0.1:7000/post-test
val =  val2 = 

I think - trouble with headers that contains ; char (on RR daemon side).

Alex-Bond commented 5 years ago

@tarampampam @wolfy-j will release new version soon.

tarampampam commented 5 years ago

Wow! You are coding machines! :D

/me waiting for the release for testing

wolfy-j commented 5 years ago

Not sure why did I close this issue earlier but it's fixed in 1.3.4

tarampampam commented 5 years ago

Yeah! It works for me now! @Alex-Bond @wolfy-j - great thx!