Actix-Web reports "App data is not configured" when processing a file upload
Asked Answered
J

5

7

I'm using the Actix framework to create a simple server and I've implemented a file upload using a simple HTML frontend.

use actix_web::web::Data;
use actix_web::{middleware, web, App, HttpResponse, HttpServer};
use std::cell::Cell;

// file upload functions, the same as you can find it under the 
// actix web documentation:
// https://github.com/actix/examples/blob/master/multipart/src/main.rs :
mod upload; 


fn index() -> HttpResponse {
    let html = r#"<html>
            <head><title>Upload Test</title></head>
            <body>
                <form target="/" method="post" enctype="multipart/form-data">
                    <input type="file" name="file"/>
                    <input type="submit" value="Submit"></button>
                </form>
            </body>
        </html>"#;

    HttpResponse::Ok().body(html)
}

#[derive(Clone)]
pub struct AppState {        
    counter: Cell<usize>,        
}

impl AppState {
    fn new() -> Result<Self, Error> {
        // some stuff
        Ok(AppState {
            counter: Cell::new(0usize),
        })
    }
}
fn main() {

    let app_state = AppState::new().unwrap();

    println!("Started http server: http://127.0.0.1:8000");

    HttpServer::new(move || {
        App::new()
            .wrap(middleware::Logger::default())
            .service(
                web::resource("/")
                    .route(web::get().to(index))
                    .route(web::post().to_async(upload::upload)),
            )
            .data(app_state.clone())
    })
    .bind("127.0.0.1:8000")
    .unwrap()
    .run()
    .unwrap();
}

Running the server works fine, but when I submit the file upload, it says:

App data is not configured, to configure use App::data()

I don't know what to do.

Jacobian answered 13/5, 2019 at 17:33 Comment(3)
Please review how to create a minimal reproducible example and then edit your question to include it. We cannot tell what crates (and their versions), types, traits, fields, etc. are present in the code. The modules upload, config and geohub_database are undefined — are they required to demo the problem? Remove or provide them. Try to reproduce your error on the Rust Playground if possible, otherwise in a brand new Cargo project. There are Rust-specific MCVE tips you can use to reduce your original code for posting here.Glans
Links to code are fine as additional information, but they are not sufficient on their own. Please edit your question to contain a minimal reproducible example.Glans
Is the logger required to reproduce the problem? If not, remove it. Is failure required to reproduce the problem? If not, remove it. We really do mean Minimal when we ask you to create a minimal reproducible example.Glans
B
4

I asked people in the rust-jp community to tell you the correct answer.

Use Arc outer HttpServer.

/*
~~~Cargo.toml
[package]
name = "actix-data-example"
version = "0.1.0"
authors = ["ncaq <[email protected]>"]
edition = "2018"

[dependencies]
actix-web = "1.0.0-rc"
env_logger = "0.6.0"
~~~
 */

use actix_web::*;
use std::sync::*;

fn main() -> std::io::Result<()> {
    std::env::set_var("RUST_LOG", "actix_web=trace");
    env_logger::init();

    let data = Arc::new(Mutex::new(ActixData::default()));
    HttpServer::new(move || {
        App::new()
            .wrap(middleware::Logger::default())
            .data(data.clone())
            .service(web::resource("/index/").route(web::get().to(index)))
            .service(web::resource("/create/").route(web::get().to(create)))
    })
    .bind("0.0.0.0:3000")?
    .run()
}

fn index(actix_data: web::Data<Arc<Mutex<ActixData>>>) -> HttpResponse {
    println!("actix_data: {:?}", actix_data);
    HttpResponse::Ok().body(format!("{:?}", actix_data))
}

fn create(actix_data: web::Data<Arc<Mutex<ActixData>>>) -> HttpResponse {
    println!("actix_data: {:?}", actix_data);
    actix_data.lock().unwrap().counter += 1;
    HttpResponse::Ok().body(format!("{:?}", actix_data))
}

/// actix-webが保持する状態
#[derive(Debug, Default)]
struct ActixData {
    counter: usize,
}

This post report to upstream. Official document data cause App data is not configured, to configure use App::data() · Issue #874 · actix/actix-web

Bimetallic answered 30/5, 2019 at 7:47 Comment(0)
S
2

Faced a similar error: Internal Server Error: "App data is not configured, to configure use App::data()"

from: https://github.com/actix/examples/blob/master/state/src/main.rs

  1. For global shared state, we wrap our state in a actix_web::web::Data and move it into the factory closure. The closure is called once-per-thread, and we clone our state and attach to each instance of the App with .app_data(state.clone()).

Thus:

impl AppState {
    fn new() -> actix_web::web::Data<AppState> {
        actix_web::web::Data<AppState> {
            counter: Cell::new(0usize),
        }
    }
}

...and in factory closure:

... skip ...
HttpServer::new(move || {
    App::new()
        .app_data(AppState::new().clone())
... skip ...
  1. For thread-local state, we construct our state within the factory closure and attach to the app with .data(state).

Thus:

... skip ...
HttpServer::new(move || {
    let app_state = Cell::new(0usize);
    App::new()
        .data(app_state)
... skip ...
Slipover answered 1/2, 2021 at 13:18 Comment(0)
U
1

Instead of:

App::data(app_state.clone())

You should use:

App::app_data(app_state.clone())
Usance answered 31/1, 2021 at 6:33 Comment(0)
P
0

If you call a function that has any parameter which doesn't match the HttpServer app data it will give you the same error.

For example, in this case, the &Client needed to be a Client.

pub fn index(client: web::Data<&Client>() {
// ...

}
Peppie answered 4/2, 2022 at 7:12 Comment(0)
D
-2

You have to register your data before you can use it:

App::new().data(AppState::new())
Datary answered 13/5, 2019 at 21:3 Comment(1)
It appears that the OP has already done that: .data(app_state.clone()). What is incorrect about their invocation?Glans

© 2022 - 2024 — McMap. All rights reserved.