diff options
Diffstat (limited to 'bs5/server/DreamRSC.ml')
-rw-r--r-- | bs5/server/DreamRSC.ml | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/bs5/server/DreamRSC.ml b/bs5/server/DreamRSC.ml index 0b35071..40fa9a8 100644 --- a/bs5/server/DreamRSC.ml +++ b/bs5/server/DreamRSC.ml @@ -1 +1,134 @@ +open Function_references + let debug = Sys.getenv_opt "DEMO_ENV" == Some "development" + +let handle_form_request action_id form_data = + let form_data = + let form_data_js = Js.FormData.make () in + form_data + |> List.iter (fun (name, value) -> + (* For now we're only supporting strings. *) + let _filename, value = value |> List.hd in + Js.FormData.append form_data_js name (`String value)); + form_data_js + in + + let args, form_data = ReactServerDOM.decodeFormDataReply form_data in + + let action_id = + match action_id with + | Some action_id -> action_id + | None -> failwith "We don't support progressive enhancement yet." + in + + let handler = + match FunctionReferences.get action_id with + | Some (FormData handler) -> handler + | _ -> assert false + in + handler args form_data + +let handle_request_body request action_id = + let%lwt body = Dream.body request in + let action_id = + match action_id with + | Some action_id -> action_id + | None -> + failwith + "Missing action ID, this request was not created by \ + server-reason-react" + in + let handler = + match FunctionReferences.get action_id with + | Some (Body handler) -> handler + | _ -> assert false + in + + handler (ReactServerDOM.decodeReply body) + +let handle_request request = + let action_id = Dream.header request "ACTION_ID" in + let content_type = Dream.header request "Content-Type" in + + match content_type with + | Some content_type + when String.starts_with content_type ~prefix:"multipart/form-data" -> ( + let%lwt result = Dream.multipart request ~csrf:false in + match result with + | `Ok form_data -> handle_form_request action_id form_data + | _ -> + failwith + "Missing form data, this request was not created by \ + server-reason-react") + | _ -> handle_request_body request action_id + +let stream_function_response request = + Dream.stream + ~headers:[ ("Content-Type", "application/react.action") ] + (fun stream -> + let%lwt () = + ReactServerDOM.create_action_response + ~subscribe:(fun chunk -> + Dream.log "Action response"; + Dream.log "%s" chunk; + let%lwt () = Dream.write stream chunk in + Dream.flush stream) + (handle_request request) + in + + Dream.flush stream) + +let is_react_component_header str = + String.equal str "application/react.component" + +let stream_model ~location app = + Dream.stream + ~headers: + [ + ("Content-Type", "application/react.component"); + ("X-Content-Type-Options", "nosniff"); + ("X-Location", location); + ] + (fun stream -> + let%lwt () = + ReactServerDOM.render_model ~debug + ~subscribe:(fun chunk -> + Dream.log "Chunk"; + Dream.log "%s" chunk; + let%lwt () = Dream.write stream chunk in + Dream.flush stream) + app + in + + Dream.flush stream) + +let stream_html ~bootstrap_script_content ~bootstrap_scripts ~bootstrap_modules + app = + Dream.stream + ~headers:[ ("Content-Type", "text/html") ] + (fun stream -> + let%lwt html, subscribe = + ReactServerDOM.render_html + ~bootstrapScriptContent:bootstrap_script_content + ~bootstrapScripts:bootstrap_scripts + ~bootstrapModules:bootstrap_modules ~debug app + in + let%lwt () = Dream.write stream html in + let%lwt () = Dream.flush stream in + let%lwt () = + subscribe (fun chunk -> + Dream.log "Chunk"; + Dream.log "%s" chunk; + let%lwt () = Dream.write stream chunk in + Dream.flush stream) + in + Dream.flush stream) + +let create_from_request ?(bootstrap_modules = []) ?(bootstrap_scripts = []) + ?(bootstrap_script_content = "") app request = + match Dream.header request "Accept" with + | Some accept when is_react_component_header accept -> + stream_model ~location:(Dream.target request) app + | _ -> + stream_html ~bootstrap_script_content ~bootstrap_scripts + ~bootstrap_modules app |