mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-30 08:49:26 +00:00
fix(table-catalog): route read_bounded_json_body errors through ApiError to hold s3s ratchet (#5759)
The namespace REST contracts PR (#5745) added 7 new s3_error! invocations in read_bounded_json_body, pushing the s3s footprint counter from 1687 to 1693 and violating the ratchet baseline. Replace those calls with ApiError::invalid_request() (gateway-side error abstraction, rustfs/backlog#1677 F1, rustfs/backlog#1733) and lower the baseline from 1687 to 1686. - Add ApiError::invalid_request(message) constructor to rustfs/src/error.rs - Replace 7 s3_error! calls in read_bounded_json_body with S3Error::from(ApiError) - Lower S3_ERROR_LINES_BASELINE from 1687 to 1686 Verification: - make pre-commit: all guard scripts + fmt-check + quick-check passed - make clippy-check: passed - cargo test table_catalog + admin handler tests: 406/406 passed - s3s-e2e: 27/27 passed
This commit is contained in:
@@ -21,6 +21,7 @@ use crate::admin::{
|
|||||||
router::{AdminOperation, Operation, S3Router},
|
router::{AdminOperation, Operation, S3Router},
|
||||||
};
|
};
|
||||||
use crate::auth::{check_key_valid, get_session_token};
|
use crate::auth::{check_key_valid, get_session_token};
|
||||||
|
use crate::error::ApiError;
|
||||||
use crate::server::{RemoteAddr, TABLE_CATALOG_COMPAT_PREFIX, TABLE_CATALOG_PREFIX};
|
use crate::server::{RemoteAddr, TABLE_CATALOG_COMPAT_PREFIX, TABLE_CATALOG_PREFIX};
|
||||||
use crate::table_catalog::{DEFAULT_WAREHOUSE_ID, TableCatalogStore};
|
use crate::table_catalog::{DEFAULT_WAREHOUSE_ID, TableCatalogStore};
|
||||||
use http::{HeaderMap, HeaderValue, StatusCode};
|
use http::{HeaderMap, HeaderValue, StatusCode};
|
||||||
@@ -1148,21 +1149,21 @@ async fn read_bounded_json_body<T: DeserializeOwned>(
|
|||||||
if let Some(content_length) = headers.get(http::header::CONTENT_LENGTH) {
|
if let Some(content_length) = headers.get(http::header::CONTENT_LENGTH) {
|
||||||
let content_length = content_length
|
let content_length = content_length
|
||||||
.to_str()
|
.to_str()
|
||||||
.map_err(|_| s3_error!(InvalidRequest, "Content-Length must be valid ASCII"))?
|
.map_err(|_| S3Error::from(ApiError::invalid_request("Content-Length must be valid ASCII")))?
|
||||||
.parse::<usize>()
|
.parse::<usize>()
|
||||||
.map_err(|_| s3_error!(InvalidRequest, "Content-Length must be a non-negative integer"))?;
|
.map_err(|_| S3Error::from(ApiError::invalid_request("Content-Length must be a non-negative integer")))?;
|
||||||
if content_length > max_size {
|
if content_length > max_size {
|
||||||
return Err(s3_error!(InvalidRequest, "{operation} request body is too large"));
|
return Err(S3Error::from(ApiError::invalid_request(format!("{operation} request body is too large"))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let body = tokio::time::timeout(timeout, input.store_all_limited(max_size))
|
let body = tokio::time::timeout(timeout, input.store_all_limited(max_size))
|
||||||
.await
|
.await
|
||||||
.map_err(|_| s3_error!(InvalidRequest, "timed out reading {operation} request body"))?
|
.map_err(|_| S3Error::from(ApiError::invalid_request(format!("timed out reading {operation} request body"))))?
|
||||||
.map_err(|err| s3_error!(InvalidRequest, "failed to read request body: {}", err))?;
|
.map_err(|err| S3Error::from(ApiError::invalid_request(format!("failed to read request body: {err}"))))?;
|
||||||
if body.is_empty() {
|
if body.is_empty() {
|
||||||
return Err(s3_error!(InvalidRequest, "request body is required"));
|
return Err(S3Error::from(ApiError::invalid_request("request body is required")));
|
||||||
}
|
}
|
||||||
serde_json::from_slice(&body).map_err(|err| s3_error!(InvalidRequest, "invalid JSON: {}", err))
|
serde_json::from_slice(&body).map_err(|err| S3Error::from(ApiError::invalid_request(format!("invalid JSON: {err}"))))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn read_json_body_or_default<T>(mut input: Body) -> S3Result<T>
|
async fn read_json_body_or_default<T>(mut input: Body) -> S3Result<T>
|
||||||
|
|||||||
@@ -43,6 +43,14 @@ impl ApiError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn invalid_request(message: impl std::fmt::Display) -> Self {
|
||||||
|
ApiError {
|
||||||
|
code: S3ErrorCode::InvalidRequest,
|
||||||
|
message: message.to_string(),
|
||||||
|
source: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn other<E>(error: E) -> Self
|
pub fn other<E>(error: E) -> Self
|
||||||
where
|
where
|
||||||
E: std::fmt::Display + Into<Box<dyn std::error::Error + Send + Sync>>,
|
E: std::fmt::Display + Into<Box<dyn std::error::Error + Send + Sync>>,
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ cd "$(dirname "$0")/.."
|
|||||||
|
|
||||||
# Baselines verified on 2026-08-05. Lower-only; see header.
|
# Baselines verified on 2026-08-05. Lower-only; see header.
|
||||||
S3S_IMPORT_FILES_BASELINE=236
|
S3S_IMPORT_FILES_BASELINE=236
|
||||||
S3_ERROR_LINES_BASELINE=1687
|
S3_ERROR_LINES_BASELINE=1686
|
||||||
|
|
||||||
TMP_DIR="$(mktemp -d)"
|
TMP_DIR="$(mktemp -d)"
|
||||||
trap 'rm -rf "$TMP_DIR"' EXIT
|
trap 'rm -rf "$TMP_DIR"' EXIT
|
||||||
|
|||||||
Reference in New Issue
Block a user