Skip to content

josecelano/axum-server-timeout

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

16 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Example Axum-server with timeouts

Testing

Related to:

I'm trying to setup axum-server with a timeout.

The timeout I want to set is for the time the server is waiting for a request after opening a connection.

This example set a timeout in the server for sending the headers, by simulating a slow client.

The goal is to just open a connection without sending any requests. The server should close the connection after a while.

I've added other server implementations using other frameworks to also check their behavior.

It only works for ActixWeb so far.

ActixWeb returns a 408 Request Timeout for the first request and panics for the second one.

Connected to the server: http://127.0.0.1:3000!
Sleeping 15 seconds ...
Client read timeout: Ok(Some(120s))
Client write timeout: Ok(Some(120s))
New request ...
Response OK: 107 bytes
HTTP/1.1 408 Request Timeout
content-length: 0
connection: close
date: Wed, 17 Apr 2024 17:18:43 GMT


New request ...
thread 'main' panicked at examples/client.rs:53:10:
Failed to write to stream: Os { code: 32, kind: BrokenPipe, message: "Broken pipe" }
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Client

There is a client example that waits some seconds and then makes two requests.

  • First, the client waits for some seconds to test if the server closes the connection.
  • The first request is a normal GET request to test the connection to the server.
  • The second request is a slow request to test server timeout. The timeout for sending the request headers.

Run the client:

$ cargo run --example client
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.02s
     Running `target/debug/examples/client`
Connected to the server: http://127.0.0.1:3000!
Client read timeout: Ok(Some(120s))
Client write timeout: Ok(Some(120s))
New request ...
Response OK: 130 bytes
HTTP/1.1 200 OK
content-type: text/plain; charset=utf-8
content-length: 13
date: Wed, 17 Apr 2024 11:07:41 GMT

Hello. world!
New slow request ...
thread 'main' panicked at examples/client.rs:63:14:
Failed to write to stream: Os { code: 104, kind: ConnectionReset, message: "Connection reset by peer" }
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

You can comment the "slow" request line in the client:

// send_request_slowly(&mut stream, request.as_bytes()).await;

To check what happens if the client is idle without sending any requests.

Axum-server

Run the server:

cargo run --example axum_server
Starting server on: http://127.0.0.1:3000 ...
Server bound to address: http://127.0.0.1:3000
New request ...

The patch proposed here seems to work partially. It closes the connection but it does not return a 408 Request Timeout response.

The client output with ActixWeb server:

Connected to the server: http://127.0.0.1:3000!
Sleeping 15 seconds without sending any requests ...
Send request ... response size: 107 bytes
HTTP/1.1 408 Request Timeout
content-length: 0
connection: close
date: Thu, 18 Apr 2024 15:26:51 GMT

thread 'main' panicked at examples/client.rs:43:14:
called `Result::unwrap()` on an `Err` value: Os { code: 32, kind: BrokenPipe, message: "Broken pipe" }
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

The client output with Axum-server:

Connected to the server: http://127.0.0.1:3000!
Sleeping 15 seconds without sending any requests ...
Send request ... response size: 130 bytes
HTTP/1.1 200 OK
content-type: text/plain; charset=utf-8
content-length: 13
date: Fri, 05 Jul 2024 12:26:57 GMT

Hello. world!
thread 'main' panicked at examples/client.rs:33:14:
called `Result::unwrap()` on an `Err` value: Os { code: 104, kind: ConnectionReset, message: "Connection reset by peer" }
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

The client output with patched Axum-server:

Connected to the server: http://127.0.0.1:3000!
Sleeping 15 seconds without sending any requests ...
Send request ... no response
thread 'main' panicked at examples/client.rs:45:14:
called `Result::unwrap()` on an `Err` value: Os { code: 32, kind: BrokenPipe, message: "Broken pipe" }
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Rocket

Run the server:

ROCKET_KEEP_ALIVE=1 ROCKET_PORT=3000 cargo run --example rocket_server
🔧 Configured for debug.
   >> address: 127.0.0.1
   >> port: 3000
   >> workers: 32
   >> max blocking threads: 512
   >> ident: Rocket
   >> IP header: X-Real-IP
   >> limits: bytes = 8KiB, data-form = 2MiB, file = 1MiB, form = 32KiB, json = 1MiB, msgpack = 1MiB, string = 8KiB
   >> temp dir: /tmp
   >> http/2: true
   >> keep-alive: 1s
   >> tls: disabled
   >> shutdown: ctrlc = true, force = true, signals = [SIGTERM], grace = 2s, mercy = 3s
   >> log level: normal
   >> cli colors: true
📬 Routes:
   >> (hello) GET /
📡 Fairings:
   >> Shield (liftoff, response, singleton)
🛡️ Shield:
   >> X-Frame-Options: SAMEORIGIN
   >> X-Content-Type-Options: nosniff
   >> Permissions-Policy: interest-cohort=()
🚀 Rocket has launched from http://127.0.0.1:3000
GET /:
   >> Matched: (hello) GET /
   >> Outcome: Success(200 OK)
   >> Response succeeded.

Actix Web

Run the server:

cargo run --example actix_web_server
Starting server on: http://127.0.0.1:3000 ...

Mitigating Slowloris DoS Attack with proxies

I'm you are using a proxy (Nginx or Apache) it seems you can mitigate this attack with the proxy configuration:

About

A example configuration for axum-server with timeouts

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages