Skip to content

Commit 5b99bed

Browse files
authored
CA-406403: Do not return HTTP 500 when Accept header can't be parsed (#6298)
/update_rrds returned a 500 HTTP code in some cases where the accept header was invalid. Now these cases are treated in the same way as a lack of Accept header.
2 parents caab0df + 7e64a26 commit 5b99bed

File tree

3 files changed

+26
-14
lines changed

3 files changed

+26
-14
lines changed

ocaml/libs/http-lib/http.mli

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ module Accept : sig
5555
val equal : t -> t -> bool
5656

5757
val of_string : string -> t list
58+
(** [of_string accept_hdr] Returns a list of weighted media types represented
59+
by [accept_hdr]. If [accept_hdr] can't be parsed, raises [Parse_failure].
60+
*)
5861

5962
val to_string : t -> string
6063

ocaml/libs/http-lib/http_test.ml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,15 @@ module Accept = struct
2424
let actual = Accept.of_string data in
2525
Alcotest.(check @@ list accept) data expected actual
2626

27+
let test_invalid () =
28+
let data = "text/html, image/gif, image/jpeg, ; q=.2, */; q=.2" in
29+
let expected = Accept.Parse_failure " " in
30+
let actual () =
31+
let _ = Accept.of_string data in
32+
()
33+
in
34+
Alcotest.check_raises "Raises Parse failure" expected actual
35+
2736
let test_accept_complex () =
2837
let data =
2938
"application/xml;q=0.9,text/html,application/xhtml+xml,*/*;q=0.8"
@@ -81,6 +90,7 @@ module Accept = struct
8190
[
8291
("Simple", `Quick, test_accept_simple)
8392
; ("Complex", `Quick, test_accept_complex)
93+
; ("Invalid", `Quick, test_invalid)
8494
]
8595
; preferred_tests
8696
]

ocaml/xcp-rrdd/bin/rrdd/rrdd_http_handler.ml

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,19 @@ let content_xml = content_hdr_of_mime mime_xml
1818

1919
let client_prefers_json req =
2020
let module Accept = Http.Accept in
21-
match req.Http.Request.accept with
22-
| None ->
23-
List.mem_assoc "json" req.Http.Request.query
24-
| Some accept -> (
25-
let accepted = Accept.of_string accept in
26-
let negotiated = Accept.preferred ~from:[mime_json; mime_xml] accepted in
27-
match negotiated with
28-
| x :: _ when String.equal x mime_json ->
29-
true
30-
| [] ->
31-
List.mem_assoc "json" req.Http.Request.query
32-
| _ ->
33-
false
34-
)
21+
let ( let* ) = Option.bind in
22+
let map_head f lst = List.nth_opt lst 0 |> Option.map f in
23+
let prefers_json =
24+
let* accept = req.Http.Request.accept in
25+
let* accepted =
26+
try Some (Accept.of_string accept) with Accept.Parse_failure _ -> None
27+
in
28+
Accept.preferred ~from:[mime_json; mime_xml] accepted
29+
|> map_head (fun x -> String.equal x mime_json)
30+
in
31+
Option.value
32+
~default:(List.mem_assoc "json" req.Http.Request.query)
33+
prefers_json
3534

3635
let content_type json = if json then content_json else content_xml
3736

0 commit comments

Comments
 (0)