package paf
Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file alpn.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 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
type 'c capability = Rd : [ `read ] capability | Wr : [ `write ] capability type body = | Body_HTTP_1_1 : 'c capability * 'c Httpaf.Body.t -> body | Body_HTTP_2_0 : 'c capability * 'c h2_body -> body and 'c h2_body = | Wr : H2.Body.Writer.t -> [ `write ] h2_body | Rd : H2.Body.Reader.t -> [ `read ] h2_body type response = | Response_HTTP_1_1 of Httpaf.Response.t | Response_HTTP_2_0 of H2.Response.t type request = | Request_HTTP_1_1 of Httpaf.Request.t | Request_HTTP_2_0 of H2.Request.t type reqd = Reqd_HTTP_1_1 of Httpaf.Reqd.t | Reqd_HTTP_2_0 of H2.Reqd.t type headers = | Headers_HTTP_1_1 of Httpaf.Headers.t | Headers_HTTP_2_0 of H2.Headers.t let response_handler_v1_1 capability edn f resp body = f edn (Response_HTTP_1_1 resp) (Body_HTTP_1_1 (capability, body)) let response_handler_v2_0 capability edn f resp body = f edn (Response_HTTP_2_0 resp) (Body_HTTP_2_0 (capability, Rd body)) let request_handler_v1 edn f reqd = f edn (Reqd_HTTP_1_1 reqd) let request_handler_v2 edn f reqd = f edn (Reqd_HTTP_2_0 reqd) module Httpaf_Client_connection = struct include Httpaf.Client_connection let yield_reader _ = assert false let next_read_operation t = (next_read_operation t :> [ `Close | `Read | `Yield ]) end type ('flow, 'edn) info = { alpn : 'flow -> string option; peer : 'flow -> 'edn; injection : 'flow -> Mimic.flow; } type server_error = [ `Bad_gateway | `Bad_request | `Exn of exn | `Internal_server_error ] let error_handler_v1 edn f ?request error (response : Httpaf.Headers.t -> [ `write ] Httpaf.Body.t) = let request = Option.map (fun req -> Request_HTTP_1_1 req) request in let response = function | Headers_HTTP_1_1 headers -> Body_HTTP_1_1 (Wr, response headers) | _ -> assert false in f edn ?request (error :> server_error) response let error_handler_v2 edn f ?request error (response : H2.Headers.t -> H2.Body.Writer.t) = let request = Option.map (fun req -> Request_HTTP_2_0 req) request in let response = function | Headers_HTTP_2_0 headers -> Body_HTTP_2_0 (Wr, Wr (response headers)) | _ -> assert false in f edn ?request (error :> server_error) response let service info ~error_handler ~request_handler connect accept close = let connection flow = match info.alpn flow with | Some "http/1.0" | Some "http/1.1" | None -> let edn = info.peer flow in let flow = info.injection flow in let error_handler = error_handler_v1 edn error_handler in let request_handler = request_handler_v1 edn request_handler in let conn = Httpaf.Server_connection.create ~error_handler request_handler in Lwt.return_ok (flow, Paf.Runtime ((module Httpaf.Server_connection), conn)) | Some "h2" -> let edn = info.peer flow in let flow = info.injection flow in let error_handler = error_handler_v2 edn error_handler in let request_handler = request_handler_v2 edn request_handler in let conn = H2.Server_connection.create ~error_handler request_handler in Lwt.return_ok (flow, Paf.Runtime ((module H2.Server_connection), conn)) | Some protocol -> Lwt.return_error (`Msg (Fmt.str "Invalid protocol %S." protocol)) in Paf.service connection connect accept close type client_error = [ `Exn of exn | `Malformed_response of string | `Invalid_response_body_length_v1 of Httpaf.Response.t | `Invalid_response_body_length_v2 of H2.Response.t | `Protocol_error of H2.Error_code.t * string ] type common_error = [ `Exn of exn | `Malformed_response of string ] let error_handler_v1 edn f = function | #common_error as err -> f edn err | `Invalid_response_body_length resp -> f edn (`Invalid_response_body_length_v1 resp) let error_handler_v2 edn f = function | #common_error as err -> f edn err | `Protocol_error _ as err -> f edn err | `Invalid_response_body_length resp -> f edn (`Invalid_response_body_length_v2 resp) let run ~sleep ?alpn ~error_handler ~response_handler edn request flow = match (alpn, request) with | (Some "h2" | None), `V2 request -> let error_handler = error_handler_v2 edn error_handler in let response_handler = response_handler_v2_0 Rd edn response_handler in let conn = H2.Client_connection.create ?config:None ?push_handler:None ~error_handler in let body = H2.Client_connection.request conn request ~error_handler ~response_handler in Lwt.async (fun () -> Paf.run (module H2.Client_connection) ~sleep conn flow) ; Lwt.return_ok (Body_HTTP_2_0 (Wr, Wr body)) | (Some "http/1.1" | None), `V1 request -> let error_handler = error_handler_v1 edn error_handler in let response_handler = response_handler_v1_1 Rd edn response_handler in let body, conn = Httpaf.Client_connection.request request ~error_handler ~response_handler in Lwt.async (fun () -> Paf.run (module Httpaf_Client_connection) ~sleep conn flow) ; Lwt.return_ok (Body_HTTP_1_1 (Wr, body)) | Some protocol, _ -> Lwt.return_error (`Msg (Fmt.str "Invalid Application layer protocol: %S" protocol))