roadrunner-php / laravel-bridge

🌉 RoadRunner ⇆ Laravel bridge 🇺🇦❤️
https://roadrunner.dev/docs/integration-laravel
MIT License
372 stars 25 forks source link

Route with method PUT not working #130

Closed Rev8Crew closed 1 year ago

Rev8Crew commented 1 year ago

Describe the bug

So my route code is Route::put('test', static fn () => \rr\dd( request()::getHttpMethodParameterOverride(), request()->method() ));

Expected behaviour

When I try to request a /test url with method POST and body params with "_method": "PUT" I get error that showed on screenshot image

Actual behaviour

The request must return dd response

Steps to reproduce

Use same route

System information

Please, complete the following information:

Key Value
PHP version 8.2.1
Current package version v5.12.0
RoadRunner version 2.12.2
Environment docker-wsl

RoadRunner configuration file content

# ---------------------------------------------------------------------------------------------------
# WARNING! This file should be used ONLY for local application development. NOT for production usage!
# ---------------------------------------------------------------------------------------------------

# Hint: RR will replace any config options using reference to environment variables,
# eg.: `option_key: ${ENVIRONMENT_VARIABLE_NAME}`.

# RR configuration version
version: "2.7"

# Remote Procedures Calling (docs: https://roadrunner.dev/docs/beep-beep-rpc)
# Is used for connecting to RoadRunner server from your PHP workers.
rpc:
  # TCP address:port for listening.
  #
  # Default: "tcp://127.0.0.1:6001"
  listen: tcp://127.0.0.1:6001

# Application server settings (docs: https://roadrunner.dev/docs/php-worker)
server:
  # Worker starting command, with any required arguments.
  #
  # This option is required.
  command: "php ./vendor/bin/rr-worker start --relay-dsn unix:///var/run/rr/rr-relay.sock"

  ## Environment variables for the worker processes.
  ##
  ## Default: <empty map>
  #env:
  #  - SOME_KEY: "SOME_VALUE"
  #  - SOME_KEY2: "SOME_VALUE2"

  # Worker relay can be: "pipes", TCP (eg.: tcp://127.0.0.1:6001), or socket (eg.: unix:///var/run/rr-relay.sock).
  #
  # Default: "pipes"
  relay: "unix:///var/run/rr/rr-relay.sock"

  # Timeout for relay connection establishing (only for socket and TCP port relay).
  #
  # Default: 60s
  relay_timeout: 60s

# HTTP plugin settings.
http:
  # Host and port to listen on (eg.: `127.0.0.1:8080`).
  #
  # This option is required.
  address: 0.0.0.0:8080

  # HTTP access logs
  #
  # Default: false
  access_logs: true

  # Maximal incoming request size in megabytes. Zero means no limit.
  #
  # Default: 0
  max_request_size: 256

  # Middlewares for the http plugin, order is important. Allowed values is: "headers", "gzip".
  #
  # Default value: []
  middleware: ["static", "headers", "gzip"]

  # File uploading settings.
  uploads:
    # Directory for file uploads. Empty value means to use $TEMP based on your OS.
    #
    # Default: ""
    dir: "/tmp"

    # Deny files with the following extensions to upload.
    #
    # Default: [".php", ".exe", ".bat"]
    forbid: [".php", ".exe", ".bat", ".sh"]

  # Settings for "headers" middleware (docs: https://roadrunner.dev/docs/http-headers).
  headers:
    # Automatically add headers to every response.
    #
    # Default: <empty map>
    response:
      X-Powered-By: "RoadRunner"

  # Settings for serving static content (docs: https://roadrunner.dev/docs/http-static).
  static:
    # Path to the directory with static assets.
    #
    # This option is required.
    dir: "/app/public"

    # File extensions to forbid.
    #
    # Default: []
    forbid: [".htaccess", ".php"]

    # Automatically add headers to every response.
    #
    # Default: <empty map>
    response:
      X-Powered-By: "RoadRunner"

  # Workers pool settings.
  pool:
    # How many worker processes will be started. Zero (or nothing) means the number of logical CPUs.
    #
    # Default: 0
    num_workers: 0

    # Maximal count of worker executions. Zero (or nothing) means no limit.
    #
    # Default: 0
    max_jobs: 64

    # Timeout for worker allocation. Zero means no limit.
    #
    # Default: 60s
    allocate_timeout: 10s

    # Timeout for worker destroying before process killing. Zero means no limit.
    #
    # Default: 60s
    destroy_timeout: 10s

    # Supervisor is used to control http workers (previous name was "limit", docs:
    # https://roadrunner.dev/docs/php-limit). "Soft" limits will not interrupt current request processing. "Hard"
    # limit on the contrary - interrupts the execution of the request.
    supervisor:
      # Maximal worker memory usage in megabytes (soft limit). Zero means no limit.
      #
      # Default: 0
      max_worker_memory: 128

      # Maximal job lifetime (hard limit). Zero means no limit.
      #
      # Default: 0s
      exec_ttl: 60s
#
#  # SSL (Secure Sockets Layer) settings (docs: https://roadrunner.dev/docs/http-https).
#  ssl:
#    # Host and port to listen on (eg.: `127.0.0.1:443`).
#    #
#    # Default: ":443"
#    address: 0.0.0.0:8443
#
#    # Automatic redirect from http:// to https:// schema.
#    #
#    # Default: false
#    redirect: false
#
#    # Path to the cert file. This option is required for SSL working.
#    #
#    # This option is required.
#    cert: /etc/ssl/certs/selfsigned.crt
#
#    # Path to the cert key file.
#    #
#    # This option is required.
#    key: /etc/ssl/private/selfsigned.key

  # HTTP/2 settings.
  http2:
    # HTTP/2 over non-encrypted TCP connection using H2C.
    #
    # Default: false
    h2c: false

    # Maximal concurrent streams count.
    #
    # Default: 128
    max_concurrent_streams: 128

## Application metrics in Prometheus format (docs: https://roadrunner.dev/docs/beep-beep-metrics). Drop this section
## for this feature disabling.
#metrics:
#  # Prometheus client address (path /metrics added automatically).
#  #
#  # Default: "127.0.0.1:2112"
#  address: 127.0.0.1:8081

# Health check endpoint (docs: https://roadrunner.dev/docs/beep-beep-health). If response code is 200 - it means at
# least one worker ready to serve requests. 500 - there are no workers ready to service requests.
# Drop this section for this feature disabling.
status:
  # Host and port to listen on (eg.: `127.0.0.1:2114`). Use the following URL: http://127.0.0.1:2114/health?plugin=http
  # Multiple plugins must be separated using "&" - http://127.0.0.1:2114/health?plugin=http&plugin=rpc where "http" and
  # "rpc" are active (connected) plugins.
  #
  # This option is required.
  address: 127.0.0.1:8082

  # Response status code if a requested plugin not ready to handle requests
  # Valid for both /health and /ready endpoints
  #
  # Default: 503
  unavailable_status_code: 503

# Automatically detect PHP file changes and reload connected services (docs:
# https://roadrunner.dev/docs/beep-beep-reload). Drop this section for this feature disabling.
reload:
  # Sync interval.
  #
  # Default: "1s"
  interval: 1s

  # Global patterns to sync.
  #
  # Default: [".php"]
  patterns: [".php"]

  # List of included for sync services (this is a map, where key name is a plugin name).
  #
  # Default: <empty map>
  services:
    http:
      # Directories to sync. If recursive is set to true, recursive sync will be applied only to the directories in
      # "dirs" section. Dot (.) means "current working directory".
      #
      # Default: []
      dirs: ["."]

      # Recursive search for file patterns to add.
      #
      # Default: false
      recursive: true

      # Ignored folders.
      #
      # Default: []
      ignore: []

# RoadRunner internal container configuration (docs: https://github.com/spiral/endure).
endure:
  # Logging level. Possible values: "debug", "info", "warning", "error", "panic", "fatal".
  #
  # Default: "error"
  log_level: error

Package configuration file content

<?php

use Spiral\RoadRunner\Environment\Mode;
use Spiral\RoadRunnerLaravel\Defaults;
use Spiral\RoadRunnerLaravel\Events;
use Spiral\RoadRunnerLaravel\Listeners;

return [
    /*
    |--------------------------------------------------------------------------
    | Force HTTPS Schema Usage
    |--------------------------------------------------------------------------
    |
    | Set this value to `true` if your application uses HTTPS (required for
    | correct links generation, for example).
    |
    */

    'force_https' => (bool) env('APP_FORCE_HTTPS', false),

    /*
    |--------------------------------------------------------------------------
    | Event Listeners
    |--------------------------------------------------------------------------
    |
    | Worker provided by this package allows to interacts with request
    | processing loop using application events.
    |
    | Feel free to add your own event listeners.
    |
    */

    'listeners' => [
        Events\BeforeLoopStartedEvent::class => [
            ...Defaults::beforeLoopStarted(),
        ],

        Events\BeforeLoopIterationEvent::class => [
            ...Defaults::beforeLoopIteration(),
        ],

        Events\BeforeRequestHandlingEvent::class => [
            ...Defaults::beforeRequestHandling(),
            Listeners\InjectStatsIntoRequestListener::class,
        ],

        Events\AfterRequestHandlingEvent::class => [
            ...Defaults::afterRequestHandling(),
        ],

        Events\AfterLoopIterationEvent::class => [
            ...Defaults::afterLoopIteration(),
            Listeners\RunGarbageCollectorListener::class, // keep the memory usage low
            // Listeners\CleanupUploadedFilesListener::class, // remove temporary files
        ],

        Events\AfterLoopStoppedEvent::class => [
            ...Defaults::afterLoopStopped(),
        ],

        Events\LoopErrorOccurredEvent::class => [
            ...Defaults::loopErrorOccurred(),
            Listeners\SendExceptionToStderrListener::class,
            Listeners\StopWorkerListener::class,
        ],
    ],

    /*
    |--------------------------------------------------------------------------
    | Containers Pre Resolving / Clearing
    |--------------------------------------------------------------------------
    |
    | The bindings listed below will be resolved before the events loop
    | starting. Clearing a binding will force the container to resolve that
    | binding again when asked.
    |
    | Feel free to add your own bindings here.
    |
    */

    'warm' => [
        ...Defaults::servicesToWarm(),
    ],

    'clear' => [
        ...Defaults::servicesToClear(),
        // 'auth', // is not required for Laravel >= v8.35
    ],

    /*
    |--------------------------------------------------------------------------
    | Reset Providers
    |--------------------------------------------------------------------------
    |
    | Providers that will be registered on every request.
    |
    | Feel free to add your service-providers here.
    |
    */

    'reset_providers' => [
        ...Defaults::providersToReset(),
        // Illuminate\Auth\AuthServiceProvider::class,             // is not required for Laravel >= v8.35
        // Illuminate\Pagination\PaginationServiceProvider::class, // is not required for Laravel >= v8.35
    ],

    /*
    |--------------------------------------------------------------------------
    | Worker Classes
    |--------------------------------------------------------------------------
    |
    | Here you can override the worker class for processing different kinds of
    | jobs, that received from the RoadRunner daemon. The key is a worker mode.
    |
    */

    'workers' => [
        Mode::MODE_HTTP => \Spiral\RoadRunnerLaravel\Worker::class,
        // Mode::MODE_JOBS => ...,
        // Mode::MODE_TEMPORAL => ...,
    ],
];
tarampampam commented 1 year ago

I think this occurs because of:

https://github.com/symfony/http-foundation/blob/b50f5e281d722cb0f4c296f908bacc3e2b721957/Request.php#L1216-L1218

and:

https://github.com/roadrunner-php/laravel-bridge/blob/8f97551ed95086fb4161b1e3d7d13b9b5877ca04/src/Defaults.php#L35

Please, provide more information about "what exactly you determine as a bug", and reopen this issue, please.

Rev8Crew commented 1 year ago

I think the bug is fact that when I use roadrunner default laravel functionality doesn't work properly. The question is why Listeners\EnableHttpMethodParameterOverrideListener::class doesn't set $httpMethodParameterOverride = true in some requests which I demonstrated earlier