X-Git-Url: http://matita.cs.unibo.it/gitweb/?a=blobdiff_plain;f=helm%2FDEVEL%2Focaml-http%2Fhttp_daemon.ml;h=bcf3da81ac51aa725994393c57b3590eb065387d;hb=34a1ea600a101bec4e1cdc40bfbdec93d503fa51;hp=c26d284ead6180f0b306011cd95852723b7845c1;hpb=697d0d8857366485238a67386d0ce8f18404ac42;p=helm.git diff --git a/helm/DEVEL/ocaml-http/http_daemon.ml b/helm/DEVEL/ocaml-http/http_daemon.ml index c26d284ea..bcf3da81a 100644 --- a/helm/DEVEL/ocaml-http/http_daemon.ml +++ b/helm/DEVEL/ocaml-http/http_daemon.ml @@ -21,6 +21,9 @@ open Printf;; +open Http_common;; +open Http_types;; +open Http_constants;; open Http_parser;; let debug = true @@ -33,18 +36,18 @@ let debug_print str = let default_addr = "0.0.0.0" let default_port = 80 let default_timeout = 300 -let default_fork = true +let default_mode = `Fork (** send raw data on outchan, flushing it afterwards *) let send_raw ~data outchan = output_string outchan data; flush outchan -let send_CRLF = send_raw ~data:Http_common.crlf +let send_CRLF = send_raw ~data:crlf - (** TODO perform some sanity test on header and value *) let send_header ~header ~value = - send_raw ~data:(header ^ ": " ^ value ^ Http_common.crlf) + Http_parser.heal_header (header, value); + send_raw ~data:(header ^ ": " ^ value ^ crlf) let send_headers ~headers outchan = List.iter (fun (header, value) -> send_header ~header ~value outchan) headers @@ -55,7 +58,7 @@ let get_code_argument func_name = fun ~code ~status -> (match code, status with | Some c, None -> c - | None, Some s -> Http_common.code_of_status s + | None, Some s -> code_of_status s | Some _, Some _ -> failwith (func_name ^ " you must give 'code' or 'status', not both") | None, None -> @@ -66,47 +69,59 @@ let send_status_line' ~version ~code = let status_line = String.concat " " - [ Http_common.string_of_version version; + [ string_of_version version; string_of_int code; - Http_common.reason_phrase_of_code code ] + Http_misc.reason_phrase_of_code code ] in - send_raw ~data:(status_line ^ Http_common.crlf) + send_raw ~data:(status_line ^ crlf) -let send_status_line - ?(version = Http_common.http_version) ?code ?status outchan - = +let send_status_line ?(version = http_version) ?code ?status outchan = send_status_line' ~version ~code:(get_code_argument "Daemon.send_status_line" ~code ~status) outchan (* FIXME duplication of code between this and response#addBasicHeaders *) -let send_basic_headers - ?(version = Http_common.http_version) ?code ?status outchan - = +let send_basic_headers ?(version = http_version) ?code ?status outchan = send_status_line' ~version ~code:(get_code_argument "Daemon.send_basic_headers" ~code ~status) outchan; send_headers - ~headers:["Date", Http_misc.date_822 (); "Server", Http_common.server_string] + ~headers:["Date", Http_misc.date_822 (); "Server", server_string] outchan - (** internal: send a fooish body explaining in HTML form the 'reason phrase' - of an HTTP response; body, if given, will be appended to the body *) -let send_foo_body ~code ~body = - let reason_phrase = Http_common.reason_phrase_of_code code in - let body = - sprintf + (** internal: given a status code and an additional body return a string + representing an HTML document that explains the meaning of given status code. + Additional data can be added to the body via 'body' argument *) +let foo_body code body = + let reason_phrase = Http_misc.reason_phrase_of_code code in + sprintf " %d %s

%d - %s

%s " - code reason_phrase code reason_phrase - (match body with None -> "" | Some text -> "\n" ^ text) + code reason_phrase code reason_phrase body + + (** internal: send a fooish body explaining in HTML form the 'reason phrase' + of an HTTP response; body, if given, will be appended to the body *) +let send_foo_body code body = send_raw ~data:(foo_body code body) + + (* TODO add the computation of Content-Length header *) +let respond + ?(body = "") ?(headers = []) + ?(version = http_version) ?(code = 200) ?status outchan + = + let code = + match status with + | None -> code + | Some s -> code_of_status s in - send_raw ~data:body + send_basic_headers ~version ~code outchan; + send_headers ~headers outchan; + send_CRLF outchan; + send_raw ~data:body outchan (** internal: low level for respond_redirect, respond_error, ... This function send a status line corresponding to a given code, some basic @@ -114,12 +129,23 @@ let send_foo_body ~code ~body = reason phrase; if body is given it will be included in the body of the HTML page *) let send_empty_response - f_name ?(is_valid_status = fun _ -> true) ?(headers = []) ~body () = - fun ?(version = Http_common.http_version) ?code ?status outchan -> - let code = get_code_argument f_name ~code ~status in + func_name ?(is_valid_status = fun _ -> true) ?(headers = []) ~body () = + fun ?(version = http_version) ?code ?status outchan -> + let code = get_code_argument func_name ~code ~status in if not (is_valid_status code) then - failwith (sprintf "'%d' isn't a valid status code for %s" code f_name) + failwith + (sprintf "'%d' isn't a valid status code for %s" code func_name) else begin (* status code suitable for answering *) + let headers = + [ + "Connection", "close"; + "Content-Type", "text/html; charset=iso-8859-1" + ] @ headers + in + let body = (foo_body code body) ^ body in + respond ~version ~code ~headers ~body outchan +(* + (* OLD VERSION, now use 'respond' function *) send_basic_headers ~version ~code outchan; send_header ~header:"Connection" ~value:"close" outchan; send_header @@ -129,43 +155,40 @@ let send_empty_response send_headers ~headers outchan; send_CRLF outchan; send_foo_body ~code ~body outchan +*) end - (* TODO sanity tests on location *) let respond_redirect - ~location ?body - ?(version = Http_common.http_version) ?(code = 301) ?status outchan = - let code = - match status with - | None -> code - | Some (s: Http_types.redirection_status) -> Http_common.code_of_status s - in - send_empty_response - "Daemon.respond_redirect" ~is_valid_status:Http_common.is_redirection - ~headers:["Location", location] ~body () - ~version ~code outchan + ~location ?(body = "") ?(version = http_version) ?(code = 301) ?status outchan + = + let code = + match status with + | None -> code + | Some (s: Http_types.redirection_status) -> code_of_status s + in + send_empty_response + "Daemon.respond_redirect" ~is_valid_status:is_redirection + ~headers:["Location", location] ~body () + ~version ~code outchan let respond_error - ?body - ?(version = Http_common.http_version) ?(code = 400) ?status outchan = + ?(body = "") ?(version = http_version) ?(code = 400) ?status outchan = let code = match status with | None -> code - | Some s -> Http_common.code_of_status s + | Some s -> code_of_status s in send_empty_response - "Daemon.respond_error" ~is_valid_status:Http_common.is_error ~body () + "Daemon.respond_error" ~is_valid_status:is_error ~body () ~version ~code outchan -let respond_not_found ~url ?(version = Http_common.http_version) outchan = +let respond_not_found ~url ?(version = http_version) outchan = send_empty_response - "Daemon.respond_not_found" ~body:None () - ~version ~code:404 outchan + "Daemon.respond_not_found" ~body:"" () ~version ~code:404 outchan -let respond_forbidden ~url ?(version = Http_common.http_version) outchan = +let respond_forbidden ~url ?(version = http_version) outchan = send_empty_response - "Daemon.respond_permission_denied" ~body:None () - ~version ~code:403 outchan + "Daemon.respond_permission_denied" ~body:"" () ~version ~code:403 outchan let send_file ?name ?file outchan = let buflen = 1024 in @@ -212,7 +235,7 @@ let send_dir_listing ~dir ~name ~path outchan = fprintf outchan "\n"; flush outchan -let respond_file ~fname ?(version = Http_common.http_version) outchan = +let respond_file ~fname ?(version = http_version) outchan = (** ASSUMPTION: 'fname' doesn't begin with a "/"; it's relative to the current document root (usually the daemon's cwd) *) let droot = Sys.getcwd () in (* document root *) @@ -251,12 +274,15 @@ let respond_with (res: Http_types.response) outchan = res#serialize outchan; flush outchan + (* TODO support also chroot to 'root', not only chdir *) (* curried request *) let start ?(addr = default_addr) ?(port = default_port) - ?(timeout = Some default_timeout) ?(fork = default_fork) - callback + ?(timeout = Some default_timeout) ?(mode = default_mode) ?root callback = + (match root with (* chdir to document root *) + | Some dir -> Sys.chdir dir + | None -> ()); let sockaddr = Unix.ADDR_INET (Unix.inet_addr_of_string addr, port) in let daemon_callback inchan outchan = try @@ -287,29 +313,31 @@ let start outchan | Malformed_query query -> respond_error - ~code:400 ~body:("Malformed query string '" ^ query ^ "'") outchan - | Malformed_query_binding (binding, query) -> + ~code:400 ~body:(sprintf "Malformed query string '%s'" query) outchan + | Malformed_query_part (binding, query) -> respond_error ~code:400 ~body:( - sprintf "Malformed query element '%s' in query '%s'" binding query) + sprintf "Malformed query part '%s' in query '%s'" binding query) outchan in - match fork with - | true -> Tcp_server.ocaml_builtin ~sockaddr ~timeout daemon_callback - | false -> Tcp_server.simple ~sockaddr ~timeout daemon_callback + match mode with + | `Single -> Http_tcp_server.simple ~sockaddr ~timeout daemon_callback + | `Fork -> Http_tcp_server.ocaml_builtin ~sockaddr ~timeout daemon_callback + | `Thread -> Http_tcp_server.thread ~sockaddr ~timeout daemon_callback (* OO request *) let start' ?(addr = default_addr) ?(port = default_port) - ?(timeout = Some default_timeout) ?(fork = default_fork) - (callback: (Http_types.request -> out_channel -> unit)) + ?(timeout = Some default_timeout) ?(mode = default_mode) ?root callback = let wrapper path params outchan = let req = new Http_request.request ~path ~params in callback req outchan in - start ~addr ~port ~timeout ~fork wrapper + match root with + | None -> start ~addr ~port ~timeout ~mode wrapper + | Some root -> start ~addr ~port ~timeout ~mode ~root wrapper module Trivial = struct