Official Discord: https://discord.gg/NWpN5mmg3x | Powerful web framework for Rust | https://github.com/actix/actix-web/wiki/FAQ
robjtede on master
tweak migration document (compare)
github-actions[bot] on gh-pages
Deploying to gh-pages from @ 5… (compare)
github-actions[bot] on gh-pages
Deploying to gh-pages from @ f… (compare)
robjtede on test-v0.1.0-beta.13
robjtede on http-test-v3.0.0-beta.13
robjtede on master
prepare actix-http-test release… prepare actix-test release 0.1.… (compare)
github-actions[bot] on gh-pages
Deploying to gh-pages from @ a… (compare)
robjtede on actors-v4.0.0-beta.12
robjtede on master
prepare actix-web-actors releas… (compare)
robjtede on awc-v3.0.0-beta.21
robjtede on master
prepare awc release 3.0.0-beta.… (compare)
robjtede on http-v3.0.0-rc.3
robjtede on master
prepare actix-http release 3.0.… (compare)
std::thread::spawn(move || {
actix_web::rt::System::new().block_on(async move {
...
})
})
Consider an endpoint for post requests via post macro (https://docs.rs/actix-web/3.3.2/actix_web/attr.post.html). For example using #[post("/login")]
.
Is it possible to define the path elsewhere like const LOGIN: &str = "/login"
and use it in the post macro? I would like to collect all endpoints at one place.
I couldn't make it work. I tried #[post(LOGIN)]
and #[post("{}", LOGIN)]
as well as #[post("{LOGIN}")]
but without success.
Cheers
Hi everyone!
I'm getting thread panic in runtime after upgrading actix from 0.10 to either 0.11 or 0.12 with
thread 'main' panicked at '`spawn_local` called from outside of a `task::LocalSet`', /Users/stepan/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.12.0/src/task/local.rs:305:18
The only change I've made to my code is that I've removed the name argument from the actix::System::new
:
let sys = actix::System::new();
let db = SyncArbiter::start(3, move || DbActor(pool.clone()));
let coordinator: Addr<_> = CoordinatorActor::default().start();
HttpServer::new(move || {
let state = create_state(db.clone(), coordinator.clone(), config.clone());
let cors_middleware = Cors::default().allow_any_origin();
App::new()
.data(state)
.wrap(cors_middleware)
.wrap(middleware::NormalizePath::new(
middleware::normalize::TrailingSlash::MergeOnly,
))
.wrap(middleware::Logger::default())
.wrap(middleware::Compress::default())
.configure(router)
})
.bind(listen_addresses.clone())
.unwrap_or_else(|_| panic!("Can't bind to {}", listen_addresses))
.keep_alive(keep_alive)
.shutdown_timeout(0)
.workers(worker_processes)
.run();
sys.run()
My current dependencies are
actix = "0.12"
actix-cors = "0.5.4"
actix-rt = "1.1"
actix-web = "3.3.2"
What am I missing?
http v0.2.5
. It would now be Rust 1.46. If you want to keep the old MSRV 1.42 it should be as easy as adding an exact dep in your Cargo.toml: http = "=0.2.4"
.
tokio::fs::File
but that's because i implemented AsyncRead, AsyncWrite, and AsyncSeek on a wrapper of tokio_uring::fs::File
and reading and writing copies all the bytes around
Quick question: the actix docs for "shared mutable state" (here) suggest to use a Mutex from std::sync
to make types thread-safe. This seems like it could be problematic since Mutex can block the current thread.
I don't know much about the internals of Actix. Is this just not a problem?
Hello, I try to write a function that returns an App instance this is usefull for my integration tests.
I used the extract into method, function i my ide to get the function declaration.
This is what I got:
pub fn construct_app() -> App<impl ServiceFactory<Request=ServiceRequest, Response=ServiceResponse<StreamLog<_>>, Error=Error, Config=(), Service=_, InitError=(), Future=_>, StreamLog<_>> {
let pool = application_config.pg.create_pool(NoTls).unwrap();
let cors = Cors::permissive();
let app = App::new()
.wrap(
middleware::DefaultHeaders::new()
.header("Access-Control-Allow-Origin", "*")
.header("Access-Control-Allow-Headers", "*"))
.wrap(cors)
.wrap(Logger::default())
.service(hosts::all_hosts)
.service(hosts::new_host)
.service(hosts::get_host_by_id)
.service(hosts::save_host)
.service(hosts::delete_host)
.service(ips::list)
.service(ips::list_networks)
.service(macs::list)
.data(pool.clone());
return app;
}
Now rust cant resolve ServiceFactory and even if I add this dependency (what I don't want) other parameter are missing as well.
What are the actual type that would be returned I onestly don't know how to figure that out, or is there another way to do this.
Can you guys help me?
Hi, I have a question. I'm using #[post]
macro to generate register endpoint. Is it possible to somehow alias this endpoint with different path?
For example:
#[post("/a/path"]
fn test() -> impl Responser {
"Ok"
}
I'd like to have this test
function also exposed as /b/another/path
. Is it possible?
Hi all, I wrote these small piece of testing code to get access to the internal web:Data<T>:
#[actix_web::test]
async fn test_crawl_does_get_root_page_links() {
let set: HashSet<Url> = HashSet::default();
let (server, port) = spawn_server(set).unwrap();
let client = reqwest::Client::default();
let response = client
.get(format!("http://localhost:{}/", port))
.send()
.await
.expect("Failed to execute the request");
assert_eq!(response.text().await.unwrap(), root_body(&port));
server.stop(false).await;
}
fn spawn_server(set: HashSet<Url>) -> Result<(Server, u16), std::io::Error> {
let (server, port) = run_server(set).unwrap();
let _ = tokio::spawn(server.clone());
Ok((server, port))
}
fn run_server(set: HashSet<Url>) -> Result<(Server, u16), std::io::Error> {
let listener = TcpListener::bind("localhost:0").expect("Failed to bind to random port");
let port = listener.local_addr().unwrap().port();
let server = HttpServer::new(move || {
App::new()
.app_data(web::Data::new(set.clone()))
.app_data(web::Data::new(port.clone()))
.wrap_fn(|request, server| {
let app_state = request.app_data::<web::Data<HashSet<Url>>>();
let s = app_state.unwrap().get_ref();
println!("{}", s.len());
let fut = server.call(request);
async move {
let response = fut.await.unwrap();
Ok(response)
}
})
.wrap_fn(|request, server| {
let fut = server.call(request);
async move {
let response = fut.await.unwrap();
Ok(response)
}
})
.route("/", web::get().to(root_page))
})
.listen(listener)?
.run();
Ok((server, port))
}
The idea was to have two of these wrapped middleware running, with the first registered running last and thus containing the modifications of the first request, which doesn't do any modifications. However, I do not understand how this is supposed to work. Once the outer layer has run, I have a response. The inner layer doesn't know anything about this response and creates a response on its own. I am sure it is my understanding that is lacking, could someone explain to me how I get these to middlewares chained? Maybe the whole idea is flawed, but it is my first success to actually access web:Data<T> from a unit test. I am open to any suggestions ;-)
if they're connected to the same backend redis server then the auth with work across domains (assuming the cookies are set up correctly)
for subdomains, there is a Host guard (see docs) which would allow you to use the same AW server for multiple subdomains
otherwise, if you want to use separate servers, then a reverse proxy set up with Traefik or Nginx is a good route to explore
Hey guys,
I am trying to use SSE (server send events) with code below
when browser try to subscribe, it is just stuck till timeout. (req timeout)
#[get("/events")]
async fn event( broadcaster: web::Data<Mutex<Broadcaster>>) -> impl Responder {
println!("enter events locking broadcaster");
let mut map : HashMap<String, String> = HashMap::new();
map.insert("status".to_string() , "connected".to_string());
let rx = broadcaster.lock().unwrap().new_client( map );
println!("add newclient");
HttpResponse::Ok()
.header("content-type", "text/event-stream")
// .no_chunking(64)
.streaming(rx)
}
I trace it, it reach HttpResponse::Ok and stuck there
I wonder if the no_chunking is required?