reactphp / http

Event-driven, streaming HTTP client and server implementation for ReactPHP.
https://reactphp.org/http/
MIT License
744 stars 143 forks source link

URI Behind Reverse Proxy Incorrect Scheme #503

Closed ellisonpatterson closed 8 months ago

ellisonpatterson commented 1 year ago

When I put the HTTP server behind an nginx reverse proxy with SSL enabled, the Request URI is showing a scheme of http.

I do not have this issue with Guzzle, and I'm wondering why ReactPHP HTTP is not using the correct scheme.

Thank you!

SimonFrings commented 1 year ago

Hey @ellisonpatterson, I'm not quite sure if this is your case here, but the presence of the http scheme here actually makes sense. When a client wants to send a request to your server, it first reaches nginx and should use a secure connection for this. The communication between the nginx reverse proxy and HTTP server doesn't require an additional secure connection since they are often running on the same system (eliminating the need for a TLS handshake, etc.). Since the HTTP server only communicates directly with nginx in this setup, it only sees the address of the nginx, which is why you see the http scheme when the request comes in.

If you want to pass on the original address of your client, you can either use the X-Forwarded-For request header to address the originating IP address of a client connecting to your server through your proxy, or the X-Forwarded-Proto request header to identify the protocol (HTTP or HTTPS) of the client.

I hope this helps :+1:

I believe this should answer your question, so I will close this ticket for now. We can reopen this if you need further help with this. If you do need to reopen the ticket, please provide some information about the steps you've taken so far, what worked and what didn't.

ellisonpatterson commented 1 year ago

The issue is that I am using Twilio validation as a middleware (https://www.twilio.com/docs/usage/security#validating-requests) and the URL specified has HTTPS as the scheme, but the RingCentral URI builder specifies HTTP which is not what what was requested, causing the Twilio request validation to fail. When I use Guzzle's PSR7 implementation, it specifies HTTPS in the URI builder as expected. I'm wondering then why the ReactPHP HTTP PSR7 implementation differs from the Guzzle one.

The problem is that it works everywhere else, but not with ReactPHP HTTP.

WyriHaximus commented 1 year ago

@ellisonpatterson Is there a gist you can share that reproduces this issue so we can have a deeper look at what is happening?

ellisonpatterson commented 1 year ago
<?php

define('ABSPATH', dirname(__FILE__));
require ABSPATH . '/vendor/autoload.php';

use Psr\Http\Message\ServerRequestInterface;
use React\Http\Message\Response;
use React\Socket\SocketServer;
use React\Http\HttpServer;

$server = new HttpServer(
    fn (ServerRequestInterface $request) => Response::plainText((string) $request->getUri())
);

$socket = new SocketServer('0.0.0.0:1111');
$server->listen($socket);

I tested with nginx, but ngrok experiences the same issue. ngrok http 1111

And it shows the entrypoint URL as this: https://65bc-xx-xx-xx-xx.ngrok-free.app -> http://localhost:1111

I get the following response when visiting the ngrok HTTPS url: http://65bc-xx-xx-xx-xx.ngrok-free.app/

And since this is (AFAIK) the only place to get the URL used in the request, the Twilio validator won't work since it hashed it with the https scheme.

SimonFrings commented 8 months ago

@ellisonpatterson Thanks for the additional information :+1:

I'm still convinced this can be resolved by using the the X-Forwarded-For request header and the X-Forwarded-Proto request header to identify the protocol (HTTP or HTTPS) of the original client.

ReactPHP may differ here from other projects, but with our work on the upcoming v3 we also want to look into our current PSR-7 implementation and some things might change. For example, we want get rid if our RingCentral dependency and maybe look into working on our own PSR-7 integration. Not completely sure if this will be a v3 topic or if we integrate this in an upcoming v1.10.0. The roadmap for ReactPHP HTTP v3 is still outstanding, but will go live soon.

The question for this should be answered, this is why I consider this ticket as closed. We can use the ReactPHP discussions to discuss any additional feature requests for improvements.