Fix Accept header parsing for proper content negotiation
- Parse Accept header from nginx request headers - Iterate through headers list to find Accept - Compare positions of application/json vs text/html - Return JSON if application/json appears first or alone - Default to HTML if no Accept header or text/html preferred Working: - curl -H 'Accept: application/json' → Returns JSON - curl (no header) → Returns HTML - curl -H 'Accept: text/html' → Returns HTML All endpoints support both formats via Accept header.
This commit is contained in:
@ -19,20 +19,43 @@ impl ContentType {
|
||||
|
||||
/// Determine response content type based on Accept header
|
||||
pub fn negotiate_content_type(request: &Request) -> ContentType {
|
||||
// For now, check query parameter as a simple way to request JSON
|
||||
// Full Accept header parsing would require more nginx FFI work
|
||||
let r: *const ngx::ffi::ngx_http_request_t = request.into();
|
||||
|
||||
unsafe {
|
||||
// Check args for format=json
|
||||
let args = (*r).args;
|
||||
if args.len > 0 && !args.data.is_null() {
|
||||
let args_slice = std::slice::from_raw_parts(args.data, args.len);
|
||||
if let Ok(args_str) = std::str::from_utf8(args_slice) {
|
||||
if args_str.contains("format=json") {
|
||||
return ContentType::Json;
|
||||
let headers_in = &(*r).headers_in;
|
||||
|
||||
// Iterate through all headers to find Accept
|
||||
let mut current = headers_in.headers.part.elts as *mut ngx::ffi::ngx_table_elt_t;
|
||||
let nelts = headers_in.headers.part.nelts;
|
||||
|
||||
for _ in 0..nelts {
|
||||
if current.is_null() {
|
||||
break;
|
||||
}
|
||||
|
||||
let header = &*current;
|
||||
if let Ok(key) = header.key.to_str() {
|
||||
if key.eq_ignore_ascii_case("accept") {
|
||||
if let Ok(value) = header.value.to_str() {
|
||||
let value_lower = value.to_lowercase();
|
||||
|
||||
// Check if JSON is preferred over HTML
|
||||
if value_lower.contains("application/json") {
|
||||
// If it's the only type or appears before text/html, use JSON
|
||||
let json_pos = value_lower.find("application/json");
|
||||
let html_pos = value_lower.find("text/html");
|
||||
|
||||
match (json_pos, html_pos) {
|
||||
(Some(_), None) => return ContentType::Json,
|
||||
(Some(j), Some(h)) if j < h => return ContentType::Json,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
current = current.add(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user