rewrk icon indicating copy to clipboard operation
rewrk copied to clipboard

rewrk to send origin-form URL in HTTP request line

Open mleonhard opened this issue 6 months ago • 0 comments

Hi David, Thanks for making rewrk. I wrote a web server (servlin) and I'm adding it to https://github.com/programatik29/rust-web-benchmarks which uses rewrk. The benchmark runs essentially rewrk -c 1 -d 1s -h http://127.0.0.1:3000/ but the requests are failing. I tracked down the root cause.

RFC 7230 says that ordinary HTTP requests must use the /path?query part of the URL, excluding the http://host part:

5.3.1. origin-form

The most common form of request-target is the origin-form.

origin-form    = absolute-path [ "?" query ]

When making a request directly to an origin server, other than a CONNECT or server-wide OPTIONS request (as detailed below), a client MUST send only the absolute path and query components of the target URI as the request-target. If the target URI's path component is empty, the client MUST send "/" as the path within the origin-form of request-target. A Host header field is also sent, as defined in Section 5.4.

For example, a client wishing to retrieve a representation of the resource identified as

 http://www.example.org/where?q=now

directly from the origin server would open (or reuse) a TCP connection to port 80 of the host "www.example.org" and send the lines:

GET /where?q=now HTTP/1.1
Host: www.example.org

followed by the remainder of the request message.

It looks like we're sending the absolute-form url http://127.0.0.1:3000/ when we want to send the origin-form url /. We're also omitting the port number in the Location header.

Send the request:

% rewrk -c 1 -d 1s -h http://127.0.0.1:3000/
Beginning round 1...
Benchmarking 1 connections @ http://127.0.0.1:3000/ for 1 second(s)
No requests completed successfully

%

Capture the request:

% nc -l 3000
GET http://127.0.0.1:3000/ HTTP/1.1
host: 127.0.0.1

%

The fix would go in crate::http::benchmark where we set http::Request.uri: https://github.com/lnx-search/rewrk/blob/d811b98a60f227cac7da75bb665cd94d24b389d9/src/http/mod.rs#L112-L115

I think the fix would be something like this:

let mut uri_parts = user_input.into_parts();
uri_parts.scheme = None;
uri_parts.authority = None;
*request.uri_mut() = uri_parts.into();

Tangent: It's interesting that all of the popular Rust HTTP servers accept such invalid HTTP requests.

Cheers, Michael

mleonhard avatar Jun 23 '25 20:06 mleonhard