Current section

Files

Jump to
wisp_inertia src internal ssr.gleam
Raw

src/internal/ssr.gleam

import gleam/dynamic/decode
import gleam/http.{Post}
import gleam/http/request
import gleam/http/response
import gleam/httpc
import gleam/int
import gleam/json
import gleam/result
pub const ssr_flag = "ssr_enabled"
pub type ClientError {
HttpError(Int)
JsonParseError
NetworkError
}
pub fn client_error_to_string(err: ClientError) -> String {
case err {
JsonParseError -> "JSON parse error"
NetworkError -> "Network error"
HttpError(code) -> "HTTP error code " <> int.to_string(code)
}
}
pub type SSRRenderResponse {
SSRRenderResponse(head: List(String), body: String)
}
// SSR render decoder
fn reponse_decoder() -> decode.Decoder(SSRRenderResponse) {
use head <- decode.field("head", decode.list(of: decode.string))
use body <- decode.field("body", decode.string)
decode.success(SSRRenderResponse(head, body))
}
/// Sends a POST request to the Node process to get the SSR content
///
pub fn server_render(
url: String,
body: String,
) -> Result(SSRRenderResponse, ClientError) {
post_request(url, body)
}
fn post_request(
url: String,
body: String,
) -> Result(SSRRenderResponse, ClientError) {
let assert Ok(base_req) = request.to(url)
let req =
base_req
|> request.set_method(Post)
|> request.set_header("Content-Type", "application/json")
|> request.set_header("Accept", "application/json")
|> request.set_body(body)
case httpc.send(req) {
Ok(resp) -> parse_response(resp)
Error(_) -> Error(NetworkError)
}
}
fn parse_response(
res: response.Response(String),
) -> Result(SSRRenderResponse, ClientError) {
case res.status {
200 -> {
json.parse(res.body, reponse_decoder())
|> result.map_error(fn(_) { JsonParseError })
}
status -> Error(HttpError(status))
}
}