Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
20dff0d
Add more request URI tests for URI components
dsheets Apr 14, 2015
66ef98e
Improve request URI test error printing; correct 2 test cases
dsheets Apr 14, 2015
e6f2812
Fix request URI parsing with query strings
dsheets Apr 14, 2015
de29d2a
Fix Request-URI tests for Sec 5.1.2 compliance
dsheets Apr 14, 2015
c5a0d84
Test empty Request-URI (='/' by Sec 5.1)
dsheets Apr 14, 2015
76ae9a4
Make request URI parsing compliant with RFC 2616 Sec 5.2
dsheets Apr 14, 2015
b28e9f3
Add CONNECT and TRACE methods
dsheets Apr 14, 2015
c663c6a
Add CONNECT and OPTIONS request URI tests; test request URI path non-…
dsheets Apr 14, 2015
6b9ab30
Add request URI host:port test; fix parse_request_options_host test
dsheets Apr 14, 2015
6b61746
Fix request-URI of authority when CONNECT method used
dsheets Apr 14, 2015
59616fd
Fix OPTIONS * no Host test
dsheets Apr 14, 2015
595dfd6
Fix request URI empty paths
dsheets Apr 14, 2015
d444d6c
CHANGES
dsheets Apr 14, 2015
a6d153c
Revert "Add CONNECT and TRACE methods"
dsheets Apr 14, 2015
e9d99f3
Update the Code generate.ml script
dsheets Apr 14, 2015
f5c5110
Regenerate Code
dsheets Apr 14, 2015
383c838
Remove unnecessary test in generate.ml
dsheets Apr 14, 2015
a091734
Update CHANGES
dsheets Apr 15, 2015
39dfa05
Handle requests for * correctly
dsheets Apr 15, 2015
dbd6147
Turn on some useful warnings as errors
dsheets Apr 15, 2015
2c2f93a
Mark CONNECT and TRACE requests as without body
dsheets Apr 15, 2015
586d1b3
modify parse request URI tests to enable invalid request testing
dsheets Apr 15, 2015
7a639f3
Return invalid request message for bad request URIs
dsheets Apr 15, 2015
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
0.17.0 (trunk):

Compatibility breaking interface changes:
* CONNECT and TRACE methods added to Code. Exhaustive matches will need updating.

New features and bug fixes:
* Fix handling of request URI for query strings and CONNECT proxies
* Fix precedence of Host header when request-URI is absolute URI
* Fix request URI path to be non-empty except for * requests (e.g. OPTIONS *)

0.16.1 (2015-04-09):
New features and bug fixes:
* Fix handling of request paths starting with multiple slashes (#308)
Expand Down
1 change: 1 addition & 0 deletions _tags
Original file line number Diff line number Diff line change
Expand Up @@ -656,3 +656,4 @@ true: annot, bin_annot
<examples/async/receive_post.{native,byte}>: custom
# OASIS_STOP
true: principal, strict_sequence, debug
true: warn(@5@8@10@11@12@14@23@24@26@29)
29 changes: 24 additions & 5 deletions lib/code.ml
Original file line number Diff line number Diff line change
@@ -1,9 +1,24 @@
(* Auto-Generated by 'ocaml generate.ml' *)

open Sexplib.Std
type version = [ `HTTP_1_0 | `HTTP_1_1 | `Other of string ] with sexp
type version = [
| `HTTP_1_0
| `HTTP_1_1
| `Other of string
] with sexp

type meth = [ `GET | `POST | `HEAD | `DELETE | `PATCH | `PUT | `OPTIONS | `Other of string ] with sexp
type meth = [
| `GET
| `POST
| `HEAD
| `DELETE
| `PATCH
| `PUT
| `OPTIONS
| `TRACE
| `CONNECT
| `Other of string
] with sexp

type informational_status =
[ `Continue
Expand Down Expand Up @@ -89,13 +104,13 @@ type server_error_status =
| `Network_connect_timeout_error
] with sexp

type status =
[ informational_status
type status = [
| informational_status
| success_status
| redirection_status
| client_error_status
| server_error_status
] with sexp
] with sexp

type status_code = [`Code of int | status ] with sexp

Expand All @@ -121,6 +136,8 @@ let string_of_method: meth -> string = function
| `PATCH -> "PATCH"
| `PUT -> "PUT"
| `OPTIONS -> "OPTIONS"
| `TRACE -> "TRACE"
| `CONNECT -> "CONNECT"
| `Other s -> s

let method_of_string: string -> meth = function
Expand All @@ -131,6 +148,8 @@ let method_of_string: string -> meth = function
| "PATCH" -> `PATCH
| "PUT" -> `PUT
| "OPTIONS" -> `OPTIONS
| "TRACE" -> `TRACE
| "CONNECT" -> `CONNECT
| s -> `Other s

let compare_method a b =
Expand Down
33 changes: 23 additions & 10 deletions lib/code.mli
Original file line number Diff line number Diff line change
@@ -1,9 +1,24 @@
(* Auto-Generated by 'ocaml generate.ml' *)

open Sexplib.Std
type version = [ `HTTP_1_0 | `HTTP_1_1 | `Other of string ] with sexp

type meth = [ `GET | `POST | `HEAD | `DELETE | `PATCH | `PUT | `OPTIONS | `Other of string ] with sexp
type version = [
| `HTTP_1_0
| `HTTP_1_1
| `Other of string
] with sexp

type meth = [
| `GET
| `POST
| `HEAD
| `DELETE
| `PATCH
| `PUT
| `OPTIONS
| `TRACE
| `CONNECT
| `Other of string
] with sexp

type informational_status =
[ `Continue (** Client should continue with request *)
Expand All @@ -29,10 +44,8 @@ type success_status =

type redirection_status =
[ `Multiple_choices (** multiple options for the resource delivered *)
| `Moved_permanently (** this and all future requests directed to the
URI provided as the "Location" header. *)
| `Found (** temporary response to request found via alternative URI
provided by the "Location" header. *)
| `Moved_permanently (** this and all future requests directed to the given URI *)
| `Found (** temporary response to request found via alternative URI *)
| `See_other (** permanent response to request found via alternative URI *)
| `Not_modified (** resource has not been modified since last requested *)
| `Use_proxy (** content located elsewhere, retrieve from there *)
Expand Down Expand Up @@ -96,13 +109,13 @@ type server_error_status =
] with sexp
(** Server_error *)

type status =
[ informational_status
type status = [
| informational_status
| success_status
| redirection_status
| client_error_status
| server_error_status
] with sexp
] with sexp

type status_code = [`Code of int | status ] with sexp

Expand Down
63 changes: 51 additions & 12 deletions lib/request.ml
Original file line number Diff line number Diff line change
Expand Up @@ -102,30 +102,69 @@ module Make(IO : S.IO) = struct
end
| None -> return `Eof

let return_request headers meth uri version =
let encoding = Header.get_transfer_encoding headers in
return (`Ok { headers; meth; uri; version; encoding })

let read ic =
parse_request_fst_line ic >>= function
| `Eof -> return `Eof
| `Invalid reason as r -> return r
| `Ok (meth, path, version) ->
| `Ok (meth, "*", version) ->
Header_IO.parse ic >>= fun headers ->
let empty = Uri.of_string "" in
let uri =
match Header.get headers "host" with
| None -> Uri.with_path empty path
let uri = match Header.get headers "host" with
| None -> Uri.of_string ""
| Some host ->
let host_uri = Uri.of_string ("//"^host) in
let uri = Uri.with_path empty path in
let uri = Uri.with_host uri (Uri.host host_uri) in
Uri.with_port uri (Uri.port host_uri)
let uri = Uri.(with_host (of_string "") (host host_uri)) in
Uri.(with_port uri (port host_uri))
in
let encoding = Header.get_transfer_encoding headers in
return (`Ok { headers; meth; uri; version; encoding })
return_request headers meth uri version
| `Ok (`CONNECT as meth, authority, version) ->
Header_IO.parse ic >>= fun headers ->
let uri = Uri.of_string ("//"^authority) in
return_request headers meth uri version
| `Ok (meth, request_uri_s, version) ->
Header_IO.parse ic >>= fun headers ->
let uri = Uri.of_string request_uri_s in
match Uri.scheme uri with
| Some _ -> (* we have an absoluteURI *)
let uri = Uri.(
match path uri with "" -> with_path uri "/" | _ -> uri
) in
return_request headers meth uri version
| None ->
let len = String.length request_uri_s in
if len > 0 && String.get request_uri_s 0 <> '/'
then return (`Invalid "bad request URI")
else
let empty = Uri.of_string "" in
let empty_base = Uri.of_string "///" in
let pqs = match Stringext.split ~max:2 request_uri_s ~on:'?' with
| [] -> empty_base
| [path] ->
Uri.resolve "http" empty_base (Uri.with_path empty path)
| path::qs::_ ->
let path_base =
Uri.resolve "http" empty_base (Uri.with_path empty path)
in
Uri.with_query path_base (Uri.query_of_encoded qs)
in
let uri = match Header.get headers "host" with
| None -> Uri.(with_scheme (with_host pqs None) None)
| Some host ->
let host_uri = Uri.of_string ("//"^host) in
let uri = Uri.with_host pqs (Uri.host host_uri) in
Uri.with_port uri (Uri.port host_uri)
in
return_request headers meth uri version

(* Defined for method types in RFC7231 *)
let has_body req =
match req.meth with
| `GET | `HEAD | `DELETE -> `No
| `POST | `PUT | `PATCH | `OPTIONS | `Other _ -> Transfer.has_body req.encoding
| `GET | `HEAD | `DELETE | `CONNECT | `TRACE -> `No
| `POST | `PUT | `PATCH | `OPTIONS | `Other _ ->
Transfer.has_body req.encoding

let make_body_reader req ic = Transfer_IO.make_reader req.encoding ic
let read_body_chunk = Transfer_IO.read
Expand Down
Loading