Skip to main content

src/aws@internal@http_request.erl

-module(aws@internal@http_request).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/aws/internal/http_request.gleam").
-export([parse/1]).
-export_type([http_request/0, header/0, parse_error/0]).

-type http_request() :: {http_request,
        binary(),
        binary(),
        binary(),
        list(header()),
        bitstring()}.

-type header() :: {header, binary(), binary()}.

-type parse_error() :: {malformed_request_line, binary()} |
    {malformed_header, binary()}.

-file("src/aws/internal/http_request.gleam", 104).
-spec is_continuation(binary()) -> boolean().
is_continuation(Line) ->
    gleam_stdlib:string_starts_with(Line, <<" "/utf8>>) orelse gleam_stdlib:string_starts_with(
        Line,
        <<"\t"/utf8>>
    ).

-file("src/aws/internal/http_request.gleam", 80).
-spec do_parse_headers(list(binary()), list(header())) -> {ok, list(header())} |
    {error, parse_error()}.
do_parse_headers(Lines, Acc) ->
    case Lines of
        [] ->
            {ok, lists:reverse(Acc)};

        [Line | Rest] ->
            case {is_continuation(Line), Acc} of
                {true, [{header, Name, Value} | Tail]} ->
                    Merged = {header,
                        Name,
                        <<<<Value/binary, " "/utf8>>/binary,
                            (gleam@string:trim(Line))/binary>>},
                    do_parse_headers(Rest, [Merged | Tail]);

                {true, []} ->
                    {error, {malformed_header, Line}};

                {false, _} ->
                    case gleam@string:split_once(Line, <<":"/utf8>>) of
                        {ok, {Name@1, Value@1}} ->
                            do_parse_headers(
                                Rest,
                                [{header, Name@1, Value@1} | Acc]
                            );

                        {error, _} ->
                            {error, {malformed_header, Line}}
                    end
            end
    end.

-file("src/aws/internal/http_request.gleam", 76).
-spec parse_headers(list(binary())) -> {ok, list(header())} |
    {error, parse_error()}.
parse_headers(Lines) ->
    do_parse_headers(Lines, []).

-file("src/aws/internal/http_request.gleam", 53).
-spec parse_request_line(binary()) -> {ok, {binary(), binary(), binary()}} |
    {error, parse_error()}.
parse_request_line(Line) ->
    case gleam@string:split(Line, <<" "/utf8>>) of
        [Method | Rest] ->
            case lists:reverse(Rest) of
                [_ | Target_parts_rev] ->
                    Target = begin
                        _pipe = Target_parts_rev,
                        _pipe@1 = lists:reverse(_pipe),
                        gleam@string:join(_pipe@1, <<" "/utf8>>)
                    end,
                    {Path, Query} = case gleam@string:split_once(
                        Target,
                        <<"?"/utf8>>
                    ) of
                        {ok, {P, Q}} ->
                            {P, Q};

                        {error, _} ->
                            {Target, <<""/utf8>>}
                    end,
                    {ok, {Method, Path, Query}};

                [] ->
                    {error, {malformed_request_line, Line}}
            end;

        [] ->
            {error, {malformed_request_line, Line}}
    end.

-file("src/aws/internal/http_request.gleam", 43).
-spec split_head_body(binary()) -> {binary(), binary()}.
split_head_body(Text) ->
    Normalized = gleam@string:replace(Text, <<"\r\n"/utf8>>, <<"\n"/utf8>>),
    case gleam@string:split_once(Normalized, <<"\n\n"/utf8>>) of
        {ok, {Head, Body}} ->
            {Head, Body};

        {error, _} ->
            {gleam@string:trim_end(Normalized), <<""/utf8>>}
    end.

-file("src/aws/internal/http_request.gleam", 25).
-spec parse(binary()) -> {ok, http_request()} | {error, parse_error()}.
parse(Text) ->
    {Head, Body} = split_head_body(Text),
    case gleam@string:split(Head, <<"\n"/utf8>>) of
        [] ->
            {error, {malformed_request_line, <<""/utf8>>}};

        [Request_line | Header_lines] ->
            gleam@result:'try'(
                parse_request_line(Request_line),
                fun(_use0) ->
                    {Method, Path, Query} = _use0,
                    gleam@result:'try'(
                        parse_headers(Header_lines),
                        fun(Headers) ->
                            {ok,
                                {http_request,
                                    Method,
                                    Path,
                                    Query,
                                    Headers,
                                    gleam_stdlib:identity(Body)}}
                        end
                    )
                end
            )
    end.