-
Notifications
You must be signed in to change notification settings - Fork 1
/
http_message.ml
118 lines (98 loc) · 3.79 KB
/
http_message.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
(*
OCaml HTTP - do it yourself (fully OCaml) HTTP daemon
Copyright (C) <2002-2005> Stefano Zacchiroli <[email protected]>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Library General Public License as
published by the Free Software Foundation, version 2.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA
*)
open Http_common;;
open Http_constants;;
open Http_types;;
open Printf;;
(* remove all bindings of 'name' from hashtbl 'tbl' *)
let rec hashtbl_remove_all tbl name =
if not (Hashtbl.mem tbl name) then
raise (Header_not_found name);
Hashtbl.remove tbl name;
if Hashtbl.mem tbl name then hashtbl_remove_all tbl name
;;
class virtual message ~body ~headers ~version ~clisockaddr ~srvsockaddr =
let ((cliaddr, cliport), (srvaddr, srvport)) =
(Http_misc.explode_sockaddr clisockaddr,
Http_misc.explode_sockaddr srvsockaddr)
in
object (self)
val _contentsBuf = Buffer.create 1024
val _headers = Hashtbl.create 11
val mutable _version: version option = version
initializer
self#setBody body;
self#addHeaders headers
method version = _version
method setVersion v = _version <- Some v
method body = Buffer.contents _contentsBuf
method setBody c =
Buffer.clear _contentsBuf;
Buffer.add_string _contentsBuf c
method bodyBuf = _contentsBuf
method setBodyBuf b =
Buffer.clear _contentsBuf;
Buffer.add_buffer _contentsBuf b
method addBody s = Buffer.add_string _contentsBuf s
method addBodyBuf b = Buffer.add_buffer _contentsBuf b
method addHeader ~name ~value =
let name = String.lowercase_ascii name in
Http_parser_sanity.heal_header (name, value);
Hashtbl.add _headers name value
method addHeaders =
List.iter (fun (name, value) -> self#addHeader ~name ~value)
method replaceHeader ~name ~value =
let name = String.lowercase_ascii name in
Http_parser_sanity.heal_header (name, value);
Hashtbl.replace _headers name value
method replaceHeaders =
List.iter (fun (name, value) -> self#replaceHeader ~name ~value)
method removeHeader ~name =
let name = String.lowercase_ascii name in
hashtbl_remove_all _headers name
method hasHeader ~name =
let name = String.lowercase_ascii name in
Hashtbl.mem _headers name
method header ~name =
if not (self#hasHeader name) then raise (Header_not_found name);
let name = String.lowercase_ascii name in
String.concat ", " (List.rev (Hashtbl.find_all _headers name))
method headers =
List.rev
(Hashtbl.fold
(fun name _ headers -> (name, self#header ~name)::headers)
_headers
[])
method clientSockaddr = clisockaddr
method clientAddr = cliaddr
method clientPort = cliport
method serverSockaddr = srvsockaddr
method serverAddr = srvaddr
method serverPort = srvport
method private virtual fstLineToString: string
method toString =
self#fstLineToString ^ (* {request,status} line *)
crlf ^
(String.concat (* headers, crlf terminated *)
""
(List.map (fun (h,v) -> h ^ ": " ^ v ^ crlf) self#headers)) ^
(sprintf "Content-Length: %d" (String.length self#body)) ^ crlf ^
crlf ^
self#body (* body *)
method serialize outchan =
output_string outchan self#toString;
flush outchan
end