Current section
Files
Jump to
Current section
Files
src/multipartkit@parser.erl
-module(multipartkit@parser).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/multipartkit/parser.gleam").
-export([parse_with_limits/3, parse/2]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
-file("src/multipartkit/parser.gleam", 138).
-spec enforce_total(integer(), multipartkit@limit:limits()) -> {ok, nil} |
{error, multipartkit@error:multipart_error()}.
enforce_total(Consumed, Limits) ->
case Consumed > multipartkit@limit:max_body_bytes(Limits) of
true ->
{error, {body_too_large, multipartkit@limit:max_body_bytes(Limits)}};
false ->
{ok, nil}
end.
-file("src/multipartkit/parser.gleam", 53).
-spec parse_loop(
bitstring(),
bitstring(),
integer(),
multipartkit@limit:limits(),
list(multipartkit@part:part()),
integer()
) -> {ok, list(multipartkit@part:part())} |
{error, multipartkit@error:multipart_error()}.
parse_loop(Body, Pattern, Cursor, Limits, Acc, Parts_count) ->
case enforce_total(Cursor, Limits) of
{error, Err} ->
{error, Err};
{ok, _} ->
case multipartkit@internal@bytes:find_blank_line(Body, Cursor) of
{error, _} ->
{error, unexpected_end_of_input};
{ok, {Blank_at, Body_start}} ->
Header_block_size = Body_start - Cursor,
case Header_block_size > multipartkit@limit:max_header_bytes(
Limits
) of
true ->
{error,
{header_too_large,
multipartkit@limit:max_header_bytes(Limits)}};
false ->
Header_block = multipartkit@internal@bytes:slice_or_empty(
Body,
Cursor,
Blank_at - Cursor
),
case multipartkit@internal@headers:parse_block(
Header_block
) of
{error, Err@1} ->
{error, Err@1};
{ok, Header_list} ->
case multipartkit@internal@headers:derive_meta(
Header_list
) of
{error, Err@2} ->
{error, Err@2};
{ok, Meta} ->
case multipartkit@internal@scan:find_delimiter(
Body,
Pattern,
Body_start
) of
incomplete ->
{error,
unexpected_end_of_input};
{found,
Body_end_excl,
Kind,
After_delim} ->
Body_size = Body_end_excl - Body_start,
case Body_size > multipartkit@limit:max_part_bytes(
Limits
) of
true ->
{error,
{part_too_large,
multipartkit@limit:max_part_bytes(
Limits
)}};
false ->
Part_body = multipartkit@internal@bytes:slice_or_empty(
Body,
Body_start,
Body_size
),
New_part = multipartkit@part:new(
Header_list,
erlang:element(
2,
Meta
),
erlang:element(
3,
Meta
),
erlang:element(
4,
Meta
),
Part_body
),
New_count = Parts_count
+ 1,
case New_count > multipartkit@limit:max_parts(
Limits
) of
true ->
{error,
{too_many_parts,
multipartkit@limit:max_parts(
Limits
)}};
false ->
case enforce_total(
After_delim,
Limits
) of
{error,
Err@3} ->
{error,
Err@3};
{ok, _} ->
Acc@1 = [New_part |
Acc],
case Kind of
closing ->
{ok,
lists:reverse(
Acc@1
)};
delimiter ->
parse_loop(
Body,
Pattern,
After_delim,
Limits,
Acc@1,
New_count
)
end
end
end
end
end
end
end
end
end
end.
-file("src/multipartkit/parser.gleam", 26).
?DOC(" Parse a multipart body with caller-supplied limits.\n").
-spec parse_with_limits(bitstring(), binary(), multipartkit@limit:limits()) -> {ok,
list(multipartkit@part:part())} |
{error, multipartkit@error:multipart_error()}.
parse_with_limits(Body, Content_type, Limits) ->
case multipartkit@header:boundary(Content_type) of
{error, Err} ->
{error, Err};
{ok, Boundary_value} ->
Total = erlang:byte_size(Body),
case Total > multipartkit@limit:max_body_bytes(Limits) of
true ->
{error,
{body_too_large,
multipartkit@limit:max_body_bytes(Limits)}};
false ->
Pattern = multipartkit@internal@scan:dash_pattern(
Boundary_value
),
case multipartkit@internal@scan:find_delimiter(
Body,
Pattern,
0
) of
incomplete ->
{error, unexpected_end_of_input};
{found, _, closing, _} ->
{ok, []};
{found, _, delimiter, After_first} ->
parse_loop(
Body,
Pattern,
After_first,
Limits,
[],
0
)
end
end
end.
-file("src/multipartkit/parser.gleam", 18).
?DOC(
" Parse a multipart body using `default_limits()`.\n"
"\n"
" `content_type` must be the full HTTP Content-Type value, including the\n"
" `boundary` parameter — for example `multipart/form-data; boundary=abc`.\n"
).
-spec parse(bitstring(), binary()) -> {ok, list(multipartkit@part:part())} |
{error, multipartkit@error:multipart_error()}.
parse(Body, Content_type) ->
parse_with_limits(Body, Content_type, multipartkit@limit:default_limits()).