Current section

34 Versions

Jump to

Compare versions

12 files changed
+507 additions
-315 deletions
  @@ -8,12 +8,12 @@ Types and functions for HTTP clients and servers!
8 8 import gleam/http/elli
9 9 import gleam/http/response.{type Response}
10 10 import gleam/http/request.{type Request}
11 - import gleam/bytes_builder.{type BytesBuilder}
11 + import gleam/bytes_tree.{type BytesTree}
12 12
13 13 // Define a HTTP service
14 14 //
15 - pub fn my_service(_request: Request(t)) -> Response(BytesBuilder) {
16 - let body = bytes_builder.from_string("Hello, world!")
15 + pub fn my_service(_request: Request(t)) -> Response(BytesTree) {
16 + let body = bytes_tree.from_string("Hello, world!")
17 17
18 18 response.new(200)
19 19 |> response.prepend_header("made-with", "Gleam")
  @@ -1,5 +1,5 @@
1 1 name = "gleam_http"
2 - version = "3.7.2"
2 + version = "4.0.0"
3 3 licences = ["Apache-2.0"]
4 4 description = "Types and functions for Gleam HTTP clients and servers"
5 5 gleam = ">= 1.0.0"
  @@ -1,6 +1,6 @@
1 1 {<<"name">>, <<"gleam_http">>}.
2 2 {<<"app">>, <<"gleam_http">>}.
3 - {<<"version">>, <<"3.7.2">>}.
3 + {<<"version">>, <<"4.0.0">>}.
4 4 {<<"description">>, <<"Types and functions for Gleam HTTP clients and servers"/utf8>>}.
5 5 {<<"licenses">>, [<<"Apache-2.0">>]}.
6 6 {<<"build_tools">>, [<<"gleam">>]}.
  @@ -37,7 +37,5 @@
37 37 <<"src/gleam@http@request.erl">>,
38 38 <<"src/gleam@http@response.erl">>,
39 39 <<"src/gleam@http@service.erl">>,
40 - <<"src/gleam_http.app.src">>,
41 - <<"src/gleam_http_native.erl">>,
42 - <<"src/gleam_http_native.mjs">>
40 + <<"src/gleam_http.app.src">>
43 41 ]}.
  @@ -7,7 +7,6 @@
7 7
8 8 import gleam/bit_array
9 9 import gleam/bool
10 - import gleam/dynamic.{type DecodeError, type Dynamic, DecodeError}
11 10 import gleam/list
12 11 import gleam/result
13 12 import gleam/string
  @@ -29,34 +28,81 @@ pub type Method {
29 28 Other(String)
30 29 }
31 30
31 + // A token is defined as:
32 + //
33 + // token = 1*tchar
34 + //
35 + // tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*"
36 + // / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~"
37 + // / DIGIT / ALPHA
38 + // ; any VCHAR, except delimiters
39 + //
40 + // (From https://www.rfc-editor.org/rfc/rfc9110.html#name-tokens)
41 + //
42 + // Where DIGIT = %x30-39
43 + // ALPHA = %x41-5A / %x61-7A
44 + // (%xXX is a hexadecimal ASCII value)
45 + //
46 + // (From https://www.rfc-editor.org/rfc/rfc5234#appendix-B.1)
47 + //
48 + fn is_valid_token(s: String) -> Bool {
49 + bit_array.from_string(s)
50 + |> do_is_valid_token(True)
51 + }
52 +
53 + fn do_is_valid_token(bytes: BitArray, acc: Bool) {
54 + case bytes, acc {
55 + <<char, rest:bytes>>, True -> do_is_valid_token(rest, is_valid_tchar(char))
56 + _, _ -> acc
57 + }
58 + }
59 +
60 + fn is_valid_tchar(ch: Int) -> Bool {
61 + case ch {
62 + // "!" | "#" | "$" | "%" | "&" | "'" | "*" | "+" | "-"
63 + // | "." | "^" | "_" | "`" | "|" | "~"
64 + 33 | 35 | 36 | 37 | 38 | 39 | 42 | 43 | 45 | 46 | 94 | 95 | 96 | 124 | 126 ->
65 + True
66 + // DIGIT
67 + ch if ch >= 0x30 && ch <= 0x39 -> True
68 + // ALPHA
69 + ch if ch >= 0x41 && ch <= 0x5A || ch >= 0x61 && ch <= 0x7A -> True
70 + _ -> False
71 + }
72 + }
73 +
32 74 // TODO: check if the a is a valid HTTP method (i.e. it is a token, as per the
33 75 // spec) and return Ok(Other(s)) if so.
34 76 pub fn parse_method(s) -> Result(Method, Nil) {
35 - case string.lowercase(s) {
36 - "connect" -> Ok(Connect)
37 - "delete" -> Ok(Delete)
38 - "get" -> Ok(Get)
39 - "head" -> Ok(Head)
40 - "options" -> Ok(Options)
41 - "patch" -> Ok(Patch)
42 - "post" -> Ok(Post)
43 - "put" -> Ok(Put)
44 - "trace" -> Ok(Trace)
45 - _ -> Error(Nil)
77 + case s {
78 + "CONNECT" -> Ok(Connect)
79 + "DELETE" -> Ok(Delete)
80 + "GET" -> Ok(Get)
81 + "HEAD" -> Ok(Head)
82 + "OPTIONS" -> Ok(Options)
83 + "PATCH" -> Ok(Patch)
84 + "POST" -> Ok(Post)
85 + "PUT" -> Ok(Put)
86 + "TRACE" -> Ok(Trace)
87 + s ->
88 + case is_valid_token(s) {
89 + True -> Ok(Other(s))
90 + False -> Error(Nil)
91 + }
46 92 }
47 93 }
48 94
49 95 pub fn method_to_string(method: Method) -> String {
50 96 case method {
51 - Connect -> "connect"
52 - Delete -> "delete"
53 - Get -> "get"
54 - Head -> "head"
55 - Options -> "options"
56 - Patch -> "patch"
57 - Post -> "post"
58 - Put -> "put"
59 - Trace -> "trace"
97 + Connect -> "CONNECT"
98 + Delete -> "DELETE"
99 + Get -> "GET"
100 + Head -> "HEAD"
101 + Options -> "OPTIONS"
102 + Patch -> "PATCH"
103 + Post -> "POST"
104 + Put -> "PUT"
105 + Trace -> "TRACE"
60 106 Other(s) -> s
61 107 }
62 108 }
  @@ -103,13 +149,6 @@ pub fn scheme_from_string(scheme: String) -> Result(Scheme, Nil) {
103 149 }
104 150 }
105 151
106 - pub fn method_from_dynamic(value: Dynamic) -> Result(Method, List(DecodeError)) {
107 - case do_method_from_dynamic(value) {
108 - Ok(method) -> Ok(method)
109 - Error(_) -> Error([DecodeError("HTTP method", dynamic.classify(value), [])])
110 - }
111 - }
112 -
113 152 pub type MultipartHeaders {
114 153 /// The headers for the part have been fully parsed.
115 154 /// Header keys are all lowercase.
  @@ -553,10 +592,6 @@ fn more_please_body(
553 592 |> Ok
554 593 }
555 594
556 - @external(erlang, "gleam_http_native", "decode_method")
557 - @external(javascript, "../gleam_http_native.mjs", "decode_method")
558 - fn do_method_from_dynamic(a: Dynamic) -> Result(Method, Nil)
559 -
560 595 /// A HTTP header is a key-value pair. Header keys must be all lowercase
561 596 /// characters.
562 597 pub type Header =
  @@ -1,9 +1,26 @@
1 1 -module(gleam@http).
2 2 -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
3 3
4 - -export([parse_method/1, method_to_string/1, scheme_to_string/1, scheme_from_string/1, parse_content_disposition/1, parse_multipart_body/2, method_from_dynamic/1, parse_multipart_headers/2]).
4 + -export([parse_method/1, method_to_string/1, scheme_to_string/1, scheme_from_string/1, parse_content_disposition/1, parse_multipart_body/2, parse_multipart_headers/2]).
5 5 -export_type([method/0, scheme/0, multipart_headers/0, multipart_body/0, content_disposition/0]).
6 6
7 + -if(?OTP_RELEASE >= 27).
8 + -define(MODULEDOC(Str), -moduledoc(Str)).
9 + -define(DOC(Str), -doc(Str)).
10 + -else.
11 + -define(MODULEDOC(Str), -compile([])).
12 + -define(DOC(Str), -compile([])).
13 + -endif.
14 +
15 + ?MODULEDOC(
16 + " Functions for working with HTTP data structures in Gleam.\n"
17 + "\n"
18 + " This module makes it easy to create and modify Requests and Responses, data types.\n"
19 + " A general HTTP message type is defined that enables functions to work on both requests and responses.\n"
20 + "\n"
21 + " This module does not implement a HTTP client or HTTP server, but it can be used as a base for them.\n"
22 + ).
23 +
7 24 -type method() :: get |
8 25 post |
9 26 head |
  @@ -32,77 +49,170 @@
32 49 binary(),
33 50 list({binary(), binary()})}.
34 51
35 - -file("/Users/louis/src/gleam/http/src/gleam/http.gleam", 34).
36 - -spec parse_method(binary()) -> {ok, method()} | {error, nil}.
37 - parse_method(S) ->
38 - case string:lowercase(S) of
39 - <<"connect"/utf8>> ->
40 - {ok, connect};
52 + -file("src/gleam/http.gleam", 60).
53 + -spec is_valid_tchar(integer()) -> boolean().
54 + is_valid_tchar(Ch) ->
55 + case Ch of
56 + 33 ->
57 + true;
41 58
42 - <<"delete"/utf8>> ->
43 - {ok, delete};
59 + 35 ->
60 + true;
44 61
45 - <<"get"/utf8>> ->
46 - {ok, get};
62 + 36 ->
63 + true;
47 64
48 - <<"head"/utf8>> ->
49 - {ok, head};
65 + 37 ->
66 + true;
50 67
51 - <<"options"/utf8>> ->
52 - {ok, options};
68 + 38 ->
69 + true;
53 70
54 - <<"patch"/utf8>> ->
55 - {ok, patch};
71 + 39 ->
72 + true;
56 73
57 - <<"post"/utf8>> ->
58 - {ok, post};
74 + 42 ->
75 + true;
59 76
60 - <<"put"/utf8>> ->
61 - {ok, put};
77 + 43 ->
78 + true;
62 79
63 - <<"trace"/utf8>> ->
64 - {ok, trace};
80 + 45 ->
81 + true;
82 +
83 + 46 ->
84 + true;
85 +
86 + 94 ->
87 + true;
88 +
89 + 95 ->
90 + true;
91 +
92 + 96 ->
93 + true;
94 +
95 + 124 ->
96 + true;
97 +
98 + 126 ->
99 + true;
100 +
101 + Ch@1 when (Ch@1 >= 16#30) andalso (Ch@1 =< 16#39) ->
102 + true;
103 +
104 + Ch@2 when ((Ch@2 >= 16#41) andalso (Ch@2 =< 16#5A)) orelse ((Ch@2 >= 16#61) andalso (Ch@2 =< 16#7A)) ->
105 + true;
65 106
66 107 _ ->
67 - {error, nil}
108 + false
68 109 end.
69 110
70 - -file("/Users/louis/src/gleam/http/src/gleam/http.gleam", 49).
111 + -file("src/gleam/http.gleam", 53).
112 + -spec do_is_valid_token(bitstring(), boolean()) -> boolean().
113 + do_is_valid_token(Bytes, Acc) ->
114 + case {Bytes, Acc} of
115 + {<<Char, Rest/binary>>, true} ->
116 + do_is_valid_token(Rest, is_valid_tchar(Char));
117 +
118 + {_, _} ->
119 + Acc
120 + end.
121 +
122 + -file("src/gleam/http.gleam", 48).
123 + -spec is_valid_token(binary()) -> boolean().
124 + is_valid_token(S) ->
125 + _pipe = gleam_stdlib:identity(S),
126 + do_is_valid_token(_pipe, true).
127 +
128 + -file("src/gleam/http.gleam", 76).
129 + -spec parse_method(binary()) -> {ok, method()} | {error, nil}.
130 + parse_method(S) ->
131 + case S of
132 + <<"CONNECT"/utf8>> ->
133 + {ok, connect};
134 +
135 + <<"DELETE"/utf8>> ->
136 + {ok, delete};
137 +
138 + <<"GET"/utf8>> ->
139 + {ok, get};
140 +
141 + <<"HEAD"/utf8>> ->
142 + {ok, head};
143 +
144 + <<"OPTIONS"/utf8>> ->
145 + {ok, options};
146 +
147 + <<"PATCH"/utf8>> ->
148 + {ok, patch};
149 +
150 + <<"POST"/utf8>> ->
151 + {ok, post};
152 +
153 + <<"PUT"/utf8>> ->
154 + {ok, put};
155 +
156 + <<"TRACE"/utf8>> ->
157 + {ok, trace};
158 +
159 + S@1 ->
160 + case is_valid_token(S@1) of
161 + true ->
162 + {ok, {other, S@1}};
163 +
164 + false ->
165 + {error, nil}
166 + end
167 + end.
168 +
169 + -file("src/gleam/http.gleam", 95).
71 170 -spec method_to_string(method()) -> binary().
72 171 method_to_string(Method) ->
73 172 case Method of
74 173 connect ->
75 - <<"connect"/utf8>>;
174 + <<"CONNECT"/utf8>>;
76 175
77 176 delete ->
78 - <<"delete"/utf8>>;
177 + <<"DELETE"/utf8>>;
79 178
80 179 get ->
81 - <<"get"/utf8>>;
180 + <<"GET"/utf8>>;
82 181
83 182 head ->
84 - <<"head"/utf8>>;
183 + <<"HEAD"/utf8>>;
85 184
86 185 options ->
87 - <<"options"/utf8>>;
186 + <<"OPTIONS"/utf8>>;
88 187
89 188 patch ->
90 - <<"patch"/utf8>>;
189 + <<"PATCH"/utf8>>;
91 190
92 191 post ->
93 - <<"post"/utf8>>;
192 + <<"POST"/utf8>>;
94 193
95 194 put ->
96 - <<"put"/utf8>>;
195 + <<"PUT"/utf8>>;
97 196
98 197 trace ->
99 - <<"trace"/utf8>>;
198 + <<"TRACE"/utf8>>;
100 199
101 200 {other, S} ->
102 201 S
103 202 end.
104 203
105 - -file("/Users/louis/src/gleam/http/src/gleam/http.gleam", 81).
204 + -file("src/gleam/http.gleam", 127).
205 + ?DOC(
206 + " Convert a scheme into a string.\n"
207 + "\n"
208 + " # Examples\n"
209 + "\n"
210 + " > scheme_to_string(Http)\n"
211 + " \"http\"\n"
212 + "\n"
213 + " > scheme_to_string(Https)\n"
214 + " \"https\"\n"
215 + ).
106 216 -spec scheme_to_string(scheme()) -> binary().
107 217 scheme_to_string(Scheme) ->
108 218 case Scheme of
  @@ -113,7 +223,18 @@ scheme_to_string(Scheme) ->
113 223 <<"https"/utf8>>
114 224 end.
115 225
116 - -file("/Users/louis/src/gleam/http/src/gleam/http.gleam", 98).
226 + -file("src/gleam/http.gleam", 144).
227 + ?DOC(
228 + " Parse a HTTP scheme from a string\n"
229 + "\n"
230 + " # Examples\n"
231 + "\n"
232 + " > scheme_from_string(\"http\")\n"
233 + " Ok(Http)\n"
234 + "\n"
235 + " > scheme_from_string(\"ftp\")\n"
236 + " Error(Nil)\n"
237 + ).
117 238 -spec scheme_from_string(binary()) -> {ok, scheme()} | {error, nil}.
118 239 scheme_from_string(Scheme) ->
119 240 case string:lowercase(Scheme) of
  @@ -127,7 +248,7 @@ scheme_from_string(Scheme) ->
127 248 {error, nil}
128 249 end.
129 250
130 - -file("/Users/louis/src/gleam/http/src/gleam/http.gleam", 337).
251 + -file("src/gleam/http.gleam", 376).
131 252 -spec skip_whitespace(bitstring()) -> bitstring().
132 253 skip_whitespace(Data) ->
133 254 case Data of
  @@ -141,7 +262,7 @@ skip_whitespace(Data) ->
141 262 Data
142 263 end.
143 264
144 - -file("/Users/louis/src/gleam/http/src/gleam/http.gleam", 427).
265 + -file("src/gleam/http.gleam", 466).
145 266 -spec more_please_headers(
146 267 fun((bitstring()) -> {ok, multipart_headers()} | {error, nil}),
147 268 bitstring()
  @@ -159,7 +280,7 @@ more_please_headers(Continuation, Existing) ->
159 280 )
160 281 end}}.
161 282
162 - -file("/Users/louis/src/gleam/http/src/gleam/http.gleam", 508).
283 + -file("src/gleam/http.gleam", 547).
163 284 -spec parse_rfc_2045_parameter_quoted_value(binary(), binary(), binary()) -> {ok,
164 285 {{binary(), binary()}, binary()}} |
165 286 {error, nil}.
  @@ -192,7 +313,7 @@ parse_rfc_2045_parameter_quoted_value(Header, Name, Value) ->
192 313 )
193 314 end.
194 315
195 - -file("/Users/louis/src/gleam/http/src/gleam/http.gleam", 525).
316 + -file("src/gleam/http.gleam", 564).
196 317 -spec parse_rfc_2045_parameter_unquoted_value(binary(), binary(), binary()) -> {{binary(),
197 318 binary()},
198 319 binary()}.
  @@ -218,7 +339,7 @@ parse_rfc_2045_parameter_unquoted_value(Header, Name, Value) ->
218 339 )
219 340 end.
220 341
221 - -file("/Users/louis/src/gleam/http/src/gleam/http.gleam", 496).
342 + -file("src/gleam/http.gleam", 535).
222 343 -spec parse_rfc_2045_parameter_value(binary(), binary()) -> {ok,
223 344 {{binary(), binary()}, binary()}} |
224 345 {error, nil}.
  @@ -235,7 +356,7 @@ parse_rfc_2045_parameter_value(Header, Name) ->
235 356 parse_rfc_2045_parameter_unquoted_value(Rest@1, Name, Grapheme)}
236 357 end.
237 358
238 - -file("/Users/louis/src/gleam/http/src/gleam/http.gleam", 485).
359 + -file("src/gleam/http.gleam", 524).
239 360 -spec parse_rfc_2045_parameter(binary(), binary()) -> {ok,
240 361 {{binary(), binary()}, binary()}} |
241 362 {error, nil}.
  @@ -257,7 +378,7 @@ parse_rfc_2045_parameter(Header, Name) ->
257 378 end
258 379 ).
259 380
260 - -file("/Users/louis/src/gleam/http/src/gleam/http.gleam", 467).
381 + -file("src/gleam/http.gleam", 506).
261 382 -spec parse_rfc_2045_parameters(binary(), list({binary(), binary()})) -> {ok,
262 383 list({binary(), binary()})} |
263 384 {error, nil}.
  @@ -286,7 +407,7 @@ parse_rfc_2045_parameters(Header, Parameters) ->
286 407 )
287 408 end.
288 409
289 - -file("/Users/louis/src/gleam/http/src/gleam/http.gleam", 449).
410 + -file("src/gleam/http.gleam", 488).
290 411 -spec parse_content_disposition_type(binary(), binary()) -> {ok,
291 412 content_disposition()} |
292 413 {error, nil}.
  @@ -323,13 +444,13 @@ parse_content_disposition_type(Header, Name) ->
323 444 )
324 445 end.
325 446
326 - -file("/Users/louis/src/gleam/http/src/gleam/http.gleam", 443).
447 + -file("src/gleam/http.gleam", 482).
327 448 -spec parse_content_disposition(binary()) -> {ok, content_disposition()} |
328 449 {error, nil}.
329 450 parse_content_disposition(Header) ->
330 451 parse_content_disposition_type(Header, <<""/utf8>>).
331 452
332 - -file("/Users/louis/src/gleam/http/src/gleam/http.gleam", 543).
453 + -file("src/gleam/http.gleam", 582).
333 454 -spec more_please_body(
334 455 fun((bitstring()) -> {ok, multipart_body()} | {error, nil}),
335 456 bitstring(),
  @@ -346,7 +467,7 @@ more_please_body(Continuation, Chunk, Existing) ->
346 467 _pipe@1 = {more_required_for_body, Chunk, _pipe},
347 468 {ok, _pipe@1}.
348 469
349 - -file("/Users/louis/src/gleam/http/src/gleam/http.gleam", 216).
470 + -file("src/gleam/http.gleam", 255).
350 471 -spec parse_body_loop(bitstring(), bitstring(), bitstring()) -> {ok,
351 472 multipart_body()} |
352 473 {error, nil}.
  @@ -394,10 +515,10 @@ parse_body_loop(Data, Boundary, Body) ->
394 515 message => <<"unreachable"/utf8>>,
395 516 module => <<"gleam/http"/utf8>>,
396 517 function => <<"parse_body_loop"/utf8>>,
397 - line => 257})
518 + line => 296})
398 519 end.
399 520
400 - -file("/Users/louis/src/gleam/http/src/gleam/http.gleam", 204).
521 + -file("src/gleam/http.gleam", 243).
401 522 -spec parse_body_with_bit_array(bitstring(), bitstring()) -> {ok,
402 523 multipart_body()} |
403 524 {error, nil}.
  @@ -412,7 +533,20 @@ parse_body_with_bit_array(Data, Boundary) ->
412 533 parse_body_loop(Data, Boundary, <<>>)
413 534 end.
414 535
415 - -file("/Users/louis/src/gleam/http/src/gleam/http.gleam", 195).
536 + -file("src/gleam/http.gleam", 234).
537 + ?DOC(
538 + " Parse the body for part of a multipart message, as defined in RFC 2045. The\n"
539 + " body is everything until the next boundary. This function is generally to be\n"
540 + " called after calling `parse_multipart_headers` for a given part.\n"
541 + "\n"
542 + " This function will accept input of any size, it is up to the caller to limit\n"
543 + " it if needed.\n"
544 + "\n"
545 + " To enable streaming parsing of multipart messages, this function will return\n"
546 + " a continuation if there is not enough data to fully parse the body, along\n"
547 + " with the data that has been parsed so far. Further information is available\n"
548 + " in the documentation for `MultipartBody`.\n"
549 + ).
416 550 -spec parse_multipart_body(bitstring(), binary()) -> {ok, multipart_body()} |
417 551 {error, nil}.
418 552 parse_multipart_body(Data, Boundary) ->
  @@ -420,23 +554,7 @@ parse_multipart_body(Data, Boundary) ->
420 554 _pipe@1 = gleam_stdlib:identity(_pipe),
421 555 parse_body_with_bit_array(Data, _pipe@1).
422 556
423 - -file("/Users/louis/src/gleam/http/src/gleam/http.gleam", 106).
424 - -spec method_from_dynamic(gleam@dynamic:dynamic_()) -> {ok, method()} |
425 - {error, list(gleam@dynamic:decode_error())}.
426 - method_from_dynamic(Value) ->
427 - case gleam_http_native:decode_method(Value) of
428 - {ok, Method} ->
429 - {ok, Method};
430 -
431 - {error, _} ->
432 - {error,
433 - [{decode_error,
434 - <<"HTTP method"/utf8>>,
435 - gleam_stdlib:classify_dynamic(Value),
436 - []}]}
437 - end.
438 -
439 - -file("/Users/louis/src/gleam/http/src/gleam/http.gleam", 380).
557 + -file("src/gleam/http.gleam", 419).
440 558 -spec parse_header_value(
441 559 bitstring(),
442 560 list({binary(), binary()}),
  @@ -497,7 +615,7 @@ parse_header_value(Data, Headers, Name, Value) ->
497 615 {error, nil}
498 616 end.
499 617
500 - -file("/Users/louis/src/gleam/http/src/gleam/http.gleam", 361).
618 + -file("src/gleam/http.gleam", 400).
501 619 -spec parse_header_name(bitstring(), list({binary(), binary()}), bitstring()) -> {ok,
502 620 multipart_headers()} |
503 621 {error, nil}.
  @@ -518,7 +636,7 @@ parse_header_name(Data, Headers, Name) ->
518 636 )
519 637 end.
520 638
521 - -file("/Users/louis/src/gleam/http/src/gleam/http.gleam", 345).
639 + -file("src/gleam/http.gleam", 384).
522 640 -spec do_parse_headers(bitstring()) -> {ok, multipart_headers()} | {error, nil}.
523 641 do_parse_headers(Data) ->
524 642 case Data of
  @@ -538,7 +656,7 @@ do_parse_headers(Data) ->
538 656 {error, nil}
539 657 end.
540 658
541 - -file("/Users/louis/src/gleam/http/src/gleam/http.gleam", 261).
659 + -file("src/gleam/http.gleam", 300).
542 660 -spec parse_headers_after_prelude(bitstring(), bitstring()) -> {ok,
543 661 multipart_headers()} |
544 662 {error, nil}.
  @@ -602,7 +720,7 @@ parse_headers_after_prelude(Data, Boundary) ->
602 720 end
603 721 ).
604 722
605 - -file("/Users/louis/src/gleam/http/src/gleam/http.gleam", 303).
723 + -file("src/gleam/http.gleam", 342).
606 724 -spec skip_preamble(bitstring(), bitstring()) -> {ok, multipart_headers()} |
607 725 {error, nil}.
608 726 skip_preamble(Data, Boundary) ->
  @@ -641,10 +759,23 @@ skip_preamble(Data, Boundary) ->
641 759 message => <<"unreachable"/utf8>>,
642 760 module => <<"gleam/http"/utf8>>,
643 761 function => <<"skip_preamble"/utf8>>,
644 - line => 333})
762 + line => 372})
645 763 end.
646 764
647 - -file("/Users/louis/src/gleam/http/src/gleam/http.gleam", 167).
765 + -file("src/gleam/http.gleam", 206).
766 + ?DOC(
767 + " Parse the headers for part of a multipart message, as defined in RFC 2045.\n"
768 + "\n"
769 + " This function skips any preamble before the boundary. The preamble may be\n"
770 + " retrieved using `parse_multipart_body`.\n"
771 + "\n"
772 + " This function will accept input of any size, it is up to the caller to limit\n"
773 + " it if needed.\n"
774 + "\n"
775 + " To enable streaming parsing of multipart messages, this function will return\n"
776 + " a continuation if there is not enough data to fully parse the headers.\n"
777 + " Further information is available in the documentation for `MultipartBody`.\n"
778 + ).
648 779 -spec parse_multipart_headers(bitstring(), binary()) -> {ok,
649 780 multipart_headers()} |
650 781 {error, nil}.
Loading more files…