Reputation: 10067
I have this below code, everything works expect the error_handler
. I'm not sure whats wrong. If I make post request with correct format I get 200 with response data. But on bad request I'm expecting 400 with JSON data which is not receiving. It just says 400, but doesn't return any error json data.
BAD REQ -> curl -X POST -H "Content-Type: application/json" -d '{"bad": "Someone was here"}' localhost:8080/send
status 400
{
error: String,
server_id: usize,
request_count: usize,
}
BAD REQ -> curl -X POST -H "Content-Type: application/json" -d '{"bad": "Someone was here"}' localhost:8080/send
status 400
I replaced .data
with .app_data
it works, but then it not able to find AppState
pub struct MessageApp {
pub port: u16,
}
impl MessageApp {
pub fn new(port: u16) -> Self {
Self{port}
}
pub async fn run(&self) -> std::io::Result<()> {
let messages = Arc::new(Mutex::new(vec![]));
println!("Starting http server: 127.0.0.1:{}", self.port);
HttpServer::new(move || {
App::new()
.data(AppState {
server_id: SERVER_COUNTER.fetch_add(1, Ordering::SeqCst),
request_count: Cell::new(0),
messages: messages.clone(),
})
.wrap(middleware::Logger::new(LOG_FORMAT))
.service(index)
.service(
web::resource("/send")
.data(
web::JsonConfig::default()
.limit(4096)
.error_handler(post_error)
)
.route(web::post().to(post))
)
.service(clear)
})
.bind(("127.0.0.1", self.port))?
.workers(8)
.run()
.await
}
}
error handler
fn post_error(err: JsonPayloadError, req: &HttpRequest) -> Error {
let extns = req.extensions();
let state = extns.get::<web::Data<AppState>>().unwrap();
let request_count = state.request_count.get() + 1;
state.request_count.set(request_count);
let post_error = PostError {
server_id: state.server_id,
request_count,
error: format!("{}", err),
};
InternalError::from_response(err, HttpResponse::BadRequest().json(post_error)).into()
}
Upvotes: 1
Views: 886
Reputation: 10067
As I mentioned before in possible solutions.
After taking help from author on github. He mentioned I need to move out .app_data
to get rid of this issue or move on to new version 3.0 which resolves this issue.
But using version 2.0.0 below is the solution:
HttpServer::new(move || {
App::new()
.data(AppState {
server_id: SERVER_COUNTER.fetch_add(1, Ordering::SeqCst),
request_count: Cell::new(0),
messages: messages.clone(),
})
.wrap(middleware::Logger::new(LOG_FORMAT))
.service(index)
.service(
web::resource("/send")
.app_data(
web::JsonConfig::default().limit(4096).error_handler(post_error)
)
.route(web::post().to(post))
)
.service(clear)
})
.bind(("127.0.0.1", self.port))?
.workers(8)
.run()
.await
As well the method for extracting AppState I was doing wrong. which fixed below inside post_error function.
fn post_error(err: JsonPayloadError, req: &HttpRequest) -> Error {
// let extns = req.extensions();
// let state = extns.get::<web::Data<AppState>>().unwrap();
let state = req.app_data::<web::Data<AppState>>().unwrap();
let request_count = state.request_count.get() + 1;
state.request_count.set(request_count);
let post_error = PostError {
server_id: state.server_id,
request_count,
error: format!("{}", err),
};
InternalError::from_response(err, HttpResponse::BadRequest().json(post_error)).into()
}
Upvotes: 3