makes the content-type mandatory for every routes

This commit is contained in:
Tamo 2021-10-05 13:30:53 +02:00
parent ddbcf449da
commit c6d107a05f
No known key found for this signature in database
GPG Key ID: 20CD8020AFA88D69
4 changed files with 61 additions and 14 deletions

View File

@ -11,17 +11,21 @@ use serde::{Deserialize, Serialize};
#[derive(Debug, thiserror::Error)]
pub enum MeilisearchHttpError {
#[error("A Content-Type header is missing. Accepted values for the Content-Type header are: \"application/json\", \"application/x-ndjson\", \"text/csv\"")]
MissingContentType,
#[error("The Content-Type \"{0}\" is invalid. Accepted values for the Content-Type header are: \"application/json\", \"application/x-ndjson\", \"text/csv\"")]
InvalidContentType(String),
#[error("A Content-Type header is missing. Accepted values for the Content-Type header are: {}",
.0.iter().map(|s| format!("\"{}\"", s)).collect::<Vec<_>>().join(", "))]
MissingContentType(Vec<String>),
#[error(
"The Content-Type \"{0}\" is invalid. Accepted values for the Content-Type header are: {}",
.1.iter().map(|s| format!("\"{}\"", s)).collect::<Vec<_>>().join(", ")
)]
InvalidContentType(String, Vec<String>),
}
impl ErrorCode for MeilisearchHttpError {
fn error_code(&self) -> Code {
match self {
MeilisearchHttpError::MissingContentType => Code::MissingContentType,
MeilisearchHttpError::InvalidContentType(_) => Code::InvalidContentType,
MeilisearchHttpError::MissingContentType(_) => Code::MissingContentType,
MeilisearchHttpError::InvalidContentType(_, _) => Code::InvalidContentType,
}
}
}

View File

@ -11,7 +11,10 @@ pub mod routes;
use std::path::Path;
use std::time::Duration;
use crate::error::{MeilisearchHttpError, ResponseError};
use crate::extractors::authentication::AuthConfig;
use actix_web::error::JsonPayloadError;
use http::header::CONTENT_TYPE;
pub use option::Opt;
use actix_web::web;
@ -98,9 +101,28 @@ pub fn configure_data(config: &mut web::ServiceConfig, data: MeiliSearch, opt: &
.app_data(data)
.app_data(
web::JsonConfig::default()
.limit(http_payload_size_limit)
.content_type(|_mime| true) // Accept all mime types
.error_handler(|err, _req| error::payload_error_handler(err).into()),
.content_type(|mime| mime == mime::APPLICATION_JSON)
.error_handler(|err, req| match err {
JsonPayloadError::ContentType if req.headers().get(CONTENT_TYPE).is_none() => {
ResponseError::from(MeilisearchHttpError::MissingContentType(vec![
mime::APPLICATION_JSON.to_string(),
]))
.into()
}
JsonPayloadError::ContentType => {
ResponseError::from(MeilisearchHttpError::InvalidContentType(
req.headers()
.get(CONTENT_TYPE)
.unwrap()
.to_str()
.unwrap_or("unknown")
.to_string(),
vec![mime::APPLICATION_JSON.to_string()],
))
.into()
}
err => error::payload_error_handler(err).into(),
}),
)
.app_data(PayloadConfig::new(http_payload_size_limit))
.app_data(
@ -180,6 +202,7 @@ macro_rules! create_app {
use actix_web::middleware::TrailingSlash;
use actix_web::App;
use actix_web::{middleware, web};
use meilisearch_http::error::{MeilisearchHttpError, ResponseError};
use meilisearch_http::routes;
use meilisearch_http::{configure_auth, configure_data, dashboard};

View File

@ -181,9 +181,24 @@ async fn document_addition(
Some("application/x-ndjson") => DocumentAdditionFormat::Ndjson,
Some("text/csv") => DocumentAdditionFormat::Csv,
Some(other) => {
return Err(MeilisearchHttpError::InvalidContentType(other.to_string()).into())
return Err(MeilisearchHttpError::InvalidContentType(
other.to_string(),
vec![
"application/json".to_string(),
"application/x-ndjson".to_string(),
"application/csv".to_string(),
],
)
.into())
}
None => {
return Err(MeilisearchHttpError::MissingContentType(vec![
"application/json".to_string(),
"application/x-ndjson".to_string(),
"application/csv".to_string(),
])
.into())
}
None => return Err(MeilisearchHttpError::MissingContentType.into()),
};
let update = Update::DocumentAddition {

View File

@ -67,7 +67,6 @@ async fn add_documents_test_no_content_types() {
/// any other content-type is must be refused
#[actix_rt::test]
#[ignore]
async fn add_documents_test_bad_content_types() {
let document = json!([
{
@ -91,8 +90,14 @@ async fn add_documents_test_bad_content_types() {
let res = test::call_service(&app, req).await;
let status_code = res.status();
let body = test::read_body(res).await;
assert_eq!(status_code, 405);
assert!(body.is_empty());
let response: Value = serde_json::from_slice(&body).unwrap_or_default();
assert_eq!(status_code, 415);
assert_eq!(
response["message"],
json!(
r#"The Content-Type "text/plain" is invalid. Accepted values for the Content-Type header are: "application/json", "application/x-ndjson", "application/csv""#
)
);
}
#[actix_rt::test]