Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • 14:46
    robjtede synchronize #2183
  • 14:46

    robjtede on msgbody-err

    static form extract future (#21… Merge branch 'master' into msgb… (compare)

  • 14:45
    robjtede synchronize #2183
  • 14:45

    robjtede on msgbody-err

    update changelog and fix msrv (compare)

  • 14:33
    robjtede synchronize #2183
  • 14:33

    robjtede on msgbody-err

    clippy (compare)

  • 14:29
    robjtede edited #2183
  • 14:29
    robjtede ready_for_review #2183
  • 14:28
    robjtede synchronize #2183
  • 14:28

    robjtede on msgbody-err

    clippy (compare)

  • 14:26
    robjtede synchronize #2183
  • 14:26

    robjtede on msgbody-err

    propagate into<error> change (compare)

  • 13:44
    robjtede synchronize #2183
  • 13:44

    robjtede on msgbody-err

    introduce encoder error type migrate some bounds to into<err… (compare)

  • 12:57

    github-actions[bot] on gh-pages

    Deploying to gh-pages from @ 0… (compare)

  • 12:54

    robjtede on master

    static form extract future (#21… (compare)

  • 12:54
    robjtede closed #2181
  • 12:49
    ibraheemdev synchronize #2181
  • 12:49
    ibraheemdev synchronize #2181
  • 10:33
    robjtede milestoned #2175
waled saleh mohammed
@waledsalah2016_twitter
hi guys - are there examples for actix web 4 ? - I want to migrate code to ver 3 to 4
1 reply
david-mcgillicuddy-moixa
@david-mcgillicuddy-moixa
I'm having a weird issue with tokio_serial (4.3) on actix (0.10) - when I call (and await on) tokio_serial::Serial::pair inside a tokio::Runtime::block_on inside a new thread, there are no issues and everything works as expected.
When I call (and await on in a ctx::spawn) it inside a Actor::start_in_arbiter closure, instead of 1) getting a panic about executors, 2) it working, 3) it hanging unpolled, it instead 4) it seems to create the Serial just fine but calling read on it returns Ok(0) instantly i.e. it's now closed.
Is there a known issue preventing interop with the actix runtime? I would like to avoid having a walled garden of tokio channels to a thread inside this massive actix application if at all possible.
2 replies
Benjamin
@benjaminweb:matrix.org
[m]
Hi, which way you advise me to implement ResponseError for bb8_tiberius::Error?
https://docs.rs/bb8-tiberius/0.5.1/bb8_tiberius/enum.Error.html
2 replies
Mehdi Aïssani
@maissani
Hi everyone i'm just asking if there is a possibiliy to get App Shared state inside Websocket ?
Sorry for this noob question but as far as i know i can get app_data from ws_index but how to pass it to the ws:start, if someone has an example .
1 reply
Mehdi Aïssani
@maissani
So it should be something like
pub async fn ws_index(r: HttpRequest, stream: web::Payload) -> Result<HttpResponse, Error> {
    let app_state = r.app_data::<web::Data<AppState>>().unwrap();
    println!("Shared State: {:?}", app_state.clone().configuration.clone().name);
    println!("{:?}", r);
    let res = ws::start(MyWebsocket::new(app_state.ws_clients), &r, stream);
    println!("{:?}", res);
    res
}
where ws_client can be something like ArcRwlock of an hashmap of websocket_clients
Mehdi Aïssani
@maissani
My aim is to provide a multiproducer consumer of data inside clients that as subscribed to a topic in order to send from other thread result of a computation in an another thread that is shared with actix_web.
So i will use it with mpsc :) @robjtede Thx bro 😎 .
enaut
@enaut:matrix.org
[m]
hey! I'm struggling to understand why I'm getting: "App data is not configured, to configure use App::data()" - Everything worked but on the slightest change of my impl actix_web::error::ResponseError for ServerError I get the App data not configured.
before I had:
impl actix_web::error::ResponseError for ServerError {
    fn error_response(&self) -> HttpResponse {
        match self {
            Self::Argonautica(_) => HttpResponse::InternalServerError().json("Argonautica Error"),
            Self::Database(e) => {
                HttpResponse::InternalServerError().json(format!("Database Error: {:?}", e))
            }
[…]
I changed that to:
impl actix_web::error::ResponseError for ServerError {
    fn error_response(&self) -> HttpResponse {
        match self {
            Self::Argonautica(_) => {
                //eprintln!("Argonautica Error happened: {:?}", e);
                HttpResponse::InternalServerError().json("test2")
            }
            _ => {
                //eprintln!("Argonautica Error happened: {:?}", e);
                HttpResponse::InternalServerError().json("test")
            } /*
              Self::Database(e) => {
                  //eprintln!("Database Error happened: {:?}", e);
                  HttpResponse::InternalServerError().json(&Self::render_error(
                      "Server Error",
                      "Database could not be accessed!",
                  ))
              }
I tried to simplify but I fail to understand what fails.
I'm greatful for any help or pointer
enaut
@enaut:matrix.org
[m]
huh actually that is not the problem... but what is then? how could I track down that error?
enaut
@enaut:matrix.org
[m]
Ok... that was hard to find... I did feed a Result<Tera> instead of Tera into the .data() - but that error could really be better!
In case someone reads this anyways :P
Voodlaz
@Voodlaz

Why does tokio block actix? When I use tokio I can't connect to the server via websockets. the tokio code is time_now() function

actix code:

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    time_now();
    let port = env::var("PORT")
        .unwrap_or_else(|_| "8081".to_string())
        .parse()
        .expect("PORT must be a number");
    println!("Server is working on {:?}", port);
    let chat_server = Lobby::default().start(); //create and spin up a lobby
    HttpServer::new(
        move || App::new()
            .service(start_connection_route)
            .data(chat_server.clone())
    )
        .bind(("0.0.0.0", port))
        .expect("Can not bind to port")
        .run()
        .await
}

tokio code:

pub async fn time_now() {

    let mut time: currentTime = currentTime {
        dayTime: "".to_string(),
        seconds: 0,
        minutes: 0,
        hours: 0,
        days: 0,
        shift: 0,
    };

    let mut one_second = Duration::from_secs(1);
    actix::spawn(async move {
    loop {
        std::thread::sleep(one_second);
        time.seconds += 1;
        if (time.seconds == 60) {time.minutes += 1; time.seconds = 0}
        if (time.minutes == 60) {time.hours += 1; time.minutes = 0}
        }
    });
}
3 replies
apilaszkiewicz
@apilaszkiewicz

Hi,

I want to achieve async sender with client that receives data in time, progressively.
the only way I have found to achieve it is with actix_utils::mpsc::channel()

it's based on: actix/actix-web#1066

as far as I understand the code, in each loop we are providing the sender Result<web::Bytes, actix_web::Error>
each loop copies the data into shared VecDeque between Sender and Reciver

the code is here: https://github.com/actix/actix-net/blob/1.0/actix-utils/src/mpsc.rs

Now what I would like to achieve is:

  • allocate custom buffer
  • use this buffer for receiving data from external source
  • use this buffer to write to external client
  • repeat until source has no bytes to offer
  • this enables me to have constant memory usage (correct me if I am wrong)
  • in case of a malicious client that read s 1 byte per second solution with very large data would be very problematic and might result with an OOM

The whole thing could be arranged by writing a custom Reciver<T>, Sender<T> just like in mpsc, they seem quite simple.

After digging deeper however I've realized that Receiver<T> has trait for futures::Stream which produces via poll_next Items
which I bet are consumed by next entities body::BodyStream

So Do I correctly assume that there is no method currently to achieve sending to client data progressively (which he receives in tempo) with a constant buffer?

33 replies
Voodlaz
@Voodlaz
How do I send websocket messages independently of messages from clients? I mean in impl StreamHandler, fn handler, match part. I don't really understand how to do it if client is not sending anything to the server. Probabbly make something else than match, but what?
10 replies
christian
@christian:matrix.boseck.net
[m]
Hello friendly developers, I am facing the issue that I need to clean up my Shared AppState if the application receives a sig_term. Has someone a hint for me how I can do this?
JosephBGerber
@JosephBGerber
Yo. I was wondering if I could get help with a quick question. I have a function that looks like this, but when I make a http request I am getting a 405 method not allowed error. I am making a POST request. What am I doing wrong?
#[post("/library/{id}/device)")]
async fn post_library_device(pool: web::Data<PgPool>, web::Path(id): web::Path<i32>) -> Result<impl Responder, Error> {
...
}
apilaszkiewicz
@apilaszkiewicz

apache bench keep alive with streaming response

FYI to avoid questions,

  • I do thing that ab is quite compact and eats very few resources compared to siege/wrk and most certainly jmeter ;)
  • absolutely no problem with curl/wget keep alive gets

assuming such simple server that outputs 10x blah

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

struct LiveStream {
    offset: i64,
}

impl LiveStream {
    pub fn new() -> LiveStream {
        LiveStream { offset: 10 }
    }
}
// https://gitter.im/actix/actix-web?at=5f94900e7be0d67d2794c0df
impl futures::stream::Stream for LiveStream {
    type Item = Result<web::Bytes, ()>;

    fn poll_next(mut self: std::pin::Pin<&mut Self>, cx: &mut futures::task::Context<'_>) -> futures::task::Poll<Option<Self::Item>> {
        if self.offset <= 0 {
            return futures::task::Poll::Ready(None);
        }
        let bytes = web::Bytes::from("blah");
        return futures::task::Poll::Ready(Some(Ok(bytes)));
    }
}

#[actix_web::get("/foo/{path}")]
fn foo(_: HttpRequest) -> HttpResponse {
    return HttpResponseBuilder::new(actix_web::http::StatusCode::OK)
        .header(actix_web::http::header::CONTENT_LENGTH, 10 * 4 as usize)
        .streaming(LiveStream::new());
}

#[actix_web::get("/bar/{path}")]
fn bar(_: HttpRequest) -> HttpResponse {
    let (tx, rx_body) = actix_utils::mpsc::channel::<actix_web::Result<web::Bytes, actix_web::Error>>();
    println!("starting response");
    actix_web::rt::spawn(async move {
        let mut offset: i64 = 10;

        while offset > 0 {
            offset -= 1;
            if let Err(_) = tx.send(Ok::<_, actix_web::Error>(web::Bytes::from("blah"))) {
                return;
            }
            futures_timer::Delay::new(std::time::Duration::from_micros(1)).await; // required
        }
        println!("response finished");
        drop(tx);
    });

    return HttpResponseBuilder::new(actix_web::http::StatusCode::OK).streaming(rx_body);
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    if std::env::var("RUST_LOG").is_err() {
        std::env::set_var("RUST_LOG", "actix_web=debug");
    }
    env_logger::init();
    let plain_server = HttpServer::new(|| App::new().wrap(middleware::Logger::default()).service(bar).service(foo))
        .keep_alive(16)
        .max_connection_rate(512)
        .max_connections(40000)
        .bind("0.0.0.0:8080")?
        .workers(600)
        .run();

    let servers = vec![plain_server];
    futures::future::join_all(servers).await;

    Ok(())
}

lets say you:
ab -k -c 1 -n 20 "http://127.0.0.1:8080/bar/xxx"
ab -k -c 1 -n 20 "http://127.0.0.1:8080/foo/xxx"
we receive log:

starting response
response finished
[2021-04-09T17:32:59Z INFO  actix_web::middleware::logger] 127.0.0.1:56404 "GET /bar/xxx HTTP/1.0" 200 40 "-" "ApacheBench/2.3" 0.001095
starting response
response finished
[2021-04-09T17:32:59Z INFO  actix_web::middleware::logger] 127.0.0.1:56404 "GET /bar/xxx HTTP/1.0" 200 40 "-" "ApacheBench/2.3" 0.000665
starting response
response finished
[2021-04-09T17:33:15Z INFO  actix_web::middleware::logger] 127.0.0.1:56416 "GET /bar/xxx HTTP/1.0" 200 40 "-" "ApacheBench/2.3" 0.001046
starting response
response finished
[2021-04-09T17:33:15Z INFO  actix_web::middleware::logger] 127.0.0.1:56416 "GET /bar/xxx HTTP/1.0" 200 40 "-" "ApacheBench/2.3" 0.000665
starting response
response finished
[2021-04-09T17:33:31Z INFO  actix_web::middleware::logger] 127.0.0.1:56440 "GET /bar/xxx HTTP/1.0" 200 40 "-" "ApacheBench/2.3" 0.001854
...

ab sems to be timeouting after 2nd response

similar handler based on impl futures::stream::Stream with poll_next has identical behaviour.

24 replies
RuRu92
@RuRu92

Hello guys, new to rust and antix.

Want to get some guidance on how to go about this situation.

What I want to use is this

struct DomainSettingProvider {
    realm: Domain,
    settings: Arc<HashMap<Domain, RefCell<Settings>>>
}

In Java, I would have provider injected through DI as a singleton.
In high load, this settings would be hold in memory, cached, and updated every so often.

This is to avoid hitting db consistently on every request. And not having a burden on memory creating and garbage collecting those objects.

How would I go about this in rust? I is this a right approach? How would I go about controlling that it can only be updated in one place and act like a cache?

14 replies
Sachin Maharana
@iSachinMaharana_twitter

hello! i am trying to implement post request for the webhook. i want to get the post reqwest body but i am facing the following error.

....
#[post("/mutate")]
async fn index(body: AdmissionReview<DynamicObject>) -> impl Responder {
    "Welcome!"
}
...
#[post("/mutate")]
   | ^^^^^^^^^^^^^^^^^^ the trait `FromRequest` is not implemented for `AdmissionReview<DynamicObject>

How can i fix this issue?

2 replies
Brandon Martin
@codedmart
I am not sure I understand how to use private cookies in actix_web? Is there a good place I can be pointed to for examples? My google fu is failing.
tranqin
@tranqins_twitter
I'm trying to insert a value into a mutex HashMap but it doesn't save. What am I doing wrong?
async fn get_hash(
    data: web::Data<AppState>,
    web::Path(data_id): web::Path<String>,
) -> impl Responder {
    let hash_map = data.hash.lock().unwrap();

    match hash_map.get(&data_id) {
        Some(info) => HttpResponse::Ok().body(info),
        None => HttpResponse::NotFound(),
    }
}

async fn add_data(data: web::Data<AppState>, text: String) -> impl Responder {
    let mut hash_map = data.hash.lock().unwrap();

    hash_map.insert("apple".to_string(), text);

    HttpResponse::Ok().body("done")
}
13 replies
brockelmore
@brockelmore
        let connector = awc::Connector::new().rustls(Arc::new(cfg)).finish();
        let client = awc::ClientBuilder::new().connector(connector).finish();
The above is my code, I am trying to use awc to create a websocket client with tls encryption. I just updated to latest betas and i get the following error:
error[E0308]: mismatched types
   --> router/src/lib.rs:382:58
    |
382 |           let client = awc::ClientBuilder::new().connector(connector).finish();
    |                                                            ^^^^^^^^^ expected struct `Connector`, found struct `actix_http::client::connector::ConnectorServicePriv`
was working prior to updating to the beta, but i didnt see a major change that should have affected this?
fakeshadow
@fakeshadow
let connector = awc::Connector::new().rustls(Arc::new(cfg));
brockelmore
@brockelmore
oh
fakeshadow
@fakeshadow
finish is called after you pass it to builder
This is to co op with the new added middleware feature
brockelmore
@brockelmore
thanks! that worked. appreciate it :)
fakeshadow
@fakeshadow
np
brockelmore
@brockelmore
never would have gotten there myself lol
Sachin Maharana
@iSachinMaharana_twitter
Hi. I want to disable the logs coming from actix web. it looks like this. Even removing .wrap(middleware::Logger::default()) still shows the logs from actix_web + my own logs.
#[actix_web::main]
async fn main() -> Result<(), anyhow::Error> {
    tracing_subscriber::fmt()
        .with_max_level(tracing::Level::INFO)
        .init();
...
HttpServer::new(|| {
        App::new()
            .wrap(middleware::Logger::default())
            .service(mutate)
            .service(health)
....

 Apr 14 12:08:56.061  INFO image_constraint: Started http server: 127.0.0.1:8443  
 Apr 14 12:08:56.063  INFO actix_server::builder: Starting 1 workers                                │
│ Apr 14 12:08:56.063  INFO actix_server::builder: Starting "actix-web-service-0.0.0.0:8443" service ││  on 0.0.0.0:8443                                                                                   ││
9 replies
jofas
@jofas

Hi all,

I don't know if this is the right place to discuss a feature request, but I have something I think might be an enhancement to actix-web.

Oftentimes, I use the fn x() -> Result<(), Error> pattern in my code for handling errors in functions that otherwise return void, e.g.

#[actix_web::main]
async fn main() -> Result<(), std::io::Error> { ... }

I haven't found anything in the documentation (whether this pattern has a name), but it is something I frequently encounter when working with rust.

I'd like to use the same pattern in my handlers, but actix_web::Responder is not implemented for (), so instead I use the less verbose async fn handler() -> Result<HttpResponse, Error> which returns Ok(HttpResponse::NoContent().finish()). Unfortunately rust does not allow me to implement Responder for () in my crates, so it must be implemented in actix-web directly. Would that be something other actix users would be interested in as well?

Kind regards,
Jonas

20 replies
BadConfig
@BadConfig
Hy guys, can you pls help me, I am trying to build a auth microservice gateway on actix-web and I am stuck with reverse proxy implementation. Is there something ready-to-use? I found smth for version 0.7 but now it is 3.x and I am not sure I can cope with implementation.
2 replies
Scott Lott
@only-cliches
This message was deleted
Matthew Briggs
@briggsnull_twitter
Hello, I'm trying to find out the status of 4.0. As I understand it, I need 4.0-beta to use tokio v1, but I'm not sure the timeline for 4.0 to be production-ready and out of beta.
6 replies
twiclo
@twiclo
I have a basic rest api backend written with actix-web. Here's an example of a common transaction: https://p.twil.cx/ufa.rs. Right now the add function just takes one DbObject but I'd like the front end to be able to pass an array of objects instead of one call for every object. I figured I could just have add take a vec<DbObject> and serde would require anything sent to it be in a [{..}] format instead of {..} but I'm looking for suggestions on a better way to do this. Requiring that a single object be wrapped in square brackets isn't ideal
JosephBGerber
@JosephBGerber
Hey I was hoping I could get some help with a problem I am having with actix/multipart.
7 replies
Alex Shapiro
@alex-shapiro
Hey, I just downloaded actix-web for the first time (4.0.0-beta.5) and I'm getting the following error
13 | use actix_service::{pipeline_factory, IntoServiceFactory, Service, ServiceFactory};
   |                     ^^^^^^^^^^^^^^^^ no `pipeline_factory` in the root
6 replies
Rob Ede
@robjtede
^ RE: yep sorry about this folks, will be rectified tomorrow... see thread for workaround
Alex Shapiro
@alex-shapiro
I'm looking into auth and I'm a little confused about whether to pick actix-identity or actix-session. When would I want to use one over the other? They seem to have overlapping use cases and some overlapping code around cookie handling.
1 reply
sleepy
@notsleepily
Hey, I was hoping I could get some help with getting actix-redis working, I'm not using it for the cookie store, I'm just trying to use it for the actor since it already has it implemented and that would be easier than creating my own actor. in the repo, I see it using resp_array! macro from redis-async crate but when I try that I get a mismatching type error (actix_redis::RespValue & redis_async::resp::RespValue) how is it being used in the actix-redis crate since I can't seem to use it? (This might be more of a rust issue than the crate itself, I just can't understand why it works in the crate)
18 replies
Björn Harrtell
@bjornharrtell

Getting:

   Compiling actix-files v0.6.0-beta.4
error[E0053]: method `error_response` has an incompatible type for trait
  --> /home/bjorn/.cargo/registry/src/github.com-1ecc6299db9ec823/actix-files-0.6.0-beta.4/src/error.rs:19:5

when attempting to depend on actix-web 4.0.0-beta.6 and actix-files 0.6.0-beta.4. Aren't those supposed to go togheter?

11 replies
Erik Funder Carstensen
@halvko
I'm looking at actix-session to see if i can update it to support actix-web:4.0.0-beta.6. When looking at the insert method of Session, and the InsertError definition, it seems like the error is meant to carry whatever value the user was trying to insert if something went wrong, but the insert method only requires value: impl Serialize. Do anyone have any thoughts on whether the value parameter should be constrained, or if the error shouldn`t carry the value which caused the error?
vidyli
@vidyli
19 replies
pub fn init() -> App {
    let frontend_origin = env::var("FRONTEND_ORIGIN").ok();

    let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
    let database_pool = new_pool(database_url).expect("Failed to create pool.");

    let message_handler = SyncArbiter::start(num_cpus::get(), move || MessageHandler {
        db_connection_pool: database_pool.clone()
    });

    let state = AppState {
        message_handler: message_handler.clone(),
    };

    App::new()
        .data(state)
        .wrap(Logger::default())
        .configure(route::routes)
}
I just want to return an App intance using function