Actix Web is a powerful, pragmatic, and extremely fast web framework for Rust.

Last update: May 28, 2022

Actix Web

Actix Web is a powerful, pragmatic, and extremely fast web framework for Rust

crates.io Documentation Version MIT or Apache 2.0 licensed Dependency Status
build status codecov downloads Chat on Discord

Features

  • Supports HTTP/1.x and HTTP/2
  • Streaming and pipelining
  • Keep-alive and slow requests handling
  • Client/server WebSockets support
  • Transparent content compression/decompression (br, gzip, deflate)
  • Powerful request routing
  • Multipart streams
  • Static assets
  • SSL support using OpenSSL or Rustls
  • Middlewares (Logger, Session, CORS, etc)
  • Includes an async HTTP client
  • Runs on stable Rust 1.46+

Documentation

Example

Dependencies:

[dependencies]
actix-web = "3"

Code:

use actix_web::{get, web, App, HttpServer, Responder};

#[get("/{id}/{name}/index.html")]
async fn index(web::Path((id, name)): web::Path<(u32, String)>) -> impl Responder {
    format!("Hello {}! id:{}", name, id)
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| App::new().service(index))
        .bind("127.0.0.1:8080")?
        .run()
        .await
}

More examples

You may consider checking out this directory for more examples.

Benchmarks

One of the fastest web frameworks available according to the TechEmpower Framework Benchmark.

License

This project is licensed under either of

at your option.

Code of Conduct

Contribution to the actix-web repo is organized under the terms of the Contributor Covenant. The Actix team promises to intervene to uphold that code of conduct.

GitHub

https://github.com/actix/actix-web
Comments
  • 1. Project future

    I realized, a lot of people depends on actix. And it would be unfair to just delete repos. I promote @JohnTitor to project leader. He did very good job helping me for the last year. I hope new community of developers emerge. And good luck!

    Reviewed by fafhrd91 at 2020-01-20 13:46
  • 2. Connection not closed correctly

    Connection are not closed correctly by default What I means is: if you do a "netstat -ano" you will see connection list growing and growing. Not all old connection get closed.

    Tested with StaticFile handler ( HTTP2 or not ) on a website with ~20k+ daily users

    With the default config -> Not closed correctly With .keep_alive(None) -> Not closed correctly With .keep_alive(server::KeepAlive::Timeout(5)) -> All connections are closed correctly

    Initially detected in this ticket #426 but it was not the main issue

    Reviewed by neowutran at 2018-08-02 18:09
  • 3. StaticFile & memory leak

    Hi, I am playing a bit with rust/actix-web on my personal website. The code is very basic https://git.neowutran.ovh:8080/neowutran/Website/src/master/src/main.rs

      server::new(|| {
        App::new()
         // .middleware(middleware::Logger::default())
          .resource("/store_stats", |r| {
            r.method(Method::POST)
              .with_config(store_statistics, |config| {
                config.limit(MAX_SIZE_STATS);
              })
          })
        .resource("/store_packets", |r| {
          r.method(Method::POST)
            .with_config(store_packets, |config| {
                config.0.limit(MAX_SIZE_PACKET);
            })
        })
        .handler("/updates",StaticFiles::new("/home/gl0/updates/").unwrap().show_files_listing())
        .handler("/others",StaticFiles::new("/home/gl0/others/").unwrap().show_files_listing())
        .handler("/teraDB",StaticFiles::new("/home/gl0/teraDB/").unwrap().show_files_listing())
        .handler("/",StaticFiles::new("/home/http/neowutran/").unwrap().show_files_listing().index_file("index.html"))
      })
    

    I run 2 instance of this exact same code. One on port 443, one on port 8083

    On port 8083, only /store_packets and /store_stats are used. 0.2% of server memory, stable. Actively used ( ~thousands request by hours, gigabytes uploaded ). Ok.

    On port 443, only the StaticFiles handler are used: /updates, /others, /teraDB, / ( TLS + HTTP2 ) Very actively used (~15k user use the /updates to download things). When I launched it yesterday, it used 0.2% of server memory. Memory used increased over time. Now, after ~15h, it now use 10% of server memory. With the command netstat -ano, I see that a lot of connections (hundreds) are "ESTABLISHED" on the service. Maybe in the case of HTTP2 / TLS, some issues with connection not being released or something like that ? ( For the same thing with apache httpd, ~0.2% of server memory, stable )

    Thanks

    Reviewed by neowutran at 2018-07-27 07:04
  • 4. actix-web 1.0

    I am planing to move 0.7 to separate branch and move 1.0 to master in 1 week.

    Any thoughts, concerns?

    High level tasks:

    • [x] Move 0.7 to separate branch
    • [x] Move 1.0 to master
    • [x] actix-files tidy up #730
    • [x] Migration guide 0.7 -> 1.0
    • [x] Upgrade the book
    • [x] Upgrade example
    Reviewed by fafhrd91 at 2019-03-10 16:06
  • 5. Memory Leak on Actix 3.2.0

    I'm creating a simple API and put it under stress using loadtest. The API consumes 3MB when idling and not under stress. With the command: loadtest -c 1000 --rps 10000 http://localhost:4000/hello/world the memory consumption goes to ~100MB.

    Expected Behavior

    After the stress test done, the memory consumption goes back to a normal level (~3MB)

    Current Behavior

    After the stress test done, the memory consumption doesn't decrease.

    Possible Solution

    Sorry I can't find any solution for this.

    Steps to Reproduce (for bugs)

    1. Implement a simple API and call the exposed route.

    Context

    I tried to make a benchmark of an API made in Rust vs a one in Spring, and while the rust version is memory efficient, it does show some leaks that are problematic.


    Code used for exposing the route.

    use actix_web::{middleware, web, App, HttpServer, Responder, HttpResponse};
    
    async fn hello_world(
        name: web::Path<String>
    ) -> impl Responder {
        HttpResponse::Ok().json(format!("{}", name))
    }
    
    #[actix_web::main]
    async fn main() -> std::io::Result<()> {
    
        println!("Launching server...");
    
        std::env::set_var("RUST_LOG", "actix_web=info,actix_server=info");
        env_logger::init();
        dotenv::dotenv().ok();
    
        let port = match std::env::var("PORT") {
            Ok(port) => port,
            _ => String::from("4000")
        };
        let address = format!("0.0.0.0:{}", port);
    
        let http_server = HttpServer::new(move || {
            App::new()
                // .wrap(middleware::Logger::default())
                .route("/hello/{name}", web::get().to(hello_world))
        })
            .bind(address.clone())?;
    
        println!("Will listen to {}", address);
    
        http_server
            .run()
            .await
    }
    

    Using LeakSanitizer it does confirm that there's a little problem:

    ==68512==ERROR: LeakSanitizer: detected memory leaks
    Direct leak of 256 byte(s) in 8 object(s) allocated from:
        #0 0x564cae1e4255  (/home/lperreau/workspace/hello-world/target/x86_64-unknown-linux-gnu/debug/hello_world+0xd6255)
        #1 0x564cae2f830b  (/home/lperreau/workspace/hello-world/target/x86_64-unknown-linux-gnu/debug/hello_world+0x1ea30b)
    
    Direct leak of 192 byte(s) in 8 object(s) allocated from:
        #0 0x564cae1e4255  (/home/lperreau/workspace/hello-world/target/x86_64-unknown-linux-gnu/debug/hello_world+0xd6255)
        #1 0x564cae40bf8b  (/home/lperreau/workspace/hello-world/target/x86_64-unknown-linux-gnu/debug/hello_world+0x2fdf8b)
    
    Indirect leak of 8192 byte(s) in 8 object(s) allocated from:
        #0 0x564cae1e4255  (/home/lperreau/workspace/hello-world/target/x86_64-unknown-linux-gnu/debug/hello_world+0xd6255)
        #1 0x564cae2f830b  (/home/lperreau/workspace/hello-world/target/x86_64-unknown-linux-gnu/debug/hello_world+0x1ea30b)
    
    Indirect leak of 32 byte(s) in 8 object(s) allocated from:
        #0 0x564cae1e4255  (/home/lperreau/workspace/hello-world/target/x86_64-unknown-linux-gnu/debug/hello_world+0xd6255)
        #1 0x564cae565a5b  (/home/lperreau/workspace/hello-world/target/x86_64-unknown-linux-gnu/debug/hello_world+0x457a5b)
    
    SUMMARY: LeakSanitizer: 8672 byte(s) leaked in 32 allocation(s).
    

    Your Environment

    • Rust Version (I.e, output of rustc -V): rustc 1.45.1 (c367798cf 2020-07-26)
    • Actix Web Version: 3.2.0
    Reviewed by Mcfloy at 2020-11-08 15:53
  • 6. Remove several usages of 'unsafe'

    This PR removes several different usages of unsafe (specifically, UnsafeCell), and replaces them with safe code. While these changes technically add some amount of overhead (Copying a type instead of taking a reference, and runtime RefCell checks), it should be so small as to be invisible on any benchmark.

    By replacing UnsafeCell with the safe Cell/UnsafeCell types, we ensure that any mistakes will lead to a panic! at worst, instead of undefined behavior.

    Each commit modifies a single file, and describes the changes made.

    Reviewed by Aaron1011 at 2019-07-10 01:19
  • 7. how to run server by #[tokio::main]

    use actix_web::{middleware, web, App, HttpRequest, HttpServer};

    async fn index(_req: HttpRequest) -> &'static str { "Hello world!" }

    #[tokio::main] #[cfg(unix)] async fn main() -> std::io::Result<()> { ::std::env::set_var("RUST_LOG", "actix_server=info,actix_web=info"); env_logger::init();

    HttpServer::new(|| {
        App::new()
            // enable logger - always register actix-web Logger middleware last
            .wrap(middleware::Logger::default())
            .service(
                web::resource("/index.html")
                    .route(web::get().to(|| async { "Hello world!" })),
            )
            .service(web::resource("/").to(index))
    })
    .bind_uds("/tmp/actix-uds.socket")?
    .run()
    .await
    

    }

    #[cfg(not(unix))] fn main() -> std::io::Result<()> { println!("not supported"); Ok(()) }

    Reviewed by IThawk at 2020-01-17 09:11
  • 8. bug: actix_web client unable to connect to any host on windows

    Following example code always produces Error: Connect(Timeout):

    use actix_rt::System;
    use awc::Client;
    use futures::future::{
        Future,
        lazy
    };
    
    fn main() {
        System::new("weight_version").block_on(lazy(|| {
    
            awc::Client::new().get("https://google.com") //any address here
                .header("User-Agent", "Actix-web")
                .send()
                .map_err(|error| {
                    println!("Error: {:?}", error);
                })
                .and_then(|response| {
                    println!("Response: {:?}", response);
                    Ok(())
                })
        }));
    }
    

    actix_web::client::Client also produces same error:

    use actix_rt::System;
    use actix_web::client::Client;
    use futures::future::{
        Future,
        lazy
    };
    
    fn main() {
        System::new("weight_version").block_on(lazy(|| {
            let client = Client::default();
    
            client.get("https://www.rust-lang.org/")
                .header("User-Agent", "Actix-web")
                .send()
                .map_err(|error| {
                    println!("Error: {:?}", error);
                    //Err(error)
                })
                .and_then(|response| {
                    println!("Response: {:?}", response);
                    Ok(())
                })
        }));
    }
    

    Tested on 3 totally different windows machines with following:

    openssl version
    OpenSSL 1.1.1c  28 May 2019
    
    Reviewed by calirofpn at 2019-08-19 13:02
  • 9. Call to Community and Participation

    Until now i made most of project related decisions. But unfortunately, i dont have much time anymore, also i'd like to spend more time outside of opensource. supporting of this large and complex project is time consuming so i'd like to hand it to contributors, who'd like to spend some time on the project. I am still planing to work on actix, but can not afford to spend that much time as before.

    @actix/contributors

    Reviewed by fafhrd91 at 2019-08-01 14:43
  • 10. Type-safe path/query parameter handling, using serde

    Users should be able to define structures that hold parameters that need to be passed to a request handler. We could use the serde Deserialize trait. The goal is to make it easier for users to access parameters without having to deal with error-handling themselves, and hopefully to avoid the current situation where making a typo in your handler vs your route means that you get a runtime error instead of a compile-time error.

    The goal is to somehow allow the user to type this:

    #[derive(Deserialize)]
    struct MyParams {
        name: String,
    }
    

    and then, define a handler like this:

    fn my_handler(req: HttpRequest<_>, my_params: MyParams) -> _ {
    }
    

    or, alternatively:

    fn my_hadler(req: HttpRequest<_>) -> _ {
        let my_params = req.get_params::<MyParams>();
    }
    

    This will require some way to declare the route for my_handler with MyParams.

    Reviewed by radix at 2018-02-09 22:31
  • 11. UDP Socket Leak

    I have a service that after ~18 - 24 hours runs out of file descriptors after a lot of investigation and some production debugging we were able to track it down to being leaked UDP sockets. My first thought is something about DNS resolution is wrong. When caught in the act the server had 418 UDP sockets open and it climbs up to the ulimit of 1024 and then server CPU spikes and the health check fails and the container is cycled.

    Reviewed by glademiller at 2018-12-07 17:17
  • 12. [actix-test] TcpStream obtained from TestServer contains HTTP/1.1 408 Request Timeout

    I'm not entirely sure whether this is considered a bug. If not, please treat it as a clarifying question.

    Expected Behavior

    I follow an example from TestServer but with a slight modification. When I obtain TcpStream out of the started TestServer, I expect the stream to be open and be readable/writeable.

    Current Behavior

    What actually happens is that the obtained stream is already closed due to HTTP/1.1 408 Request Timeout. Please see the reproduction steps below.

    Steps to Reproduce (for bugs)

    use actix_web::{get, App, HttpResponse, Error, Responder};
    use tokio::net::TcpStream;
    
    #[get("/")]
    async fn my_handler() -> Result<impl Responder, Error> {
        Ok(HttpResponse::Ok())
    }
    
    #[actix_rt::test]
    async fn test_example() {
        let srv = actix_test::start(||
            App::new().service(my_handler)
        );
    
        let stream = TcpStream::connect(srv.addr()).await.unwrap();
    
        let (read_half, _write_half) = stream.into_split();
    
        // Comment in the following if the execution ends up 'called `Result::unwrap()` on an `Err` value: Kind(WouldBlock)'
        //use tokio::time::{sleep, Duration};
        //sleep(Duration::from_millis(10000)).await;
    
        let mut buf = [0; 256];
        read_half.try_read(&mut buf).unwrap();
        println!("buf: {:?}", buf);
    }
    

    One may need to comment in the above lines of code. When the code above runs (as expected by myself), it should print something like

    buf: [72, 84, 84, 80, 47, 49, 46, 49, 32, 52, 48, 56, 32, 82, 101, 113, 117, 101, 115, 116, 32, 84, 105, 109, 101, 111, 117, 116, 13, 10, 99, 111, 110, 116, 101, 110, 116, 45, 108, 101, 110, 103, 116, 104, 58, 32, 48, 13, 10, 99, 111, 110, 110, 101, 99, 116, 105, 111, 110, 58, 32, 99, 108, 111, 115, 101, 13, 10, 100, 97, 116, 101, 58, 32, 84, 104, 117, 44, 32, 50, 54, 32, 77, 97, 121, 32, 50, 48, 50, 50, 32, 50, 51, 58, 52, 53, 58, 48, 56, 32, 71, 77, 84, 13, 10, 13, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
    

    This reads roughly (the date part may differ depending on when the code runs):

    HTTP/1.1 408 Request Timeout
    content-length: 0
    connection: close
    date: Thu, 26 May 2022 21:56:20 GMT
    

    Context

    What am I trying to accomplish by calling TcpStream::connect on a TestServer started via actix_test::start? Well, I'd like to write an integration test where there is an Actix actor holding on to tokio::net::tcp::OwnedReadHalf and the test main program holding onto to tokio::net::tcp::OwnedWriteHalf. I'd like the test main program to feed test inputs through the stream and I want the actor to extract it through the read half, as being used as a trait object of tokio::io::AsyncRead. I am aware that there are other ways to pass data to an Actix actor, but the constraints imposed by an existing architecture led me to the said approach.

    I'd like to understand whether I can expect TcpStream to be obtained out of TestServer's address, without being in the closed state.

    Your Environment

    • Rust Version (I.e, output of rustc -V): rustc 1.60.0 (7737e0b5c 2022-04-04)
    • Actix Web Version: 4.0.1
    • actix-test Version: 0.1.0-beta.13
    Reviewed by saitoy1 at 2022-05-27 00:27
  • 13. Failure to flush Payload when it is dropped before handler consumes all bytes

    In cases where a handler exits early without reading a supplied Payload, there is some new code in actix-web (see PR #2624) that consumes the rest of the bytes in the request.

    It seems not to work with large request bodies (approaching 512k).

    Expected Behavior

    If a Payload is dropped before all bytes are consumed, the rest of the client request should still be consumed.

    Current Behavior

    If a Payload is dropped before all bytes are consumed, the rest of the request is consumed if the request is small, but larger requests stop reading and drop the connection with a message "handler did not read whole payload and dispatcher could not drain read buf; return 500 and close connection".

    Possible Solution

    Haven't quite found the root cause yet, but it appears that the read_buf in the Dispatcher is empty. When PayloadDecoder::decode() is called with read_buf as src, it reports zero bytes available, but self.kind contains a nonzero Kind::Length of remaining bytes. If they were both correctly zero, it would return PayloadItem::Eof, and the flush would terminate correctly. If they were both correctly nonzero, it would successfully return PayloadItem::Chunk(buf), which would continue the flush loop until exhausted.

    I'm not sure which one is wrong here, but it only seems to happen if there are a certain number of reads required to flush the request.

    Steps to Reproduce (for bugs)

    Minimal server:

    use actix_web::{post, web::Payload, App, HttpServer};
    
    #[post("/hello")]
    async fn greet(_: Payload) -> &'static str {
        "Ok\n"
    }
    
    #[actix_web::main]
    async fn main() -> std::io::Result<()> {
        env_logger::init();
        HttpServer::new(|| App::new().service(greet))
            .bind(("127.0.0.1", 5000))?
            .run()
            .await
    }
    

    Client-side - I was able to duplicate this by sending a 511k file (succeeded), and a 512k file (failed), but managed to narrow down to exact number of bytes by using curl's -C to skip initial bytes in the file. Byte ranges may vary across OSs, not sure.

    # create a 512k file of random data
    dd if=/dev/random of=512k bs=1024 count=512
    # this succeeds - continue sending data from byte 1753
    curl -C 1753 -H 'Content-Type: application/octet-stream' -d @512k -v http://127.0.0.1:5000/hello
    # this fails - continue sending data from byte 1752
    curl -C 1752 -H 'Content-Type: application/octet-stream' -d @512k -v http://127.0.0.1:5000/hello
    

    Context

    I'd like to be able to return from a handler without having to worry about whether I've finished reading the Payload completely. For example, streaming a file to disk, then having a write fail, it's much easier to handle with a simple ? and a handler returning a Result, than having to wrap the whole thing in a handler that cleans up the Payload before returning an error.

    Your Environment

    • MacOS 12.4 x86_64
    • actix-web 4.0.1
    • actix-http 3.0.0
    • rustc 1.61.0 (fe5b13d68 2022-05-18)
    Reviewed by squidpickles at 2022-05-26 21:51
  • 14. Server does not clean up resources after calling ServerHandle::stop in certain cases

    If a service takes long time to complete (longer than value specified byHttpServer::shutdown_timeout to be precise), it seems the server does not properly clean up after itself. In particular, I have an issue with this when the server holds on to a tokio channel sender and I'm waiting for the channel's receiver to get "channel closed" message in a separate tokio task after stopping the server.

    Expected Behavior

    After calling ServerHandle::stop and waiting until the end of the shutdown_timeout period, all resources held by the server should be dropped.

    Current Behavior

    Server seems to still hold on to resources.

    Possible Solution

    None known...

    Steps to Reproduce (for bugs)

    Given the following example application:

    use actix_web::{Responder, HttpResponse, web::{Data}};
    use tokio::sync::{mpsc, broadcast};
    use log::*;
    
    #[actix_web::post("/sleep10")]
    pub async fn sleep10(tx: Data<mpsc::UnboundedSender<()>>) -> impl Responder {
        info!("sleeping 10 seconds");
        tokio::time::sleep(std::time::Duration::from_secs(10)).await;
        info!("slept 10 seconds");
        tx.send(()).unwrap();
        HttpResponse::Ok()
    }
    
    #[actix_web::post("/sleep30")]
    pub async fn sleep30(tx: Data<mpsc::UnboundedSender<()>>) -> impl Responder {
        info!("sleeping 30 seconds");
        tokio::time::sleep(std::time::Duration::from_secs(30)).await;
        info!("slept 30 seconds");
        tx.send(()).unwrap();
        HttpResponse::Ok()
    }
    
    #[tokio::main]
    async fn main() -> anyhow::Result<()> {
        env_logger::init();
    
        let (stop_tx, mut stop_rx) = broadcast::channel(1);
        let (tx, mut rx) = mpsc::unbounded_channel();
    
        // My spawned task that consumes the channel’s receiver.
        let consumer_handle = tokio::spawn(async move {
            loop {
                tokio::select! {
                    Some(()) = rx.recv() => info!("task received item"),
                    Ok(()) = stop_rx.recv() => {
                        info!("task draining items");
                        while let Some(()) = rx.recv().await { // This will block as sender is never dropped.
                            info!("task drained item");
                        }
                        info!("task finished draining");
                        break;
                    }
                }
            }
        });
    
        let tx = Data::new(tx);
        let server = actix_web::HttpServer::new(move || {
            let tx = tx.clone();
            actix_web::App::new()
                .service(sleep10)
                .service(sleep30)
                .app_data(tx) // This sender is never dropped.
        })
        .bind("localhost:20000")?
        .workers(4)
        .disable_signals()
        .shutdown_timeout(20) // Modified shutdown timeout, less than 30 seconds.
        .run();
    
        let server_handle = server.handle();
        let signal = tokio::signal::ctrl_c();
    
        tokio::pin!(server);
        tokio::select! {
            r = signal => {
                info!("received interrupt signal");
                r.unwrap();
                let ((), r) = tokio::join!(server_handle.stop(true), server);
                r.unwrap();
                info!("stopping task");
                stop_tx.send(()).unwrap();
                consumer_handle.await.unwrap();
            }
            r = &mut server => {
                info!("server finished");
                r.unwrap();
                stop_tx.send(()).unwrap();
                consumer_handle.await.unwrap();
            }
        }
    
        Ok(())
    }
    

    When I call curl -X POST localhost:20000/sleep10 and send SIGINT to the application, it cleanly shutsdown (OK).

    $ RUST_LOG=debug cargo run
    [2022-05-13T08:18:56Z INFO  actix_server::builder] Starting 4 workers
    [2022-05-13T08:18:56Z INFO  actix_server::server] Tokio runtime found; starting in existing Tokio runtime
    [2022-05-13T08:19:00Z INFO  shutdown] sleeping 10 seconds
    ^C[2022-05-13T08:19:01Z INFO  shutdown] received interrupt signal
    [2022-05-13T08:19:01Z INFO  actix_server::worker] Graceful worker shutdown; finishing 1 connections
    [2022-05-13T08:19:01Z DEBUG actix_server::accept] Paused accepting connections on [::1]:20000
    [2022-05-13T08:19:01Z DEBUG actix_server::accept] Paused accepting connections on 127.0.0.1:20000
    [2022-05-13T08:19:01Z INFO  actix_server::accept] Accept thread stopped
    [2022-05-13T08:19:01Z INFO  actix_server::worker] Shutting down idle worker
    [2022-05-13T08:19:01Z INFO  actix_server::worker] Shutting down idle worker
    [2022-05-13T08:19:01Z INFO  actix_server::worker] Shutting down idle worker
    [2022-05-13T08:19:10Z INFO  shutdown] slept 10 seconds
    [2022-05-13T08:19:10Z INFO  shutdown] task received item
    [2022-05-13T08:19:11Z INFO  shutdown] stopping task
    [2022-05-13T08:19:11Z INFO  shutdown] task draining items
    [2022-05-13T08:19:11Z INFO  shutdown] task finished draining
    $
    

    If I call curl -X POST localhost:20000/sleep30 and send SIGINT, the application never terminates (BUG).

    $ RUST_LOG=debug cargo run
    [2022-05-13T08:21:14Z INFO  actix_server::builder] Starting 4 workers
    [2022-05-13T08:21:14Z INFO  actix_server::server] Tokio runtime found; starting in existing Tokio runtime
    [2022-05-13T08:21:17Z INFO  shutdown] sleeping 30 seconds
    ^C[2022-05-13T08:21:19Z INFO  shutdown] received interrupt signal
    [2022-05-13T08:21:19Z DEBUG actix_server::accept] Paused accepting connections on [::1]:20000
    [2022-05-13T08:21:19Z DEBUG actix_server::accept] Paused accepting connections on 127.0.0.1:20000
    [2022-05-13T08:21:19Z INFO  actix_server::worker] Shutting down idle worker
    [2022-05-13T08:21:19Z INFO  actix_server::worker] Shutting down idle worker
    [2022-05-13T08:21:19Z INFO  actix_server::worker] Shutting down idle worker
    [2022-05-13T08:21:19Z INFO  actix_server::worker] Graceful worker shutdown; finishing 1 connections
    [2022-05-13T08:21:19Z INFO  actix_server::accept] Accept thread stopped
    [2022-05-13T08:21:39Z INFO  shutdown] stopping task
    [2022-05-13T08:21:39Z INFO  shutdown] task draining items
    ... never terminates ...
    

    Context

    The end goal for me is to implement graceful shutdown of my application that also runs some other tokio spawned and spawn_blocking tasks.

    Your Environment

    • Rust Version: rustc 1.60.0 (7737e0b5c 2022-04-04)
    • Actix Web Version: 4.0.1
    • OS: macOS (12.3.1), Apple M1
    Reviewed by julianskartor at 2022-05-13 08:32
  • 15. Actix returns 400 instead of 422 on unprocessible entity

    Actix doesn't specify an extraction error as "unprocessible entity" with a specific code 422, and just use a common 400 code that means "Bad request"

    Reviewed by Dominux at 2022-05-08 06:46
  • 16. contentType error

    #[derive(Debug, Serialize, Deserialize)]
    pub struct UserRolesReq {
        pub user_id: u64,
        pub roles: Vec<u64>,
    }
     #[post("auth_role")]
    pub async fn auth_role(arg: Form<UserRolesReq>) -> HttpResponse {
        println!("{:?}", arg);
    
        //  UserService::auth_role(arg.into_inner()).await;
    
        todo!()
    }
    
    Reviewed by by965738071 at 2022-05-06 09:52
  • 17. awc sends `form-data` data

    Expected Behavior

    Use awc on server to send form-data request for post to another server

    Current Behavior

    awc doesn't seem to have a similar API

    Possible Solution

        let img_file = tokio::fs::read("a.jpg").await?;
        let request = FormData::new();
        request.append("file", img_file);
    
        let mut req = client.post("https://xxx").send_formdata(&request).await?;
    

    Steps to Reproduce (for bugs)

    Context

    Your Environment

    • Rust Version (I.e, output of rustc -V):rustc 1.60.0 (7737e0b5c 2022-04-04)
    • Actix Web Version: 4
    awc = { version = "3.0.0", features = ["openssl"] }
    
    Reviewed by januwA at 2022-05-05 13:25
Salvo is a powerful and simplest web server framework in Rust world
Salvo is a powerful and simplest web server framework in Rust world

Salvo is an extremely simple and powerful Rust web backend framework. Only basic Rust knowledge is required to develop backend services.

May 24, 2022
A starter template for actix-web projects that feels very Django-esque. Avoid the boring stuff and move faster.

Jelly A.K.A, the actix-web starter you probably wish you had. This is provided as-is, and anyone is free to extend it or rework it as they desire - ju

May 13, 2022
Add Facebook and Google authentication to your HTTP REST API in Actix-web

I created this project while learning Rust. Project shows how to handle Facebook and Google token verification in Rust using Actix-Web. Hope this help

May 16, 2022
In-progress extractors and middleware for Actix Web

actix-web-lab Experimental extractors, middleware, and other extras for possible inclusion in Actix Web. Things To Know About This Crate It will never

May 19, 2022
Extension for actix-web to validate user permissions

actix-web-grants Extension for actix-web to validate user permissions. To check user access to specific services, you can use built-in proc-macro, Per

May 11, 2022
Easy to use multipart forms for actix-web

Actix Easy Multipart Easy to use Multipart Forms for actix-web. File uploads are written to disk as temporary files similar to the way the $_FILES var

May 17, 2022
Example Actix 2.x REST application implementing many features

Rust/Actix Example An Actix 2.0 REST server using the Rust language. Motivation Actix Web is a fast, powerful web framework for building web applicati

May 23, 2022
A fast, boilerplate free, web framework for Rust

Tower Web A web framework for Rust with a focus on removing boilerplate. API Documentation Tower Web is: Fast: Fully asynchronous, built on Tokio and

May 18, 2022
Sincere is a micro web framework for Rust(stable) based on hyper and multithreading

The project is no longer maintained! Sincere Sincere is a micro web framework for Rust(stable) based on hyper and multithreading. Style like koa. The

May 16, 2022
A flexible web framework that promotes stability, safety, security and speed.

A flexible web framework that promotes stability, safety, security and speed. Features Stability focused. All releases target stable Rust. This will n

May 22, 2022
:zap: fast http framework for rust

zap ⚡ The mission of zap is, to deliver a basic, but fast rust web server library. Documentation About This code is based on tokio's minihttp project,

May 6, 2022
An Extensible, Concurrent Web Framework for Rust

Iron Extensible, Concurrency Focused Web Development in Rust. Response Timer Example Note: This example works with the current iron code in this repos

May 27, 2022
An expressjs inspired web framework for Rust

nickel.rs nickel.rs is a simple and lightweight foundation for web applications written in Rust. Its API is inspired by the popular express framework

May 16, 2022
A web framework for Rust.

Rocket Rocket is an async web framework for Rust with a focus on usability, security, extensibility, and speed. #[macro_use] extern crate rocket; #[g

May 27, 2022
A lightweight web framework built on hyper, implemented in Rust language.

Sapper Sapper, a lightweight web framework, written in Rust. Sapper focuses on ergonomic usage and rapid development. It can work with stable Rust. Sa

May 17, 2022
Web framework in Rust

Rouille, a Rust web micro-framework Rouille is a micro-web-framework library. It creates a listening socket and parses incoming HTTP requests from cli

May 22, 2022
Handlebars middleware for Iron web framework

handlebars-iron Handlebars middleware for the Iron web framework. This library, together with handlebars, iron and hyper, works on both stable and nig

Dec 18, 2021
A blazingly fast static web server with routing, templating, and security in a single binary you can set up with zero code. :zap::crab:
A blazingly fast static web server with routing, templating, and security in a single binary you can set up with zero code. :zap::crab:

binserve ⚡ ?? A blazingly fast static web server with routing, templating, and security in a single binary you can set up with zero code. ?? UPDATE: N

May 23, 2022
Simple and fast web server

see Overview Simple and fast web server as a single executable with no extra dependencies required. Features Built with Tokio and Hyper TLS encryption

May 24, 2022