GithubHelp home page GithubHelp logo

actix / actix-web Goto Github PK

View Code? Open in Web Editor NEW
20.2K 229.0 1.6K 14 MB

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

Home Page: https://actix.rs

License: Apache License 2.0

Rust 99.54% JavaScript 0.01% Shell 0.42% Just 0.03%
rust web web-development websockets actix actix-web async

actix-web's Introduction

Actix Web

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

crates.io Documentation MSRV MIT or Apache 2.0 licensed Dependency Status
CI codecov downloads Chat on Discord

Features

  • Supports HTTP/1.x and HTTP/2
  • Streaming and pipelining
  • Powerful request routing with optional macros
  • Full Tokio compatibility
  • Keep-alive and slow requests handling
  • Client/server WebSockets support
  • Transparent content compression/decompression (br, gzip, deflate, zstd)
  • Multipart streams
  • Static assets
  • SSL support using OpenSSL or Rustls
  • Middlewares (Logger, Session, CORS, etc)
  • Integrates with the awc HTTP client
  • Runs on stable Rust 1.72+

Documentation

Example

Dependencies:

[dependencies]
actix-web = "4"

Code:

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

#[get("/hello/{name}")]
async fn greet(name: web::Path<String>) -> impl Responder {
    format!("Hello {name}!")
}

#[actix_web::main] // or #[tokio::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| {
        App::new().service(greet)
    })
    .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 the following licenses, 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.

actix-web's People

Contributors

aaron1011 avatar adwhit avatar aliemjay avatar ava57r avatar dependabot[bot] avatar doumanash avatar dowwie avatar dunnock avatar fafhrd91 avatar fakeshadow avatar fuchsnj avatar ibraheemdev avatar jesskfullwood avatar johntitor avatar jrconlin avatar kornelski avatar krircc avatar lukemathwalker avatar mattgathu avatar memoryruins avatar messense avatar mitsuhiko avatar mockersf avatar neopallium avatar niklasf avatar popzxc avatar radix avatar robjtede avatar svenstaro avatar zzau13 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

actix-web's Issues

Ranges header support

This week I took a deep dive in the RFC and thought about the possibilites. I have a solution now, but I don't feel it's complete, so I need your advice about the implementation.

RFC defines two types of response when the ranges header is present: a simple one, and when you request multiple ranges which must give you back a "Multipart" response.

Implementing the latter one has the advantage of fully conforming the RFC, but has security implications(overlapping ranges, etc). The former one is much easier if you modify the Responder. In most cases it's enough. You can watch&seek a movie in your browser, also you can get a working ipxe server(this was my goal with this). Implementing this for the NamedFIle is trivial, but what if we need the ranges support for files when they come from another location.(database like MongoDB or CouchDB, S3, another webserver etc) In this case it's maybe easier to add the support in a main component.

What do you think about this and which is the preferred way for this project?

Basic Example does not compile

The Basic Example does not appear to compile, with the following error:

error[E0277]: the trait bound `actix_web::Body: std::convert::From<std::string::String>` is not satisfied
  --> src/main.rs:20:10
   |
20 |         .body(format!("Hello {}!", req.match_info().get("name").unwrap()))
   |          ^^^^ the trait `std::convert::From<std::string::String>` is not implemented for `actix_web::Body`
   |
   = note: required because of the requirements on the impl of `std::convert::Into<actix_web::Body>` for `std::string::String`

Using main.rs equal to the basic example and a Cargo.toml that looks like:

[package]
name = "actix_test"
version = "0.1.0"

[dependencies]
actix = "*"
actix-web = "*"
env_logger = "*"

Getting Started

Hello

I discover actix-web. When I follow the instructions of the example https://actix.github.io/actix-web/guide/qs_2. html with this code

fn main () {

    let sys = actix:: System:: new ("example");

    let app = Application:: new ()
        . resource ("/", |r| r. f (index)
        . finish ();

    HttpServer:: new (|| app)
        . bind ("127.0.0.0.1:8088"). unwrap ()
        . start ();

}

then I have the mistake

HttpServer:: new (|| app)
^^^^^^^^^^^^^^^^^^^^^^`actix_web:: application:: HttpApplication` is not an iterator; maybe try calling ``iter ()` or a similar method

How to compile the code HttpServer:: new (|| app) without error?

The final example works but is not consistent with the first steps indicated.

Thank you

"Signal" feature doesn't compile

#....................
actix = "^0.3.5"
actix-web = { git = "https://github.com/actix/actix-web.git", version = "0.3.0",  features = ["signal"] }


//....................
use actix_web::*;

#[cfg(unix)]
use actix::actors::signal::{ProcessSignals, Subscribe};


//....................
let signals = Arbiter::system_registry().get::<ProcessSignals>();
signals.send(Subscribe(addr.subscriber()));

===============>

error[E0433]: failed to resolve. Use of undeclared type or module `Arbiter`
  --> src/main.rs:73:19
   |
73 |     let signals = Arbiter::system_registry().get::<ProcessSignals>();
   |                   ^^^^^^^ Use of undeclared type or module `Arbiter`

Address already in use

Hello

I test a little app and i use cargo-watch as cargo watch -x run : it's work but often i have thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Error { repr: Os { code: 98, message: "Address already in use" } }', /checkout/src/libcore/result.rs:906:4

And i wait (1mn) ... and after it's restart

actix does not seem to release the listened port correctly (after a SIGTERM for example).

But then how to close a connection to a database or use actix-web with kubernetes like (https://blog.risingstack.com/graceful-shutdown-node-js-kubernetes/).

Have you an example to properly close actix-web.
Thank

signal not close postgresql client

Hello

actor do not close automatically postgresql conn after shutting down the actix-web application.

When a start application, i mount 12 clients

let db_url = "postgres://postgres:azerty@localhost:5432/test";
let addr = SyncArbiter::start(num_cpus::get() * 3, move || db::DbExecutor::new(&db_url));

...

// (db.rs)
impl DbExecutor {
    pub fn new(db_url: &str) -> DbExecutor {
        DbExecutor{
            conn : match Connection::connect(db_url, TlsMode::None) {
                Err(err) => panic!("Error connecting to {} {:?}", db_url, err),
                Ok(conn) => conn
            }
        }
    }
}

I can count 12 clients with this sql cmd number-of-active-connections-and-remaining-connections

select max_conn,used,res_for_super,max_conn-used-res_for_super res_for_normal
from
  (select count(*) used from pg_stat_activity) t1,
  (select setting::int res_for_super from pg_settings where name=$$superuser_reserved_connections$$) t2,
  (select setting::int max_conn from pg_settings where name=$$max_connections$$) t3;

If now i send ctrl+c, application stop (ok) and rerun sql cmd, i see always 12 connections (ko). If a rerun actix-web application i have 24 clients connections. etc.

#17 , you said btw usually you don't need explicit disconnect in rust, usually connections get closed on "drop".

What would be the solution to close also the postgresql connections after a signal ?

Can't have multiple Applications on a single server with different state

I don't think this is currently possible, but please correct me if I'm wrong.

HttpServer::new() requires an iterator of Applications (something that implements IntoHttpHandler)

Since the Application has a generic State parameter, if you have applications with a different type for State, you can't create an iterator over these different types.

slog

Hello

I use slog + AppState ... and it's ok ! Now i have colored term info (and i can also write json to a file with slog ...) . See my first code .

But i have a problem with Actor with lifetime : See my second code

error[E0106]: missing lifetime specifier
  --> src/db.rs:45:59
   |
45 | pub struct CreateUserWithLog { pub name: String, pub log: &Logger}
   |                                                           ^ expected lifetime parameter

error: aborting due to previous error

first code src/main.rs (ok)

#[macro_use]
extern crate slog;
extern crate slog_term;
extern crate slog_async;
extern crate slog_envlogger;
extern crate slog_stream;
use slog::Drain;
use slog::Logger;
...
struct AppState {
    db: SyncAddress<DbExecutor>,
    log: Logger,
}
...
fn index(mut req: HttpRequest<AppState>) -> Box<Future<Item=HttpResponse, Error=Error>> {
    let _log = &req.state().log;
    debug!(_log, "Hello {}", "slog"); // OK !
    ...
}
...
fn main() {
    ::std::env::set_var("RUST_LOG", "actix_web=info");
    let _guard = slog_envlogger::init().unwrap(); // replace ``env_logger::init();``
    let decorator = slog_term::TermDecorator::new().build();
    let console_drain = slog_term::FullFormat::new(decorator).build().fuse();
    let console_drain = slog_async::Async::new(console_drain).build().fuse();
    let _log = slog::Logger::root(console_drain, o!());
    ...
    let addr = HttpServer::new(
        move || Application::with_state(AppState{
                db: addr.clone(),
                log: _log.clone(),
            })
    ...
}

second code (with error &Logger=> ^ expected lifetime parameter)

// db.rs
use std::io;
use actix_web::*;
use actix::prelude::*;
use slog::Logger;
...
pub struct CreateUserWithLog { pub name: String, pub log: &Logger}
impl ResponseType for CreateUserWithLog { type Item = String; type Error = Error; }
impl Handler<CreateUserWithLog> for DbExecutor {
    fn handle(&mut self, msg: CreateUserWithLog, _: &mut Self::Context)
              -> Response<Self, CreateUserWithLog>
    {
        println!("*** {}", &msg.name);
        Self::reply("Hello".to_string())
    }
}

// main.rs
fn index(mut req: HttpRequest<AppState>) -> Box<Future<Item=HttpResponse, Error=Error>> {

    let _log = &req.state().log; // ok
    debug!(_log, "Hello {}", "slog");  // ok

    req.state().db.call_fut(CreateUserWithLog{name: "hello name".to_owned(), log: &req.state().log})
        .from_err()
        .and_then(|res| {
            Ok(HttpResponse::build(StatusCode::OK)
                .content_type("text/html; charset=utf-8")
                .body("<html>Hello PG</html>").unwrap())
        })
        .responder()

I'm not yet comfortable with the lifetime of the rust language: how do I point to slog in this synchronous actor CreateUserWithLog?
Thank

session name & example

Hello

We can set cookie path, domain, secure ... but not name : always actix_session. Can you add a method to modify it?

If you have an example to manage database sessions (with tokio-redis or tokio-postgres) I would be interested to find example inside example/basic.rs (login/logout)

Thanks

gracefull shutdown

  • Given browser try to load a content
  • And keep open connexion to application (because content-length is not exact by example)
  • When i shutdown actix-web application
  • Then application stop
  • But thread actor keep alive (because open by browser)
  • And browser continue to wait
  • And i have "Adress is already use" when i restart application

examples/basic : #30

With firefox or chrome: html not finish to load (because content-length seem not exact).

Hello world - a few compilation errors

This

extern crate actix_web;

use actix_web::*;

fn index(req: HttpRequest) -> String {
    format!("Hello {}!", &req.match_info()["name"])
}

fn main() {
    HttpServer::new(
        || Application::new()
            .resource("/{name}", |r| r.f(index)))
        .bind("127.0.0.1:8080")?
        .start();
}

gives this

$ cargo build
   Compiling my_webapp v0.1.0 (file:///home/alex/projects/rust/my_webapp)
error[E0608]: cannot index into a value of type `&actix_web::Params`
 --> src/main.rs:6:27
  |
6 |     format!("Hello {}!", &req.match_info()["name"])
  |                           ^^^^^^^^^^^^^^^^^^^^^^^^

error[E0599]: no function or associated item named `new` found for type `actix_web::Application<_>` in the current scope
  --> src/main.rs:11:12
   |
11 |         || Application::new()
   |            ^^^^^^^^^^^^^^^^ function or associated item not found in `actix_web::Application<_>`

error[E0624]: method `bind` is private
  --> src/main.rs:13:10
   |
13 |         .bind("127.0.0.1:8080")?
   |          ^^^^                                                                                                                                            
                                                                                                                                                              
error[E0277]: the `?` operator can only be used in a function that returns `Result` (or another type that implements `std::ops::Try`)                         
  --> src/main.rs:10:5                                                                                                                                        
   |                                                                                                                                                          
10 |        HttpServer::new(                                                                                                                                  
   |   _____-                                                                                                                                                 
   |  |_____|                                                                                                                                                 
   | ||                                                                                                                                                       
11 | ||         || Application::new()                                                                                                                         
12 | ||             .resource("/{name}", |r| r.f(index)))                                                                                                     
13 | ||         .bind("127.0.0.1:8080")?                                                                                                                      
   | ||                                -                                                                                                                      
   | ||________________________________|                                                                                                                      
   | |_________________________________cannot use the `?` operator in a function that returns `()`                                                            
   |                                   in this macro invocation                                                                                               
   |                                                                                                                                                          
   = help: the trait `std::ops::Try` is not implemented for `()`                                                                                              
   = note: required by `std::ops::Try::from_error`                                                                                                            
                                                                                                                                                              
error: aborting due to 4 previous errors

error: Could not compile `my_webapp`.

Hello actix

Hello

I discover your actix-web project and this one seems really promising. Can be as promising as the nodesjs/express framework (easy, cool, fast, documented...).

Is there a minimal example to use a third tokio module (https://tokio.rs/docs/going-deeper-tokio/third-party/) to call curl, postgres, cassandra... in a road function? is that even possible?

Thank you

CORS middleware: allowed_headers is defaulting to None

The documentation for CorsBuilder::allowed_headers() says

If All is set, whatever is requested by the client in Access-Control-Request-Headers will be echoed back in the Access-Control-Allow-Headers header.
...
Defaults to All.

The code is correctly defaulting the internal headers value to All, but there is no code actually echoing back the Access-Control-Request-Headers, it just leaves the Access-Control-Allow-Headers header empty.

relevant line of code generating the response:
https://github.com/actix/actix-web/blob/master/src/middleware/cors.rs#L303

Proposal: Logo

I think a beautigul Logo is missing for the project.
so i make one and 3 colors.


Actix and Actix Web always recompile on cargo build

When using Actix and Actix Web as dependencies in a project, running cargo build triggers them to recompile every time.

I.e, running cargo new --bin actix_test with the following Cargo.toml :

[package]
name = "actix_test"
version = "0.1.0"

[dependencies]
actix = "*"
actix-web = "*"

Running cargo build will always trigger a rebuild:

$ cargo build
   Compiling actix v0.3.0
   Compiling actix-web v0.1.0
   Compiling actix_test v0.1.0 (file:///<path_to_dir>/actix_test)
    Finished dev [unoptimized + debuginfo] target(s) in 4.89 secs

web site draft

http://tmpxqsddkjqlkdjlqkjdlqkdjqlkjd.surge.sh/

I know the http://ejs.co/ site which is based on a free template proposed by https://themes.3rdwavemedia.com/. I quickly adapted this template (draft) for actix-web: see the real demo http://tmpxqsddkjqlkdjlqkjdlqkdjqlkjd.surge.sh/

I will remove the demo site within a week and if you are interested then copy the content to the temporary repository https://github.com/ami44/actix-web-ami44-site

Thank you for your help this week, my vacation is over and I will be less present.
good continuation

app state & session

i try this example https://actix.github.io/actix-web/guide/qs_3.html#state
it's OK but i want also set session

fn index(req: HttpRequest<AppState>) -> String {
    let count = req.state().counter.get() + 1;
    req.state().counter.set(count);
    req.session().set("token", "xxxxxxxxxx".to_owned() )?; // <==== KO
    format!("Request number: {}", count)
}

fn main() {
    Application::with_state(AppState{counter: Cell::new(0)})
        .resource("/", |r| r.method(Method::GET).f(index))
        .finish();
}

Err

error[E0599]: no method named `session` found for type `actix_web::HttpRequest<AppState>` in the current scope

How get state and session in this example ?
Thank

HEAD responses can contain body

I find this library awesome, the API is much cleaner and easier to work with than other web frameworks which utilising async operations. My only blocking issue is the lack of support for ranges and RFC compilant HEAD responses. Former one is more like an inconvenience, but the latter one is more problematic since seemingly I can't work around it.

HEAD requests are special since their responses will contain the "content-length", but body will always be empty. I can't override the content-length(framework calculates it for me, which is nice) but in this case it would be a must. Another workaround is preparing a body, then throwing it away is not efficient solution.

I'm not a seasoned developer so maybe I overlooked something, if this is the case can you point me out what I missed? Thanks!

Example of a Handler that returns a future

I would love an example of how to return a Future to an HttpResponse.

For example using something like mysql async to make a request to a database and then compose an HttpResponse and have that been returned. Or an HTTP request via Hyper and then compose a response based on the result.

I love what you have done so far and I suspect I'm missing something obvious but I haven't been able to figure it out myself.

I would be willing to contribute an example if you point me in the right direction.

Thanks.

build error ring-asm

cd licorne && cargo clean && cargo update && cargo build

error: Multiple packages link to native library `ring-asm`. A native library can be linked only once.

Package `ring v0.12.1`
    ... which is depended on by `cookie v0.10.1`
    ... which is depended on by `actix-web v0.3.2 (https://github.com/actix/actix-web#a7c24aac)`
    ... which is depended on by `licorne v0.1.0 (file:///C:/Users/ami44/Documents/licorne)`
links to native library `ring-asm`.

Package `ring v0.13.0-alpha`
    ... which is depended on by `cookie v0.11.0-dev (https://github.com/alexcrichton/cookie-rs.git#8579b4b7)`
    ... which is depended on by `actix-redis v0.1.0 (https://github.com/actix/actix-redis#abb6c6ba)`
    ... which is depended on by `licorne v0.1.0 (file:///C:/Users/ami44/Documents/licorne)`
also links to native library `ring-asm`.

postgresql performance

Hello - Is not an issue

I found your example diesel/postgresql added to FrameworkBenchmarks.

I'm surprised that you don't usetokio-postgres orr2d2-postgres - Using an ORM always means sacrificing a little bit of performance for a little bit of ease. Have you ever made a performance comparison that decided on the choice of "diesel"?

Thank

postgresql handler

Hello

Thank for your diesel example. I adapted it to use rust-postgres ... but i don't know how to point to the open connection inside Handler :-)

use std::io;
use actix_web::*;
use actix::prelude::*;
use postgres::{Connection, TlsMode};

pub struct DbExecutor(Connection);

impl Actor for DbExecutor {
    type Context = SyncContext<Self>;
}

impl DbExecutor {
    pub fn new(db_url: &str) -> DbExecutor {
        DbExecutor(
            /*let conn =*/ match Connection::connect(db_url, TlsMode::None) {
                Err(err) => panic!("Error connecting to {} {:?}", db_url, err),
                Ok(conn) => conn
            }
        )
    }
}

...

impl Handler<CreateUser> for DbExecutor {
    fn handle(&mut self, msg: CreateUser, _: &mut Self::Context)
              -> Response<Self, CreateUser>
    {

        // let rows = &conn.query("SELECT 1;", &[]).unwrap(); // println!("{:?}", rows); <== how point to conn

        Self::reply("Hello".to_string())
    }
}

Thank for your help

How to handle application/json?

First of, let me say: thanks for your time and all the effort you put into actix-web!

Secondly, my question would be considering json post requests. How would you handle them? Could you give an example?

missing middleware

actix-web is young but I think it has great potential. One important piece missing when choosing a framework is the management of authentication. I invite you to take inspiration from https://github.com/jaredhanson/passport: it is an indispensable middleware when developing a website quickly with authentication.

With this generic middleware you should capture the majority of developers who want to make a website in rust.

You are also missing a nice web page like https://rocket.rs (maybe your company can help you?)

Bye, Happy New Year

json-rust

Hello

I would like to use json-rust (light and fast https://github.com/serde-rs/json-benchmark) instead of serde_json. I found example #2 https://actix.github.io/actix-web/guide/qs_7. html#json-request you can manually load payload into memory and ther deserialize it. Here is simple example. ....

I copied/paste the code into the file the example actix-web-master/examples/json/src/main. rs and I have several errors:

I've fixed fn index (mut req: HttpRequest) -> Future<Item=HttpResponse, Error=Error=Error> {```` in fn index (mut req: HttpRequest) -> Box<Future<Item=HttpResponse, Error=Error>>>> {`` but then I have the error

error[E0599]: no method named `concat2` found for type `actix_web:: payload:: ReadAny` in the current scope
  src/main. rs: 29:32
   |
29 | req. payload_mut (). readany (). concat2 ()
   | ^^^^^^^
   |
   = help: items from traits can only be used if the trait is in scope
   = note: the following trait is implemented but not in scope, perhaps add a `use' for it:
           candidate #1: `future:: Stream; `

Could you fix this example in the documentation and add an example that works in actix-web-master/examples/json/src/main. rs.

Sorry, I'm really a beginner
Thank you

serde_qs

discovered today this library https://docs.rs/serde_qs/0.4.0-rc. 2/serde_qs/ which allows parsing complex urls like

?name=Acme&id=42&phone=12345&address[postcode]=12345&address[city]=Carrot+City&user_ids[0]=1&user_ids[1]=2&user_ids[2]=3&user_ids[3]=4

to struct

{
    id: 42,
    name: "Acme".to_string(),
    phone: 12345,
    address: Address {
        city: "Carrot City".to_string(),
        postcode: "12345".to_string(),
    },
    user_ids: vec![1, 2, 3, 4],
};

Ami44

[Low prio/question] deserialize ws::Message::Binary with bincode?

Hello!

I have a websocket working and would like to deserialize the message I get.

    impl Handler<ws::Message> for MyWebSocket {
        type Result = ();

        fn handle(&mut self, msg: ws::Message, ctx: &mut Self::Context) {
            println!("WS received {:?}", msg);

            match msg {
                ws::Message::Ping(msg) => ctx.pong(&msg),
                ws::Message::Text(text) => ctx.text(&format!("Websocket received text: {}", text)),
                ws::Message::Binary(bin) => {
                    let decoded: Test = deserialize(&bin[..]).unwrap();
                    println!("Received a binary message {:?}", decoded);

                    ctx.binary(bin)
                },
                ws::Message::Closed | ws::Message::Error => ctx.stop(),
                _ => (),
            }
        }
    }

Sadly that doesn't compile, because: > error[E0608]: cannot index into a value of type actix_web::Binary

Now what I did to fix this, is add another match, like so:

match bin {
                    actix_web::Binary::Bytes(b) => {
                        let decoded: Test = deserialize(&b[..]).unwrap();
                        println!("Received a binary message {:?}", decoded);
                        ctx.binary(b)
                    },
                    _ => ()
                }

That works, for my case but doesn't seem too elegant.
Isn't there any generic way to access the insides of the Binary?

req.query inside future

Hello

i have this route (POST) "/name/{name}" to match "/name/aaa?token=xxxxxxxxxxx"
i try to get data inside path (ok) AND query (ko) AND body (ok)

fn action(mut req: HttpRequest) -> Box<Future<Item=HttpResponse, Error=Error>> { // println!("{:?}", req);
    let name: String = req.match_info().query("name").unwrap(); // <== OK, i get "aaaa"
    let query:HashMap<Cow<str>, Cow<str>> = req.query(); println!("{:?}", query); // <== KO, if i add this line
    req.payload_mut().readany() .... <== OK, i get body 

build error

error[E0502]: cannot borrow `req` as mutable because it is also borrowed as immutable
   --> src/main.rs:84:5
    |
73  |     let rawquery:HashMap<Cow<str>, Cow<str>> = req.query(); println!("{:?}", rawquery);
    |                                                --- immutable borrow occurs here
...
84  |     req.payload_mut().readany()
    |     ^^^ mutable borrow occurs here
...
129 | }
    | - immutable borrow ends here

But if set fn action(req: HttpRequest) i have another error.

How extract query params (when i need also path and body) - see nothing in doc.
Thanks

Request appears to hang after returning data

The following code causes web browser requests to appear to never complete despite the body having been completely downloaded. I have about 43 rows in the database.

Requests made with curl or wget function as expected.

My state looks like

struct State {
    db: SyncAddress<DbExecutor>,
    db2: SyncAddress<crud::CRUDExecutor>,
}

Handler

fn loadly(req: HttpRequest<State>) -> Box<Future<Item = HttpResponse, Error = Error>> {
    use schema::users::dsl::*;
    req.state().db2.call_fut( crud::Load::new(users.filter(id.ne(32))) )
        .from_err()
        .and_then(|res: Result<Vec<models::User>, _>| {
            match res {
                Ok(user) => {
                    println!("User: {:?}", user);
                    Ok(httpcodes::HTTPOk.build().chunked().json(user)?)
                }
                Err(_) => Ok(httpcodes::HTTPInternalServerError.into())
            }
        })
        .responder()    
}

CRUDExecutor

//! Db executor actor
use diesel;
use actix_web;
use actix::prelude::*;
use r2d2::Pool;
use r2d2_diesel::ConnectionManager;
use diesel::MysqlConnection;
use diesel::prelude::*;
use std::marker::PhantomData;

use models;
use schema;

pub struct CRUDExecutor(pub Pool<ConnectionManager<MysqlConnection>>);

pub struct Load<T, R>(pub T, pub PhantomData<R>)
where
    T: diesel::query_dsl::RunQueryDsl<MysqlConnection>
        + diesel::query_builder::Query
        + diesel::query_builder::QueryFragment<diesel::mysql::Mysql>
        + diesel::query_builder::QueryId;

impl<T, R> Load<T, R> where
    T: diesel::query_dsl::RunQueryDsl<MysqlConnection>
        + diesel::query_builder::Query
        + diesel::query_builder::QueryFragment<diesel::mysql::Mysql>
        + diesel::query_builder::QueryId {
    pub fn new(t: T) -> Self {
        Load(t, PhantomData)
    }        

}

impl<T, R> ResponseType for Load<T, R>
where
    T: diesel::query_dsl::RunQueryDsl<MysqlConnection>
        + diesel::query_builder::Query
        + diesel::query_builder::QueryFragment<diesel::mysql::Mysql>
        + diesel::query_builder::QueryId,
{
    type Item = Vec<R>;
    type Error = actix_web::error::ErrorInternalServerError<diesel::result::Error>;
}

impl Actor for CRUDExecutor {
    type Context = SyncContext<Self>;
}


impl<T, R> Handler<Load<T, R>> for CRUDExecutor
where
    T: diesel::query_dsl::RunQueryDsl<MysqlConnection>
        + diesel::query_builder::Query
        + diesel::query_builder::QueryFragment<diesel::mysql::Mysql>
        + diesel::query_builder::QueryId,
    diesel::mysql::Mysql: diesel::types::HasSqlType<<T as diesel::query_builder::Query>::SqlType>,
    (i32, String): diesel::Queryable<<T as diesel::query_builder::Query>::SqlType, diesel::mysql::Mysql>,
    R: diesel::Queryable<<T as diesel::query_builder::Query>::SqlType, diesel::mysql::Mysql>
{
    fn handle(&mut self, msg: Load<T, R>, _: &mut Self::Context) -> Response<Self, Load<T, R>> {
        // use self::schema::users::dsl::*;
        let conn = self.0.get().unwrap();

        match msg.0.load::<R>(&*conn) {
            Ok(items) => Self::reply(items),
            Err(err) => Self::reply_error(actix_web::error::ErrorInternalServerError(err)),
        }
    }
}

Diesel Schema

table! {
    users (id) {
        id -> Integer,
        name -> Text,
    }
}

Issue with JSON Encoded Responses

If I have a handler such as the one below

#[derive(Serialize, Queryable, Debug)]
pub struct User {
    pub id: i32,
    pub name: String,
}
fn loadly(req: HttpRequest<State>) -> Box<Future<Item = HttpResponse, Error = Error>> {
    let userv: Vec<models::User> = vec![models::User{id: 1, name: "rabbit".to_owned()},
    models::User{id: 2, name: "rabbit".to_owned()},
    models::User{id: 3, name: "rabbit".to_owned()},
    models::User{id: 4, name: "rabbit".to_owned()}
    ];
    Box::new(futures::future::ok(httpcodes::HTTPOk.build().chunked().json(userv).unwrap()))
}

The response ends up being the following

HTTP/1.1 200 OK
content-length: 011
content-type: application/json
date: Tue, 02 Jan 2018 20:55:42 GMT

Body
[{"id":1,"n

examples/tls

cargo run ok but error when use

thread 'arbiter:"a097acc7-af55-43b7-ba0f-61b256b68092":"actor"' panicked at 'called `Result::unwrap()` on an `Err` value: InvalidHeaderValueBytes(InvalidHeaderValue { _priv: () })', /checkout/src/libcore/result.rs:906:4
note: Run with `RUST_BACKTRACE=1` for a backtrace.

System is not running with actix 0.4.2 and actix-web 0.3.0 (minimal example)

So I updated actix and actix-web today by deleting my Cargo.lock and updating again.

I got this in my Cargo.toml

actix = { git = "https://github.com/actix/actix" }
actix-web = { git = "https://github.com/actix/actix-web" }

and this in my Cargo.lock

dependencies = [
 "actix 0.4.2 (git+https://github.com/actix/actix)",
 "actix-web 0.3.0 (git+https://github.com/actix/actix-web)",
...
]

Now this minimal example:

fn main() {
    let url = "localhost:8000";

    let sys = actix::System::new("test");
    let _server = HttpServer::new(
        || Application::new()
            .resource("/", |r| r.f(index))
              )
        .bind(url).unwrap()
        .start();

    let _ = sys.run();
}

fn index(req: HttpRequest) -> &'static str {
    "Hurray!"
}

gives me:

thread 'main' panicked at 'System is not running', /home/unmoving/.cargo/registry/src/github.com-1ecc6299db9ec823/actix-0.4.2/src/arbiter.rs:143:21
stack backtrace:
0: std::sys::unix::backtrace::tracing::imp::unwind_backtrace
at libstd/sys/unix/backtrace/tracing/gcc_s.rs:49
1: std::sys_common::backtrace::print
at libstd/sys_common/backtrace.rs:68
at libstd/sys_common/backtrace.rs:57
2: std::panicking::default_hook::{{closure}}
at libstd/panicking.rs:381
3: std::panicking::default_hook
at libstd/panicking.rs:397
4: std::panicking::rust_panic_with_hook
at libstd/panicking.rs:577
5: std::panicking::begin_panic
at /checkout/src/libstd/panicking.rs:538
6: actix::arbiter::Arbiter::system::{{closure}}
at /home/unmoving/.cargo/registry/src/github.com-1ecc6299db9ec823/actix-0.4.2/src/arbiter.rs:143
7: <std::thread::local::LocalKey>::try_with
at /checkout/src/libstd/thread/local.rs:377
8: <std::thread::local::LocalKey>::with
at /checkout/src/libstd/thread/local.rs:288
9: actix::arbiter::Arbiter::system
at /home/unmoving/.cargo/registry/src/github.com-1ecc6299db9ec823/actix-0.4.2/src/arbiter.rs:141
10: actix::arbiter::Arbiter::new
at /home/unmoving/.cargo/registry/src/github.com-1ecc6299db9ec823/actix-0.4.2/src/arbiter.rs:58
11: actix::arbiter::Arbiter::start
at /home/unmoving/.cargo/registry/src/github.com-1ecc6299db9ec823/actix-0.4.2/src/arbiter.rs:196
12: <actix_web::server::HttpServer<T, A, H, U>>::start_workers
at /home/unmoving/.cargo/git/checkouts/actix-web-02c803d355aed967/584d0c9/src/server.rs:286
13: <actix_web::server::HttpServer<tokio_core::net::tcp::TcpStream, std::net::addr::SocketAddr, H, U>>::start
at /home/unmoving/.cargo/git/checkouts/actix-web-02c803d355aed967/584d0c9/src/server.rs:353
14: rust_actix_test::main
at src/main.rs:89
15: std::rt::lang_start::{{closure}}
at /checkout/src/libstd/rt.rs:74
16: std::panicking::try::do_call
at libstd/rt.rs:59
at libstd/panicking.rs:480
17: __rust_maybe_catch_panic
at libpanic_unwind/lib.rs:102
18: std::rt::lang_start_internal
at libstd/panicking.rs:459
at libstd/panic.rs:365
at libstd/rt.rs:58
19: std::rt::lang_start
at /checkout/src/libstd/rt.rs:74
20: main
21: __libc_start_main
22: _start

I can't seem to find the reason. Any ideas?

Complete example now at: https://github.com/Unmoving/actix-web-test/tree/master

Actix module error is private

Trying to use the basic example again, I get the following:

error[E0603]: module `error` is private
 --> src/main.rs:8:5
  |
8 | use actix_web::error::Result;
  |     ^^^^^^^^^^^^^^^^^^^^^^^^

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.