Packages
mist
0.7.1
6.0.3
6.0.2
6.0.1
6.0.0
5.0.4
5.0.3
5.0.2
5.0.1
5.0.0
5.0.0-rc1
4.0.7
4.0.6
4.0.5
4.0.4
4.0.3
4.0.2
4.0.1
4.0.0
3.0.0
2.0.0
1.2.0
1.1.0
1.0.0
1.0.0-rc3
1.0.0-rc2
1.0.0-rc1
0.17.0
0.15.0
0.14.3
0.14.2
0.14.1
0.14.0
0.13.2
0.13.1
0.13.0
0.12.0
0.11.0
0.10.0
0.9.4
0.9.3
0.9.2
0.9.1
0.9.0
0.8.3
0.8.2
0.8.1
0.8.0
0.7.1
0.7.0
0.6.1
0.6.0
0.5.2
0.5.1
0.5.0
0.4.5
0.4.4
0.4.3
0.4.2
0.4.1
0.4.0
0.3.3
0.3.2
0.3.1
0.3.0
0.2.1
0.2.0
0.1.3
a misty Gleam web server
Current section
Files
Jump to
Current section
Files
src/mist@http.erl
-module(mist@http).
-compile(no_auto_import).
-export([from_header/1, parse_headers/3, read_data/3, parse_request/2, read_body/1, new_state/0, handler/2, handler_func/1, upgrade_socket/1, upgrade/2]).
-export_type([packet_type/0, http_uri/0, http_packet/0, decoded_packet/0, decode_error/0, buffer/0, body/0, handler_error/0, state/0, http_response_body/0, handler_response/0]).
-type packet_type() :: http | httph_bin | http_bin.
-type http_uri() :: {abs_path, bitstring()}.
-type http_packet() :: {http_request,
gleam@dynamic:dynamic(),
http_uri(),
{integer(), integer()}} |
{http_header,
integer(),
gleam@erlang@atom:atom_(),
bitstring(),
bitstring()}.
-type decoded_packet() :: {binary_data, http_packet(), bitstring()} |
{end_of_headers, bitstring()} |
{more_data, gleam@option:option(integer())}.
-type decode_error() :: malformed_request |
invalid_method |
invalid_path |
unknown_header |
unknown_method |
invalid_body |
discard_packet.
-type buffer() :: {buffer, integer(), bitstring()}.
-opaque body() :: {unread, bitstring(), glisten@tcp:socket()} |
{read, bitstring()}.
-type handler_error() :: {invalid_request, decode_error()} | not_found.
-type state() :: {state,
gleam@option:option(gleam@otp@process:timer()),
gleam@option:option(mist@websocket:websocket_handler())}.
-type http_response_body() :: {bit_builder_body,
gleam@bit_builder:bit_builder()} |
{file_body, mist@file:file_descriptor(), binary(), integer(), integer()}.
-type handler_response() :: {response,
gleam@http@response:response(http_response_body())} |
{upgrade, mist@websocket:websocket_handler()}.
-spec from_header(bitstring()) -> binary().
from_header(Value) ->
{ok, Value@2} = case gleam@bit_string:to_string(Value) of
{ok, Value@1} -> {ok, Value@1};
_try ->
erlang:error(#{gleam_error => assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _try,
module => <<"mist/http"/utf8>>,
function => <<"from_header"/utf8>>,
line => 66})
end,
gleam@string:lowercase(Value@2).
-spec parse_headers(
bitstring(),
glisten@tcp:socket(),
gleam@map:map_(binary(), binary())
) -> {ok, {gleam@map:map_(binary(), binary()), bitstring()}} |
{error, decode_error()}.
parse_headers(Bs, Socket, Headers) ->
case http_ffi:decode_packet(httph_bin, Bs, []) of
{ok, {binary_data, {http_header, _@1, _@2, Field, Value}, Rest}} ->
Field@1 = from_header(Field),
{ok, Value@2} = case gleam@bit_string:to_string(Value) of
{ok, Value@1} -> {ok, Value@1};
_try ->
erlang:error(#{gleam_error => assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _try,
module => <<"mist/http"/utf8>>,
function => <<"parse_headers"/utf8>>,
line => 83})
end,
_pipe = Headers,
_pipe@1 = gleam@map:insert(_pipe, Field@1, Value@2),
parse_headers(Rest, Socket, _pipe@1);
{ok, {end_of_headers, Rest@1}} ->
{ok, {Headers, Rest@1}};
{ok, {more_data, Size}} ->
Amount_to_read = gleam@option:unwrap(Size, 0),
case read_data(Socket, {buffer, Amount_to_read, Bs}, unknown_header) of
{error, _try@1} -> {error, _try@1};
{ok, Next} ->
parse_headers(Next, Socket, Headers)
end;
_@3 ->
{error, unknown_header}
end.
-spec read_data(glisten@tcp:socket(), buffer(), decode_error()) -> {ok,
bitstring()} |
{error, decode_error()}.
read_data(Socket, Buffer, Error) ->
To_read = gleam@int:min(erlang:element(2, Buffer), 1000000),
Timeout = 15000,
case begin
_pipe = Socket,
_pipe@1 = glisten@tcp:receive_timeout(_pipe, To_read, Timeout),
gleam@result:replace_error(_pipe@1, Error)
end of
{error, _try} -> {error, _try};
{ok, Data} ->
Next_buffer = {buffer,
erlang:element(2, Buffer)
- To_read,
<<(erlang:element(3, Buffer))/bitstring,
Data/bitstring>>},
case erlang:element(2, Next_buffer) > 0 of
true ->
read_data(Socket, Next_buffer, Error);
false ->
{ok, erlang:element(3, Next_buffer)}
end
end.
-spec read_chunk(
glisten@tcp:socket(),
buffer(),
gleam@bit_builder:bit_builder()
) -> {ok, gleam@bit_builder:bit_builder()} | {error, decode_error()}.
read_chunk(Socket, Buffer, Body) ->
case {erlang:element(3, Buffer),
http_ffi:binary_match(
erlang:element(3, Buffer),
<<13/integer, 10/integer>>
)} of
{_@1, {ok, {Offset, _@2}}} ->
<<Chunk@1:Offset/binary, _@5/integer, _@6/integer, Rest@1/binary>> = case erlang:element(
3,
Buffer
) of
<<Chunk:Offset/binary, _@3/integer, _@4/integer, Rest/binary>> -> <<Chunk:Offset/binary,
_@3/integer,
_@4/integer,
Rest/binary>>;
_try ->
erlang:error(#{gleam_error => assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _try,
module => <<"mist/http"/utf8>>,
function => <<"read_chunk"/utf8>>,
line => 140})
end,
case begin
_pipe = Chunk@1,
_pipe@1 = gleam@bit_string:to_string(_pipe),
_pipe@2 = gleam@result:map(
_pipe@1,
fun gleam@erlang@charlist:from_string/1
),
gleam@result:replace_error(_pipe@2, invalid_body)
end of
{error, _try@1} -> {error, _try@1};
{ok, Chunk_size} ->
case begin
_pipe@3 = http_ffi:string_to_int(Chunk_size, 16),
gleam@result:replace_error(_pipe@3, invalid_body)
end of
{error, _try@2} -> {error, _try@2};
{ok, Size} ->
case Size of
0 ->
{ok, Body};
Size@1 ->
case Rest@1 of
<<Next_chunk:Size@1/binary,
13/integer,
10/integer,
Rest@2/binary>> ->
read_chunk(
Socket,
{buffer, 0, Rest@2},
gleam@bit_builder:append(
Body,
Next_chunk
)
);
_@7 ->
case read_data(
Socket,
{buffer,
0,
erlang:element(3, Buffer)},
invalid_body
) of
{error, _try@3} -> {error, _try@3};
{ok, Next} ->
read_chunk(
Socket,
{buffer, 0, Next},
Body
)
end
end
end
end
end;
{<<>>, _@8} ->
case read_data(
Socket,
{buffer, 0, erlang:element(3, Buffer)},
invalid_body
) of
{error, _try@4} -> {error, _try@4};
{ok, Next@1} ->
read_chunk(Socket, {buffer, 0, Next@1}, Body)
end;
{_@9, {error, nil}} ->
{error, invalid_body}
end.
-spec decode_atom(gleam@dynamic:dynamic()) -> {ok, gleam@erlang@atom:atom_()} |
{error, list(gleam@dynamic:decode_error())}.
decode_atom(Value) ->
case erlang:is_atom(Value) of
true ->
{ok, gleam@dynamic:unsafe_coerce(Value)};
false ->
{error,
[{decode_error, <<"Atom"/utf8>>, gleam@dynamic:classify(Value), []}]}
end.
-spec parse_request(bitstring(), glisten@tcp:socket()) -> {ok,
gleam@http@request:request(body())} |
{error, decode_error()}.
parse_request(Bs, Socket) ->
case http_ffi:decode_packet(http_bin, Bs, []) of
{ok,
{binary_data, {http_request, Http_method, {abs_path, Path}, _@1}, Rest}} ->
case begin
_pipe = Http_method,
_pipe@1 = decode_atom(_pipe),
_pipe@2 = gleam@result:map(
_pipe@1,
fun gleam@erlang@atom:to_string/1
),
_pipe@3 = gleam@result:'or'(
_pipe@2,
gleam@dynamic:string(Http_method)
),
_pipe@4 = gleam@result:replace_error(_pipe@3, nil),
_pipe@5 = gleam@result:then(
_pipe@4,
fun gleam@http:parse_method/1
),
gleam@result:replace_error(_pipe@5, unknown_method)
end of
{error, _try} -> {error, _try};
{ok, Method} ->
case parse_headers(Rest, Socket, gleam@map:new()) of
{error, _try@1} -> {error, _try@1};
{ok, {Headers, Rest@1}} ->
case begin
_pipe@6 = Path,
_pipe@7 = gleam@bit_string:to_string(_pipe@6),
gleam@result:replace_error(
_pipe@7,
invalid_path
)
end of
{error, _try@2} -> {error, _try@2};
{ok, Path@1} ->
{Path@4, Query@1} = case gleam@string:split(
Path@1,
<<"?"/utf8>>
) of
[Path@2] ->
{Path@2, []};
[Path@3, Query_string] ->
Query = begin
_pipe@8 = Query_string,
_pipe@9 = gleam@uri:parse_query(
_pipe@8
),
gleam@result:unwrap(_pipe@9, [])
end,
{Path@3, Query}
end,
Req = begin
_pipe@10 = gleam@http@request:new(),
_pipe@11 = gleam@http@request:set_body(
_pipe@10,
{unread, Rest@1, Socket}
),
_pipe@12 = gleam@http@request:set_method(
_pipe@11,
Method
),
_pipe@13 = gleam@http@request:set_path(
_pipe@12,
Path@4
),
gleam@http@request:set_query(
_pipe@13,
Query@1
)
end,
{ok,
erlang:setelement(
3,
Req,
gleam@map:to_list(Headers)
)}
end
end
end;
_@2 ->
{error, discard_packet}
end.
-spec read_body(gleam@http@request:request(body())) -> {ok,
gleam@http@request:request(bitstring())} |
{error, decode_error()}.
read_body(Req) ->
case {gleam@http@request:get_header(Req, <<"transfer-encoding"/utf8>>),
erlang:element(4, Req)} of
{{ok, <<"chunked"/utf8>>}, {unread, Rest, Socket}} ->
case read_chunk(Socket, {buffer, 0, Rest}, gleam@bit_builder:new()) of
{error, _try} -> {error, _try};
{ok, Chunk} ->
{ok,
gleam@http@request:set_body(
Req,
gleam@bit_builder:to_bit_string(Chunk)
)}
end;
{_@1, {unread, Rest@1, Socket@1}} ->
Body_size = begin
_pipe = erlang:element(3, Req),
_pipe@1 = gleam@list:find(
_pipe,
fun(Tup) ->
gleam@pair:first(Tup)
=:= <<"content-length"/utf8>>
end
),
_pipe@2 = gleam@result:map(_pipe@1, fun gleam@pair:second/1),
_pipe@3 = gleam@result:then(_pipe@2, fun gleam@int:parse/1),
gleam@result:unwrap(_pipe@3, 0)
end,
Remaining = Body_size - gleam@bit_string:byte_size(Rest@1),
_pipe@4 = case {Body_size, Remaining} of
{0, 0} ->
{ok, <<>>};
{0, _@2} ->
{ok, Rest@1};
{_@3, 0} ->
{ok, Rest@1};
{_@4, _@5} ->
read_data(
Socket@1,
{buffer, Remaining, Rest@1},
invalid_body
)
end,
_pipe@5 = gleam@result:map(
_pipe@4,
fun(_capture) -> gleam@http@request:set_body(Req, _capture) end
),
gleam@result:replace_error(_pipe@5, invalid_body);
{_@6, {read, _@7}} ->
{error, invalid_body}
end.
-spec new_state() -> state().
new_state() ->
{state, none, none}.
-spec handler(
fun((gleam@http@request:request(bitstring())) -> gleam@http@response:response(gleam@bit_builder:bit_builder())),
integer()
) -> fun((glisten@tcp:handler_message(), glisten@tcp:loop_state(state())) -> gleam@otp@actor:next(glisten@tcp:loop_state(state()))).
handler(Handler, Max_body_limit) ->
Bad_request = begin
_pipe = gleam@http@response:new(400),
gleam@http@response:set_body(_pipe, gleam@bit_builder:new())
end,
handler_func(
fun(Req) ->
_pipe@14 = case {gleam@http@request:get_header(
Req,
<<"content-length"/utf8>>
),
gleam@http@request:get_header(
Req,
<<"transfer-encoding"/utf8>>
)} of
{{ok, <<"0"/utf8>>}, _@1} ->
_pipe@1 = Req,
_pipe@2 = gleam@http@request:set_body(_pipe@1, <<>>),
Handler(_pipe@2);
{{error, nil}, {error, nil}} ->
_pipe@1 = Req,
_pipe@2 = gleam@http@request:set_body(_pipe@1, <<>>),
Handler(_pipe@2);
{_@2, {ok, <<"chunked"/utf8>>}} ->
_pipe@3 = Req,
_pipe@4 = read_body(_pipe@3),
_pipe@5 = gleam@result:map(_pipe@4, Handler),
gleam@result:unwrap(_pipe@5, Bad_request);
{{ok, Size}, _@3} ->
_pipe@6 = Size,
_pipe@7 = gleam@int:parse(_pipe@6),
_pipe@13 = gleam@result:map(
_pipe@7,
fun(Size@1) -> case Size@1 > Max_body_limit of
true ->
_pipe@8 = gleam@http@response:new(413),
_pipe@9 = gleam@http@response:set_body(
_pipe@8,
gleam@bit_builder:new()
),
gleam@http@response:prepend_header(
_pipe@9,
<<"connection"/utf8>>,
<<"close"/utf8>>
);
false ->
_pipe@10 = Req,
_pipe@11 = read_body(_pipe@10),
_pipe@12 = gleam@result:map(
_pipe@11,
Handler
),
gleam@result:unwrap(_pipe@12, Bad_request)
end end
),
gleam@result:unwrap(_pipe@13, Bad_request)
end,
_pipe@15 = gleam@http@response:map(
_pipe@14,
fun(A) -> {bit_builder_body, A} end
),
{response, _pipe@15}
end
).
-spec handler_func(
fun((gleam@http@request:request(body())) -> handler_response())
) -> fun((glisten@tcp:handler_message(), glisten@tcp:loop_state(state())) -> gleam@otp@actor:next(glisten@tcp:loop_state(state()))).
handler_func(Handler) ->
glisten@tcp:handler(
fun(Msg, Socket_state) ->
{loop_state, Socket, Sender, State} = Socket_state,
case erlang:element(3, State) of
{some, Ws_handler} ->
case mist@websocket:frame_from_message(Socket, Msg) of
{ok, {ping_frame, _@1, _@2}} ->
{ok, _@4} = case glisten@tcp:send(
Socket,
mist@websocket:frame_to_bit_builder(
{pong_frame, 0, <<>>}
)
) of
{ok, _@3} -> {ok, _@3};
_try ->
erlang:error(#{gleam_error => assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _try,
module => <<"mist/http"/utf8>>,
function => <<"handler_func"/utf8>>,
line => 355})
end,
{continue, Socket_state};
{ok, {close_frame, _@5, _@6} = Frame} ->
{ok, _@8} = case glisten@tcp:send(
Socket,
mist@websocket:frame_to_bit_builder(Frame)
) of
{ok, _@7} -> {ok, _@7};
_try@1 ->
erlang:error(#{gleam_error => assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _try@1,
module => <<"mist/http"/utf8>>,
function => <<"handler_func"/utf8>>,
line => 363})
end,
_@10 = case erlang:element(2, Ws_handler) of
{some, Func} ->
Func(Sender);
_@9 ->
nil
end,
{stop, normal};
{ok, {pong_frame, _@11, _@12}} ->
{stop, normal};
{ok, Frame@1} ->
_pipe = case Frame@1 of
{text_frame, _@13, Payload} ->
{ok, Msg@2} = case gleam@bit_string:to_string(
Payload
) of
{ok, Msg@1} -> {ok, Msg@1};
_try@2 ->
erlang:error(
#{gleam_error => assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _try@2,
module => <<"mist/http"/utf8>>,
function => <<"handler_func"/utf8>>,
line => 375}
)
end,
{text_message, Msg@2};
_@14 ->
{binary_message, erlang:element(3, Frame@1)}
end,
_pipe@1 = (fun(Ws_msg) ->
gleam_erlang_ffi:rescue(
fun() ->
(erlang:element(4, Ws_handler))(
Ws_msg,
Sender
)
end
)
end)(_pipe),
_pipe@2 = gleam@result:replace(
_pipe@1,
{continue, Socket_state}
),
_pipe@3 = gleam@result:map_error(
_pipe@2,
fun(Err) ->
mist@logger:error(Err),
_@16 = case erlang:element(2, Ws_handler) of
{some, Func@1} ->
Func@1(Sender);
_@15 ->
nil
end,
Err
end
),
_pipe@4 = gleam@result:replace_error(
_pipe@3,
{stop, normal}
),
gleam@result:unwrap_both(_pipe@4);
{error, _@17} ->
_@19 = case erlang:element(2, Ws_handler) of
{some, Func@2} ->
Func@2(Sender);
_@18 ->
nil
end,
{stop, normal}
end;
none ->
_@21 = case erlang:element(2, State) of
{some, T} ->
gleam@otp@process:cancel_timer(T);
_@20 ->
timer_not_found
end,
_pipe@5 = Msg,
_pipe@6 = parse_request(_pipe@5, Socket),
_pipe@7 = gleam@result:map_error(
_pipe@6,
fun(Err@1) -> case Err@1 of
discard_packet ->
nil;
_@22 ->
mist@logger:error(Err@1),
glisten@tcp:close(Socket),
nil
end end
),
_pipe@8 = gleam@result:replace_error(
_pipe@7,
{stop, normal}
),
_pipe@33 = gleam@result:map(
_pipe@8,
fun(Req) ->
case gleam_erlang_ffi:rescue(
fun() -> Handler(Req) end
) of
{ok,
{response,
{response,
_@23,
_@24,
{bit_builder_body, Body}} = Resp}} ->
_pipe@9 = Resp,
_pipe@10 = gleam@http@response:set_body(
_pipe@9,
Body
),
_pipe@11 = mist@encoder:to_bit_builder(
_pipe@10
),
_pipe@12 = glisten@tcp:send(
Socket,
_pipe@11
),
_pipe@13 = gleam@result:map(
_pipe@12,
fun(_) ->
case gleam@http@response:get_header(
Resp,
<<"connection"/utf8>>
) of
{ok, <<"close"/utf8>>} ->
glisten@tcp:close(Socket),
{stop, normal};
_@25 ->
Timer = gleam@otp@process:send_after(
Sender,
10000,
close
),
{continue,
erlang:setelement(
4,
Socket_state,
erlang:setelement(
2,
State,
{some, Timer}
)
)}
end
end
),
_pipe@14 = gleam@result:replace_error(
_pipe@13,
{stop, normal}
),
gleam@result:unwrap_both(_pipe@14);
{ok,
{response,
{response,
_@26,
_@27,
{file_body,
File_descriptor,
Content_type,
Offset,
Length}} = Resp@1}} ->
_pipe@15 = Resp@1,
_pipe@16 = gleam@http@response:prepend_header(
_pipe@15,
<<"content-length"/utf8>>,
gleam@int:to_string(Length - Offset)
),
_pipe@17 = gleam@http@response:prepend_header(
_pipe@16,
<<"content-type"/utf8>>,
Content_type
),
_pipe@18 = gleam@http@response:set_body(
_pipe@17,
gleam@bit_builder:new()
),
_pipe@19 = (fun(R) ->
mist@encoder:response_builder(
erlang:element(2, Resp@1),
erlang:element(3, R)
)
end)(_pipe@18),
_pipe@20 = glisten@tcp:send(
Socket,
_pipe@19
),
_pipe@21 = gleam@result:map(
_pipe@20,
fun(_) ->
mist@file:sendfile(
File_descriptor,
Socket,
Offset,
Length,
[]
)
end
),
_pipe@22 = gleam@result:replace(
_pipe@21,
{continue, Socket_state}
),
_pipe@23 = gleam@result:replace_error(
_pipe@22,
{stop, normal}
),
gleam@result:unwrap_both(_pipe@23);
{ok, {upgrade, With_handler}} ->
_pipe@24 = Req,
_pipe@25 = upgrade(Socket, _pipe@24),
_pipe@26 = gleam@result:map(
_pipe@25,
fun(_) ->
_@29 = case erlang:element(
3,
With_handler
) of
{some, Func@3} ->
Func@3(Sender);
_@28 ->
nil
end
end
),
_pipe@27 = gleam@result:replace(
_pipe@26,
{continue,
erlang:setelement(
4,
Socket_state,
erlang:setelement(
3,
State,
{some, With_handler}
)
)}
),
_pipe@28 = gleam@result:replace_error(
_pipe@27,
{stop, normal}
),
gleam@result:unwrap_both(_pipe@28);
{error, {exited, Msg@3} = Err@2} ->
mist@logger:error(Err@2),
_pipe@29 = gleam@http@response:new(500),
_pipe@30 = gleam@http@response:set_body(
_pipe@29,
gleam@bit_builder:from_bit_string(
<<"Internal Server Error"/utf8>>
)
),
_pipe@31 = gleam@http@response:prepend_header(
_pipe@30,
<<"content-length"/utf8>>,
<<"21"/utf8>>
),
_pipe@32 = mist@encoder:to_bit_builder(
_pipe@31
),
glisten@tcp:send(Socket, _pipe@32),
glisten@tcp:close(Socket),
{stop, {abnormal, Msg@3}};
{error, {thrown, Msg@3} = Err@2} ->
mist@logger:error(Err@2),
_pipe@29 = gleam@http@response:new(500),
_pipe@30 = gleam@http@response:set_body(
_pipe@29,
gleam@bit_builder:from_bit_string(
<<"Internal Server Error"/utf8>>
)
),
_pipe@31 = gleam@http@response:prepend_header(
_pipe@30,
<<"content-length"/utf8>>,
<<"21"/utf8>>
),
_pipe@32 = mist@encoder:to_bit_builder(
_pipe@31
),
glisten@tcp:send(Socket, _pipe@32),
glisten@tcp:close(Socket),
{stop, {abnormal, Msg@3}};
{error, {errored, Msg@3} = Err@2} ->
mist@logger:error(Err@2),
_pipe@29 = gleam@http@response:new(500),
_pipe@30 = gleam@http@response:set_body(
_pipe@29,
gleam@bit_builder:from_bit_string(
<<"Internal Server Error"/utf8>>
)
),
_pipe@31 = gleam@http@response:prepend_header(
_pipe@30,
<<"content-length"/utf8>>,
<<"21"/utf8>>
),
_pipe@32 = mist@encoder:to_bit_builder(
_pipe@31
),
glisten@tcp:send(Socket, _pipe@32),
glisten@tcp:close(Socket),
{stop, {abnormal, Msg@3}}
end
end
),
gleam@result:unwrap_both(_pipe@33)
end
end
).
-spec upgrade_socket(gleam@http@request:request(body())) -> {ok,
gleam@http@response:response(gleam@bit_builder:bit_builder())} |
{error, gleam@http@request:request(body())}.
upgrade_socket(Req) ->
case begin
_pipe = gleam@http@request:get_header(Req, <<"upgrade"/utf8>>),
gleam@result:replace_error(_pipe, Req)
end of
{error, _try} -> {error, _try};
{ok, _@1} ->
case begin
_pipe@1 = gleam@http@request:get_header(
Req,
<<"sec-websocket-key"/utf8>>
),
gleam@result:replace_error(_pipe@1, Req)
end of
{error, _try@1} -> {error, _try@1};
{ok, Key} ->
case begin
_pipe@2 = gleam@http@request:get_header(
Req,
<<"sec-websocket-version"/utf8>>
),
gleam@result:replace_error(_pipe@2, Req)
end of
{error, _try@2} -> {error, _try@2};
{ok, _@2} ->
Accept_key = mist@websocket:parse_key(Key),
_pipe@3 = gleam@http@response:new(101),
_pipe@4 = gleam@http@response:set_body(
_pipe@3,
gleam@bit_builder:from_bit_string(<<""/utf8>>)
),
_pipe@5 = gleam@http@response:prepend_header(
_pipe@4,
<<"Upgrade"/utf8>>,
<<"websocket"/utf8>>
),
_pipe@6 = gleam@http@response:prepend_header(
_pipe@5,
<<"Connection"/utf8>>,
<<"Upgrade"/utf8>>
),
_pipe@7 = gleam@http@response:prepend_header(
_pipe@6,
<<"Sec-WebSocket-Accept"/utf8>>,
Accept_key
),
{ok, _pipe@7}
end
end
end.
-spec upgrade(glisten@tcp:socket(), gleam@http@request:request(body())) -> {ok,
nil} |
{error, nil}.
upgrade(Socket, Req) ->
case begin
_pipe = upgrade_socket(Req),
gleam@result:replace_error(_pipe, nil)
end of
{error, _try} -> {error, _try};
{ok, Resp} ->
case begin
_pipe@1 = Resp,
_pipe@2 = mist@encoder:to_bit_builder(_pipe@1),
_pipe@3 = glisten@tcp:send(Socket, _pipe@2),
gleam@result:replace_error(_pipe@3, nil)
end of
{error, _try@1} -> {error, _try@1};
{ok, _@1} ->
{ok, nil}
end
end.