cgi.ml 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. (*
  2. * cgi.ml
  3. *
  4. * Created by Marcus Rohrmoser on 16.05.20.
  5. * Copyright © 2020-2021 Marcus Rohrmoser mobile Software http://mro.name/~me. All rights reserved.
  6. *
  7. * This program is free software: you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation, either version 3 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. *)
  20. let camel = "🐫"
  21. module Os = struct
  22. let getenv = Sys.getenv
  23. (* https://github.com/rixed/ocaml-cgi/blob/master/cgi.ml#L169 *)
  24. let getenv_safe ?default s =
  25. try getenv s
  26. with Not_found -> (
  27. match default with
  28. | Some d -> d
  29. | None -> failwith ("Cgi: the environment variable " ^ s ^ " is not set"))
  30. end
  31. let redirect oc url =
  32. let status = 302
  33. and reason = "Found"
  34. and mime = "text/plain; charset=utf-8" in
  35. Printf.fprintf oc "%s: %d %s\n" "Status" status reason;
  36. Printf.fprintf oc "%s: %s\n" "Content-Type" mime;
  37. Printf.fprintf oc "%s: %s\n" "Location" url;
  38. Printf.fprintf oc "\n";
  39. Printf.fprintf oc "%s %s.\n" camel reason;
  40. 0
  41. let error oc status reason =
  42. let mime = "text/plain; charset=utf-8" in
  43. Printf.fprintf oc "%s: %d %s\n" "Status" status reason;
  44. Printf.fprintf oc "%s: %s\n" "Content-Type" mime;
  45. Printf.fprintf oc "\n";
  46. Printf.fprintf oc "%s %s.\n" camel reason;
  47. 0
  48. let dump_clob oc mime clob =
  49. Printf.fprintf oc "%s: %s\n" "Content-Type" mime;
  50. Printf.fprintf oc "\n";
  51. Printf.fprintf oc "%s" clob;
  52. 0
  53. type req_raw = {
  54. host : string;
  55. http_cookie : string;
  56. path_info : string;
  57. query_string : string;
  58. request_method : string;
  59. scheme : string;
  60. script_name : string;
  61. server_port : string;
  62. }
  63. let consolidate req' =
  64. Result.bind req' (fun req ->
  65. (* despite https://tools.ietf.org/html/rfc3875#section-4.1.13 1und1.de
  66. * webhosting returns the script_name instead an empty or nonex path_info in
  67. * case *)
  68. match req.path_info = req.script_name with
  69. | true -> Ok { req with path_info = "" }
  70. | false -> req')
  71. let request_uri req =
  72. req.script_name ^ req.path_info
  73. ^ match req.query_string with "" -> "" | qs -> "?" ^ qs
  74. (* Almost trivial. https://tools.ietf.org/html/rfc3875 *)
  75. let request_from_env () =
  76. try
  77. Ok
  78. {
  79. host = Os.getenv_safe ~default:(Os.getenv "SERVER_NAME") "HTTP_HOST";
  80. http_cookie = Os.getenv_safe ~default:"" "HTTP_COOKIE";
  81. path_info = Os.getenv_safe ~default:"" "PATH_INFO";
  82. query_string = Os.getenv_safe ~default:"" "QUERY_STRING";
  83. request_method = Os.getenv "REQUEST_METHOD";
  84. (* request_uri = Os.getenv "REQUEST_URI"; *)
  85. scheme =
  86. (match Os.getenv_safe ~default:"" "HTTPS" with
  87. | "on" -> "https"
  88. | _ -> "http");
  89. script_name = Os.getenv "SCRIPT_NAME";
  90. server_port = Os.getenv "SERVER_PORT";
  91. }
  92. with Not_found -> Error "Not Found."