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)
Sorry have another question, just wondering if i can improve the code ergonomics a little. Prior to upgrading i'd have code like this:
let (game, rounds) = block(move || {
let game = Game::find_by_id(&connection, game_id)?;
let rounds = Round::belonging_to(&game).load::<Round>(&connection)?;
Ok((game, rounds))
})
.await?;
Now with the changes to block(), it wraps the result for me. Since i want errors to return from the db operations there, i want to keep my own result. But this makes for a bit more code:
let data: Result<(Game, Vec<Round>), Error> = block(move || {
let game = Game::find_by_id(&connection, game_id)?;
let rounds = Round::belonging_to(&game).load::<Round>(&connection)?;
Ok((game, rounds))
})
.await?;
let (game, rounds) = data?;
HttpServer::new(move || {
let auth = HttpAuthentication::bearer(bearer_auth_validator);
App::new()
.app_data(state.clone())
.wrap(middleware::Logger::default())
.wrap(auth)
.service(put_job)
.service(next)
})
I got an application like this. I would like to put the auth
only with the two services, and add another service without the bearer authentication. How would I go about that?
Fiddled a bit with it, looks like
HttpServer::new(move || {
let auth = HttpAuthentication::bearer(bearer_auth_validator);
App::new()
.app_data(state.clone())
.wrap(middleware::Logger::default())
.service(metrics)
.service(web::scope("").wrap(auth).service(next).service(put_job))
})
works
res.map_body(...)
(line 321) which you can use to wrap the stream in your own struct with other bits you'll need when the stream is done
I was wondering what the best way of encrypting proxied data through websockets would be.
I'm essentially making a proxy, but I don't want to be able to see the data.
I was thinking about implementing a TLS-like handshake, but then the server still gets both certificates and the encryption is breakable.
I'm going to be sending passwords and usernames through the network and the only server-side processing I'm going to be doing is mapping WSS streams to a random id.
.guard(guard::fn_guard(|req| is_logged(req.get_session())))
I need to setup a connection bb8 connection pool inside actor startup. The bb8 pool builder is async call whereas started fn in Actor is sync. How do I get this initialization done?
Here is my code:
#[derive(Debug, Default)]
pub struct RedisActor {
pub pool: Option<Pool<RedisConnectionManager>>,
}
impl Actor for RedisActor {
type Context = Context<Self>;
fn started(&mut self, ctx: &mut Self::Context) {
let manager = RedisConnectionManager::new("redis://localhost").unwrap();
self.pool = Option::from(bb8::Pool::builder()
.max_size(5)
.build(manager).await.unwrap());
}
}
The line await is failing because I can't use await inside normal function. Can someone help how to do this kind of pool initialization inside the actor start
Having two problems with migration to v4.
fn render_404() -> HttpResponse {
let body = serde_json::to_string(&ErrorResponse {
code: 404,
message: "Endpoint not found".into(),
})
.unwrap();
HttpResponse::with_body(StatusCode::NOT_FOUND, BoxBody::new(body))
}
App::new()
// ....
.default_service(web::route().to(render_404))
I get error:
the trait
Handler<_>
is not implemented forfn() -> actix_web::HttpResponse {render_404}
Secondly, I get this error on my own middleware:
error[E0271]: type mismatch resolving `<KeycloakAuth<[closure@src/main.rs:162:33: 165:14]> as Transform<actix_web::scope::ScopeService, ServiceRequest>>::Response == ServiceResponse`
--> src/main.rs:206:35
|
206 | ... .wrap(either_middleware::OneOrAnother::new(keycloak_auth.clone()))
| ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `EitherBody`, found struct `BoxBody`
| |
| required by a bound introduced by this call
|
= note: expected struct `ServiceResponse<EitherBody<_>>`
found struct `ServiceResponse<BoxBody>`
note: required because of the requirements on the impl of `Transform<actix_web::scope::ScopeService, ServiceRequest>` for `OneOrAnother<KeycloakAuth<[closure@src/main.rs:162:33: 165:14]>, KeycloakError>`
--> src/either_middleware.rs:22:22
|
22 | impl<S, Req, T1, T2> Transform<S, Req> for OneOrAnother<T1, T2>
| ^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^
The whole middleware is here: https://bpa.st/HXXQ
Wondering what has changed that made these two things now not work
ah I figured that of the two middlewares T1 and T2, they respectively have Response = EitherBody and BoxBody. And then there's this bound
T1: Transform<S, Req, Response = S::Response, Error = S::Error>,
T2: Transform<S, Req, Response = S::Response, Error = S::Error, InitError = T1::InitError>,
Which says that they need to equal S::Response.
I don't really know what S::Response is... I mean all we know is S: Service<Req> + 'static,
. Actually I see from https://docs.rs/actix-web/latest/actix_web/struct.App.html#method.wrap that S = T::Service
(where S is the generic argument in my middleware and T the generic argument in App). Still it's a difficult puzzle...
impl<S, Req, T1, T2, R> Transform<S, Req> for OneOrAnother<T1, T2>
where
S: Service<Req> + 'static,
T1: Transform<S, Req, Response = R, Error = S::Error>,
T2: Transform<S, Req, Response = R, Error = S::Error, InitError = T1::InitError>,
T1::Future: 'static,
type Response = EitherBody<T1::Response, T2::Response>;
My next problem is that Etiher from actix-utils
impls Future like this:
impl<L, R> Future for Either<L, R>
where
L: Future,
R: Future<Output = L::Output>,
{
type Output = L::Output;
I don't understand why it doesn't have type Output = either::Either<L::Output, R::Output>;
.
Can someone here enlighten me whether a PR for this would be desired? Meanwhile, I'll try to find a workaround for my own use case
@robjtede:matrix.org Am I going in the right direction here? Let's just look at the signatures and bounds:
impl<S, Req, T1, T2, Response1, Response2> Transform<S, Req> for OneOrAnother<T1, T2>
where
S: Service<Req> + 'static,
T1: Transform<S, Req, Response = ServiceResponse<Response1>, Error = Error>,
T2: Transform<
S,
Req,
Response = ServiceResponse<Response2>,
Error = Error,
InitError = T1::InitError,
>,
T1::Future: 'static,
T1::InitError: 'static,
T1::Transform: 'static,
T2::Future: 'static,
T2::InitError: 'static,
T2::Transform: 'static,
{
type Response = ServiceResponse<EitherBody<Response1, Response2>>;
type Error = Error;
type Transform = OneOrAnotherMiddleware<T1::Transform, T2::Transform>;
type InitError = T1::InitError;
type Future = LocalBoxFuture<'static, Result<Self::Transform, Self::InitError>>;
pub enum OneOrAnotherMiddleware<T1, T2> {
Left(T1),
Right(T2),
}
impl<T1, T2, Response1, Response2, Req> Service<Req> for OneOrAnotherMiddleware<T1, T2>
where
T1: Service<Req, Response = ServiceResponse<Response1>, Error = Error>,
T2: Service<Req, Response = ServiceResponse<Response2>, Error = Error>,
{
type Response = ServiceResponse<EitherBody<Response1, Response2>>;
type Error = Error;
type Future =
std::pin::Pin<Box<dyn std::future::Future<Output = Result<Self::Response, Self::Error>>>>;
I just made it compile, but it doesn't feel completely right.
I just addedd a lot of bounds and generics (Response1
, Response2
) mainly because of the requirement that all Response
types need to be ServiceResponse<_>
. I didn't make the implementation right now but from the bounds and signatures I think we can deduce that the implementation would sort of.. ignore the ServiceResponse it gets from the inner middlewares, and wrap it anew..? But I'm really in doubt about that.
Hello together :) I'm currently trying to implement an auth-middleware, which sets a user's data as the request's extension. To do so it extracts an auth-token from the requests cookie and queries against a r2d2 postgres-pool in order to determine, whether this token belongs to a user. Following the docs, I passed a clone of the pool to app_data. After setting app_data, I attached my middleware. However, it fails to extract the Pool, meaning I can not use it in its implementation of "call". I checked multiple times that the pool's type while setting app_data matches the type during its extraction.
So my question is:
Is app_data supposed to be available within the context of a middleware, or are there other caveats I'm not aware of?
Thanks in advance! :)