mirror of
https://tangled.org/tranquil.farm/tranquil-pds
synced 2026-08-04 00:16:06 +00:00
fix(lexicon): wildcard mime type handling and case insensitivity
This commit is contained in:
@@ -322,15 +322,7 @@ fn validate_blob_ref(
|
||||
|
||||
if let Some(ref accept) = lex_blob.accept {
|
||||
let mime_type = obj.get("mimeType").and_then(|v| v.as_str()).unwrap_or("");
|
||||
let matched = accept
|
||||
.iter()
|
||||
.any(|pattern| match pattern.strip_suffix("/*") {
|
||||
Some(prefix) => {
|
||||
mime_type.starts_with(prefix)
|
||||
&& mime_type.as_bytes().get(prefix.len()) == Some(&b'/')
|
||||
}
|
||||
None => mime_type == pattern,
|
||||
});
|
||||
let matched = accept.iter().any(|pattern| mime_type_matches_accept_pattern(mime_type, pattern));
|
||||
if !mime_type.is_empty() && !matched {
|
||||
return Err(LexValidationError::field(
|
||||
path,
|
||||
@@ -352,6 +344,34 @@ fn validate_blob_ref(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn mime_type_matches_accept_pattern(mime_type: &str, pattern: &str) -> bool {
|
||||
let normalized_mime = normalize_mime_for_match(mime_type);
|
||||
let normalized = normalize_mime_for_match(pattern);
|
||||
|
||||
if normalized == "*/*" || normalized == "*" {
|
||||
return true;
|
||||
}
|
||||
|
||||
match normalized.strip_suffix("/*") {
|
||||
Some(prefix) => {
|
||||
!prefix.is_empty()
|
||||
&& normalized_mime.starts_with(prefix)
|
||||
&& normalized_mime.len() > prefix.len()
|
||||
&& normalized_mime.as_bytes()[prefix.len()] == b'/'
|
||||
}
|
||||
None => normalized_mime == normalized,
|
||||
}
|
||||
}
|
||||
|
||||
fn normalize_mime_for_match(value: &str) -> String {
|
||||
value
|
||||
.split(';')
|
||||
.next()
|
||||
.unwrap_or("")
|
||||
.trim()
|
||||
.to_ascii_lowercase()
|
||||
}
|
||||
|
||||
fn validate_bytes(
|
||||
lex_bytes: &LexBytes,
|
||||
value: &serde_json::Value,
|
||||
@@ -733,6 +753,87 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_blob_accept_wildcard_allows_any_mime() {
|
||||
let lex_blob = LexBlob {
|
||||
accept: Some(vec!["*/*".to_string()]),
|
||||
max_size: None,
|
||||
};
|
||||
let blob = json!({
|
||||
"$type": "blob",
|
||||
"ref": { "$link": "bafyreiabcdef" },
|
||||
"mimeType": "application/gzip",
|
||||
"size": 123
|
||||
});
|
||||
|
||||
assert!(validate_blob_ref(&lex_blob, &blob, "root/entries/0/node/blob").is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_blob_accept_prefix_wildcard_matches_subtypes() {
|
||||
let lex_blob = LexBlob {
|
||||
accept: Some(vec!["image/*".to_string()]),
|
||||
max_size: None,
|
||||
};
|
||||
let blob = json!({
|
||||
"$type": "blob",
|
||||
"ref": { "$link": "bafyreiabcdef" },
|
||||
"mimeType": "image/png",
|
||||
"size": 123
|
||||
});
|
||||
|
||||
assert!(validate_blob_ref(&lex_blob, &blob, "blob").is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_blob_accept_exact_type_rejects_different_mime() {
|
||||
let lex_blob = LexBlob {
|
||||
accept: Some(vec!["image/png".to_string()]),
|
||||
max_size: None,
|
||||
};
|
||||
let blob = json!({
|
||||
"$type": "blob",
|
||||
"ref": { "$link": "bafyreiabcdef" },
|
||||
"mimeType": "application/gzip",
|
||||
"size": 123
|
||||
});
|
||||
|
||||
let err = validate_blob_ref(&lex_blob, &blob, "blob").unwrap_err();
|
||||
assert!(matches!(err, LexValidationError::InvalidField { .. }));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_blob_accept_exact_type_ignores_params_and_case() {
|
||||
let lex_blob = LexBlob {
|
||||
accept: Some(vec!["text/html".to_string()]),
|
||||
max_size: None,
|
||||
};
|
||||
let blob = json!({
|
||||
"$type": "blob",
|
||||
"ref": { "$link": "bafyreiabcdef" },
|
||||
"mimeType": "Text/HTML; charset=utf-8",
|
||||
"size": 123
|
||||
});
|
||||
|
||||
assert!(validate_blob_ref(&lex_blob, &blob, "blob").is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_blob_accept_prefix_ignores_params_and_case() {
|
||||
let lex_blob = LexBlob {
|
||||
accept: Some(vec!["text/*".to_string()]),
|
||||
max_size: None,
|
||||
};
|
||||
let blob = json!({
|
||||
"$type": "blob",
|
||||
"ref": { "$link": "bafyreiabcdef" },
|
||||
"mimeType": "TEXT/HTML; charset=UTF-8",
|
||||
"size": 123
|
||||
});
|
||||
|
||||
assert!(validate_blob_ref(&lex_blob, &blob, "blob").is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_validate_cross_schema_local_ref_in_union() {
|
||||
let registry = test_registry();
|
||||
|
||||
Reference in New Issue
Block a user