Current section
34 Versions
Jump to
Current section
34 Versions
Compare versions
8
files changed
+694
additions
-698
deletions
| @@ -1,5 +1,5 @@ | |
| 1 1 | name = "gleam_http" |
| 2 | - version = "4.2.0" |
| 2 | + version = "4.3.0" |
| 3 3 | licences = ["Apache-2.0"] |
| 4 4 | description = "Types and functions for Gleam HTTP clients and servers" |
| 5 5 | gleam = ">= 1.11.0" |
| @@ -1,6 +1,6 @@ | |
| 1 1 | {<<"name">>, <<"gleam_http">>}. |
| 2 2 | {<<"app">>, <<"gleam_http">>}. |
| 3 | - {<<"version">>, <<"4.2.0">>}. |
| 3 | + {<<"version">>, <<"4.3.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">>]}. |
| @@ -273,14 +273,169 @@ pub fn parse_multipart_headers( | |
| 273 273 | boundary: String, |
| 274 274 | ) -> Result(MultipartHeaders, Nil) { |
| 275 275 | let boundary = bit_array.from_string(boundary) |
| 276 | - // TODO: rewrite this to use a bit pattern once JavaScript supports |
| 277 | - // the `b:binary-size(bsize)` pattern. |
| 278 | - let prefix = <<45, 45, boundary:bits>> |
| 279 | - case bit_array.slice(data, 0, bit_array.byte_size(prefix)) == Ok(prefix) { |
| 280 | - // There is no preamble, parse the headers. |
| 281 | - True -> parse_headers_after_prelude(data, boundary) |
| 282 | - // There is a preamble, skip it before parsing. |
| 283 | - False -> skip_preamble(data, boundary) |
| 276 | + let boundary_bytes = bit_array.byte_size(boundary) |
| 277 | + do_parse_multipart_headers(data, boundary, boundary_bytes) |
| 278 | + } |
| 279 | + |
| 280 | + fn do_parse_multipart_headers( |
| 281 | + data: BitArray, |
| 282 | + boundary: BitArray, |
| 283 | + boundary_bytes: Int, |
| 284 | + ) -> Result(MultipartHeaders, Nil) { |
| 285 | + case data { |
| 286 | + // The headers start right away with a boundary. |
| 287 | + <<"--", found:size(boundary_bytes)-bytes, rest:bits>> if found == boundary -> |
| 288 | + case rest { |
| 289 | + // Final boundary `--boundary--`. |
| 290 | + <<"--", rest:bits>> -> Ok(MultipartHeaders([], remaining: rest)) |
| 291 | + |
| 292 | + // Regular boundary `--boundary`. |
| 293 | + <<_, _, _:bits>> -> do_parse_headers(rest) |
| 294 | + |
| 295 | + // Not enough bytes to make a choice, we have to wait for more. |
| 296 | + _ -> |
| 297 | + more_please_headers(data, fn(data) { |
| 298 | + do_parse_multipart_headers(data, boundary, boundary_bytes) |
| 299 | + }) |
| 300 | + } |
| 301 | + |
| 302 | + // The headers start with a preamble we need to skip. |
| 303 | + _ -> skip_preamble(data, boundary, boundary_bytes) |
| 304 | + } |
| 305 | + } |
| 306 | + |
| 307 | + fn skip_preamble( |
| 308 | + data: BitArray, |
| 309 | + boundary: BitArray, |
| 310 | + boundary_bytes: Int, |
| 311 | + ) -> Result(MultipartHeaders, Nil) { |
| 312 | + case data { |
| 313 | + // We might have found the preamble end! |
| 314 | + <<"\r\n--", rest:bytes>> -> { |
| 315 | + case rest { |
| 316 | + // It is indeed the end, we go on parsing the headers that come after |
| 317 | + // the boundary. |
| 318 | + <<found:size(boundary_bytes)-bytes, rest:bits>> if found == boundary -> |
| 319 | + do_parse_headers(rest) |
| 320 | + |
| 321 | + // This was not the end because `\r\n--` is not followed by the expected |
| 322 | + // boundary, so we keep ignoring bytes. |
| 323 | + <<_found:size(boundary_bytes)-bytes, _:bits>> -> |
| 324 | + skip_preamble(rest, boundary, boundary_bytes) |
| 325 | + |
| 326 | + // There's not enough bytes to make sure the `\r\n--` is not followed |
| 327 | + // by the closing boundary so we have to wait for more to come. |
| 328 | + _ -> |
| 329 | + more_please_headers(data, skip_preamble(_, boundary, boundary_bytes)) |
| 330 | + } |
| 331 | + } |
| 332 | + |
| 333 | + // We don't have enough bytes to be sure this is not the end of the preamble |
| 334 | + // so we have to wait for more to come. |
| 335 | + <<>> | <<"\r">> | <<"\r\n">> | <<"\r\n-">> -> |
| 336 | + more_please_headers(data, skip_preamble(_, boundary, boundary_bytes)) |
| 337 | + |
| 338 | + // The byte is surely part of the preamble and can be skipped. |
| 339 | + <<_, data:bytes>> -> skip_preamble(data, boundary, boundary_bytes) |
| 340 | + |
| 341 | + _ -> panic as "unreachable" |
| 342 | + } |
| 343 | + } |
| 344 | + |
| 345 | + fn do_parse_headers(data: BitArray) -> Result(MultipartHeaders, Nil) { |
| 346 | + case data { |
| 347 | + // We've reached the end, there are no headers. |
| 348 | + <<"\r\n\r\n", data:bytes>> -> Ok(MultipartHeaders([], remaining: data)) |
| 349 | + |
| 350 | + // Skip the line break after the boundary. |
| 351 | + <<"\r\n", data:bytes>> -> parse_header_name(data, []) |
| 352 | + |
| 353 | + <<"\r">> | <<>> -> more_please_headers(data, do_parse_headers) |
| 354 | + |
| 355 | + _ -> Error(Nil) |
| 356 | + } |
| 357 | + } |
| 358 | + |
| 359 | + fn parse_header_name( |
| 360 | + data: BitArray, |
| 361 | + headers: List(Header), |
| 362 | + ) -> Result(MultipartHeaders, Nil) { |
| 363 | + case data { |
| 364 | + // We first have to skip all whitespace preceding the name. |
| 365 | + <<" ", rest:bits>> | <<"\t", rest:bits>> -> parse_header_name(rest, headers) |
| 366 | + <<_, _:bits>> -> parse_header_name_loop(data, headers, <<>>) |
| 367 | + |
| 368 | + // We don't have enough bits to make a choice and will have to wait for more |
| 369 | + // to come. |
| 370 | + _ -> more_please_headers(data, parse_header_name(_, headers)) |
| 371 | + } |
| 372 | + } |
| 373 | + |
| 374 | + fn parse_header_name_loop(data: BitArray, headers: List(Header), name: BitArray) { |
| 375 | + case data { |
| 376 | + // We've found the end of the header, we can now start parsing its value. |
| 377 | + <<":", data:bits>> -> |
| 378 | + case bit_array.to_string(name) { |
| 379 | + Ok(name) -> parse_header_value(data, headers, name) |
| 380 | + Error(Nil) -> Error(Nil) |
| 381 | + } |
| 382 | + |
| 383 | + // Otherwise the character belongs to the header. |
| 384 | + <<char, data:bits>> -> |
| 385 | + parse_header_name_loop(data, headers, <<name:bits, char>>) |
| 386 | + |
| 387 | + // We don't have enough bits to make a choice and have to wait for more to |
| 388 | + // come. |
| 389 | + _ -> more_please_headers(data, parse_header_name_loop(_, headers, name)) |
| 390 | + } |
| 391 | + } |
| 392 | + |
| 393 | + fn parse_header_value(data: BitArray, headers: List(Header), name: String) { |
| 394 | + case data { |
| 395 | + // We first have to skip all whitespace preceding the value. |
| 396 | + <<" ", rest:bits>> | <<"\t", rest:bits>> -> |
| 397 | + parse_header_value(rest, headers, name) |
| 398 | + |
| 399 | + <<_, _:bits>> -> parse_header_value_loop(data, headers, name, <<>>) |
| 400 | + |
| 401 | + // We don't have enough bits to make a choice and will have to wait for more |
| 402 | + // to come. |
| 403 | + _ -> more_please_headers(data, parse_header_value(_, headers, name)) |
| 404 | + } |
| 405 | + } |
| 406 | + |
| 407 | + fn parse_header_value_loop( |
| 408 | + data: BitArray, |
| 409 | + headers: List(Header), |
| 410 | + name: String, |
| 411 | + value: BitArray, |
| 412 | + ) -> Result(MultipartHeaders, Nil) { |
| 413 | + case data { |
| 414 | + // We need at least 4 bytes to check for the end of the headers. |
| 415 | + <<>> | <<_>> | <<_, _>> | <<_, _, _>> -> |
| 416 | + more_please_headers(data, fn(data) { |
| 417 | + parse_header_value_loop(data, headers, name, value) |
| 418 | + }) |
| 419 | + |
| 420 | + <<"\r\n\r\n", data:bytes>> -> { |
| 421 | + use value <- result.map(bit_array.to_string(value)) |
| 422 | + let headers = list.reverse([#(string.lowercase(name), value), ..headers]) |
| 423 | + MultipartHeaders(headers:, remaining: data) |
| 424 | + } |
| 425 | + |
| 426 | + <<"\r\n ", data:bytes>> | <<"\r\n\t", data:bytes>> -> |
| 427 | + parse_header_value_loop(data, headers, name, value) |
| 428 | + |
| 429 | + <<"\r\n", data:bytes>> -> { |
| 430 | + use value <- result.try(bit_array.to_string(value)) |
| 431 | + let headers = [#(string.lowercase(name), value), ..headers] |
| 432 | + parse_header_name(data, headers) |
| 433 | + } |
| 434 | + |
| 435 | + <<char, rest:bytes>> -> |
| 436 | + parse_header_value_loop(rest, headers, name, <<value:bits, char>>) |
| 437 | + |
| 438 | + _ -> Error(Nil) |
| 284 439 | } |
| 285 440 | } |
| 286 441 | |
| @@ -300,237 +455,75 @@ pub fn parse_multipart_body( | |
| 300 455 | data: BitArray, |
| 301 456 | boundary: String, |
| 302 457 | ) -> Result(MultipartBody, Nil) { |
| 303 | - boundary |
| 304 | - |> bit_array.from_string |
| 305 | - |> parse_body_with_bit_array(data, _) |
| 458 | + let boundary = bit_array.from_string(boundary) |
| 459 | + let boundary_bytes = bit_array.byte_size(boundary) |
| 460 | + do_parse_multipart_body(data, boundary, boundary_bytes) |
| 306 461 | } |
| 307 462 | |
| 308 | - fn parse_body_with_bit_array( |
| 463 | + fn do_parse_multipart_body( |
| 309 464 | data: BitArray, |
| 310 465 | boundary: BitArray, |
| 466 | + boundary_bytes: Int, |
| 311 467 | ) -> Result(MultipartBody, Nil) { |
| 312 | - let bsize = bit_array.byte_size(boundary) |
| 313 | - let prefix = bit_array.slice(data, 0, 2 + bsize) |
| 314 | - case prefix == Ok(<<45, 45, boundary:bits>>) { |
| 315 | - True -> Ok(MultipartBody(<<>>, done: False, remaining: data)) |
| 316 | - False -> parse_body_loop(data, boundary, <<>>) |
| 468 | + case data { |
| 469 | + <<"--", found:size(boundary_bytes)-bytes, _:bytes>> if found == boundary -> |
| 470 | + Ok(MultipartBody(<<>>, done: False, remaining: data)) |
| 471 | + _ -> parse_body_loop(data, boundary, boundary_bytes, <<>>) |
| 317 472 | } |
| 318 473 | } |
| 319 474 | |
| 320 475 | fn parse_body_loop( |
| 321 476 | data: BitArray, |
| 322 477 | boundary: BitArray, |
| 478 | + boundary_bytes: Int, |
| 323 479 | body: BitArray, |
| 324 480 | ) -> Result(MultipartBody, Nil) { |
| 325 | - let dsize = bit_array.byte_size(data) |
| 326 | - let bsize = bit_array.byte_size(boundary) |
| 327 | - let required = 6 + bsize |
| 328 481 | case data { |
| 329 | - _ if dsize < required -> { |
| 330 | - more_please_body(parse_body_loop(_, boundary, <<>>), body, data) |
| 331 | - } |
| 482 | + <<>> | <<"\r">> -> |
| 483 | + more_please_body(body, data, fn(data) { |
| 484 | + parse_body_loop(data, boundary, boundary_bytes, <<>>) |
| 485 | + }) |
| 332 486 | |
| 333 | - // TODO: flatten this into a single case expression once JavaScript supports |
| 334 | - // the `b:binary-size(bsize)` pattern. |
| 335 | - // |
| 336 | - // \r\n |
| 337 | - <<13, 10, data:bytes>> -> { |
| 338 | - let desired = <<45, 45, boundary:bits>> |
| 339 | - let size = bit_array.byte_size(desired) |
| 340 | - let dsize = bit_array.byte_size(data) |
| 341 | - let prefix = bit_array.slice(data, 0, size) |
| 342 | - let rest = bit_array.slice(data, size, dsize - size) |
| 343 | - case prefix == Ok(desired), rest { |
| 344 | - // --boundary\r\n |
| 345 | - True, Ok(<<13, 10, _:bytes>>) -> |
| 346 | - Ok(MultipartBody(body, done: False, remaining: data)) |
| 487 | + <<"\r\n", rest:bits>> -> |
| 488 | + case rest { |
| 489 | + // This string match is written as `"\r", "\n"` (instead of just |
| 490 | + // `"\r\n"`) to work around this compiler bug: |
| 491 | + // https://github.com/gleam-lang/gleam/issues/4993 |
| 492 | + // |
| 493 | + // Even after that is fixed want to keep it like this to make sure the |
| 494 | + // http library will work with older gleam versions on the js target. |
| 495 | + // So please don't change it! |
| 496 | + // |
| 497 | + // vvvvvvvvvv This one right here! |
| 498 | + <<"--", found:size(boundary_bytes)-bytes, "\r", "\n", _:bits>> |
| 499 | + if found == boundary |
| 500 | + -> Ok(MultipartBody(body, done: False, remaining: rest)) |
| 347 501 | |
| 348 | - // --boundary-- |
| 349 | - True, Ok(<<45, 45, data:bytes>>) -> |
| 350 | - Ok(MultipartBody(body, done: True, remaining: data)) |
| 502 | + // Same goes for this match as well! |
| 503 | + // vvvvvvvvvv This one right here! |
| 504 | + <<"--", found:size(boundary_bytes)-bytes, "-", "-", rest:bits>> |
| 505 | + if found == boundary |
| 506 | + -> Ok(MultipartBody(body, done: True, remaining: rest)) |
| 351 507 | |
| 352 | - False, _ -> parse_body_loop(data, boundary, <<body:bits, 13, 10>>) |
| 353 | - _, _ -> Error(Nil) |
| 508 | + <<_, _, _:size(boundary_bytes)-bytes, _, _, _:bits>> -> |
| 509 | + parse_body_loop(rest, boundary, boundary_bytes, <<body:bits, "\r\n">>) |
| 510 | + |
| 511 | + _ -> |
| 512 | + more_please_body(body, data, fn(data) { |
| 513 | + parse_body_loop(data, boundary, boundary_bytes, <<>>) |
| 514 | + }) |
| 354 515 | } |
| 355 | - } |
| 356 516 | |
| 357 | - <<char, data:bytes>> -> { |
| 358 | - parse_body_loop(data, boundary, <<body:bits, char>>) |
| 359 | - } |
| 517 | + <<char, data:bits>> -> |
| 518 | + parse_body_loop(data, boundary, boundary_bytes, <<body:bits, char>>) |
| 360 519 | |
| 361 520 | _ -> panic as "unreachable" |
| 362 521 | } |
| 363 522 | } |
| 364 523 | |
| 365 | - fn parse_headers_after_prelude( |
| 366 | - data: BitArray, |
| 367 | - boundary: BitArray, |
| 368 | - ) -> Result(MultipartHeaders, Nil) { |
| 369 | - let dsize = bit_array.byte_size(data) |
| 370 | - let bsize = bit_array.byte_size(boundary) |
| 371 | - let required_size = bsize + 4 |
| 372 | - |
| 373 | - // TODO: this could be written as a single case expression if JavaScript had |
| 374 | - // support for the `b:binary-size(bsize)` pattern. Rewrite this once the |
| 375 | - // compiler support this. |
| 376 | - |
| 377 | - use <- bool.guard( |
| 378 | - when: dsize < required_size, |
| 379 | - return: more_please_headers(parse_headers_after_prelude(_, boundary), data), |
| 380 | - ) |
| 381 | - |
| 382 | - use prefix <- result.try(bit_array.slice(data, 0, required_size - 2)) |
| 383 | - use second <- result.try(bit_array.slice(data, 2 + bsize, 2)) |
| 384 | - let desired = <<45, 45, boundary:bits>> |
| 385 | - |
| 386 | - use <- bool.guard(prefix != desired, return: Error(Nil)) |
| 387 | - |
| 388 | - case second == <<45, 45>> { |
| 389 | - // --boundary-- |
| 390 | - // The last boundary. Return the epilogue. |
| 391 | - True -> { |
| 392 | - let rest_size = dsize - required_size |
| 393 | - use data <- result.map(bit_array.slice(data, required_size, rest_size)) |
| 394 | - MultipartHeaders([], remaining: data) |
| 395 | - } |
| 396 | - |
| 397 | - // --boundary |
| 398 | - False -> { |
| 399 | - let start = required_size - 2 |
| 400 | - let rest_size = dsize - required_size + 2 |
| 401 | - use data <- result.try(bit_array.slice(data, start, rest_size)) |
| 402 | - do_parse_headers(data) |
| 403 | - } |
| 404 | - } |
| 405 | - } |
| 406 | - |
| 407 | - fn skip_preamble( |
| 408 | - data: BitArray, |
| 409 | - boundary: BitArray, |
| 410 | - ) -> Result(MultipartHeaders, Nil) { |
| 411 | - let data_size = bit_array.byte_size(data) |
| 412 | - let boundary_size = bit_array.byte_size(boundary) |
| 413 | - let required = boundary_size + 4 |
| 414 | - case data { |
| 415 | - _ if data_size < required -> |
| 416 | - more_please_headers(skip_preamble(_, boundary), data) |
| 417 | - |
| 418 | - // TODO: change this to use one non-nested case expression once the compiler |
| 419 | - // supports the `b:binary-size(bsize)` pattern on JS. |
| 420 | - // \r\n-- |
| 421 | - <<13, 10, 45, 45, data:bytes>> -> { |
| 422 | - case bit_array.slice(data, 0, boundary_size) { |
| 423 | - // --boundary |
| 424 | - Ok(prefix) if prefix == boundary -> { |
| 425 | - let start = boundary_size |
| 426 | - let length = bit_array.byte_size(data) - boundary_size |
| 427 | - use rest <- result.try(bit_array.slice(data, start, length)) |
| 428 | - do_parse_headers(rest) |
| 429 | - } |
| 430 | - Ok(_) -> skip_preamble(data, boundary) |
| 431 | - Error(_) -> Error(Nil) |
| 432 | - } |
| 433 | - } |
| 434 | - |
| 435 | - <<_, data:bytes>> -> skip_preamble(data, boundary) |
| 436 | - |
| 437 | - _ -> panic as "unreachable" |
| 438 | - } |
| 439 | - } |
| 440 | - |
| 441 | - fn skip_whitespace(data: BitArray) -> BitArray { |
| 442 | - case data { |
| 443 | - // Space or tab. |
| 444 | - <<32, data:bytes>> | <<9, data:bytes>> -> skip_whitespace(data) |
| 445 | - _ -> data |
| 446 | - } |
| 447 | - } |
| 448 | - |
| 449 | - fn do_parse_headers(data: BitArray) -> Result(MultipartHeaders, Nil) { |
| 450 | - case data { |
| 451 | - // \r\n\r\n |
| 452 | - // We've reached the end, there are no headers. |
| 453 | - <<13, 10, 13, 10, data:bytes>> -> Ok(MultipartHeaders([], remaining: data)) |
| 454 | - |
| 455 | - // \r\n |
| 456 | - // Skip the line break after the boundary. |
| 457 | - <<13, 10, data:bytes>> -> parse_header_name(data, [], <<>>) |
| 458 | - |
| 459 | - <<13>> | <<>> -> more_please_headers(do_parse_headers, data) |
| 460 | - |
| 461 | - _ -> Error(Nil) |
| 462 | - } |
| 463 | - } |
| 464 | - |
| 465 | - fn parse_header_name( |
| 466 | - data: BitArray, |
| 467 | - headers: List(Header), |
| 468 | - name: BitArray, |
| 469 | - ) -> Result(MultipartHeaders, Nil) { |
| 470 | - case skip_whitespace(data) { |
| 471 | - // : |
| 472 | - <<58, data:bytes>> -> |
| 473 | - data |
| 474 | - |> skip_whitespace |
| 475 | - |> parse_header_value(headers, name, <<>>) |
| 476 | - |
| 477 | - <<char, data:bytes>> -> |
| 478 | - parse_header_name(data, headers, <<name:bits, char>>) |
| 479 | - |
| 480 | - _ -> more_please_headers(parse_header_name(_, headers, name), data) |
| 481 | - } |
| 482 | - } |
| 483 | - |
| 484 | - fn parse_header_value( |
| 485 | - data: BitArray, |
| 486 | - headers: List(Header), |
| 487 | - name: BitArray, |
| 488 | - value: BitArray, |
| 489 | - ) -> Result(MultipartHeaders, Nil) { |
| 490 | - let size = bit_array.byte_size(data) |
| 491 | - case data { |
| 492 | - // We need at least 4 bytes to check for the end of the headers. |
| 493 | - _ if size < 4 -> |
| 494 | - fn(data) { |
| 495 | - data |
| 496 | - |> skip_whitespace |
| 497 | - |> parse_header_value(headers, name, value) |
| 498 | - } |
| 499 | - |> more_please_headers(data) |
| 500 | - |
| 501 | - // \r\n\r\n |
| 502 | - <<13, 10, 13, 10, data:bytes>> -> { |
| 503 | - use name <- result.try(bit_array.to_string(name)) |
| 504 | - use value <- result.map(bit_array.to_string(value)) |
| 505 | - let headers = list.reverse([#(string.lowercase(name), value), ..headers]) |
| 506 | - MultipartHeaders(headers, data) |
| 507 | - } |
| 508 | - |
| 509 | - // \r\n\s |
| 510 | - // \r\n\t |
| 511 | - <<13, 10, 32, data:bytes>> | <<13, 10, 9, data:bytes>> -> |
| 512 | - parse_header_value(data, headers, name, value) |
| 513 | - |
| 514 | - // \r\n |
| 515 | - <<13, 10, data:bytes>> -> { |
| 516 | - use name <- result.try(bit_array.to_string(name)) |
| 517 | - use value <- result.try(bit_array.to_string(value)) |
| 518 | - let headers = [#(string.lowercase(name), value), ..headers] |
| 519 | - parse_header_name(data, headers, <<>>) |
| 520 | - } |
| 521 | - |
| 522 | - <<char, rest:bytes>> -> { |
| 523 | - let value = <<value:bits, char>> |
| 524 | - parse_header_value(rest, headers, name, value) |
| 525 | - } |
| 526 | - |
| 527 | - _ -> Error(Nil) |
| 528 | - } |
| 529 | - } |
| 530 | - |
| 531 524 | fn more_please_headers( |
| 532 | - continuation: fn(BitArray) -> Result(MultipartHeaders, Nil), |
| 533 525 | existing: BitArray, |
| 526 | + continuation: fn(BitArray) -> Result(MultipartHeaders, Nil), |
| 534 527 | ) -> Result(MultipartHeaders, Nil) { |
| 535 528 | Ok( |
| 536 529 | MoreRequiredForHeaders(fn(more) { |
| @@ -540,6 +533,19 @@ fn more_please_headers( | |
| 540 533 | ) |
| 541 534 | } |
| 542 535 | |
| 536 | + fn more_please_body( |
| 537 | + chunk: BitArray, |
| 538 | + existing: BitArray, |
| 539 | + continuation: fn(BitArray) -> Result(MultipartBody, Nil), |
| 540 | + ) -> Result(MultipartBody, Nil) { |
| 541 | + Ok( |
| 542 | + MoreRequiredForBody(chunk, fn(more) { |
| 543 | + use <- bool.guard(more == <<>>, return: Error(Nil)) |
| 544 | + continuation(<<existing:bits, more:bits>>) |
| 545 | + }), |
| 546 | + ) |
| 547 | + } |
| 548 | + |
| 543 549 | pub type ContentDisposition { |
| 544 550 | ContentDisposition(String, parameters: List(#(String, String))) |
| 545 551 | } |
| @@ -644,19 +650,6 @@ fn parse_rfc_2045_parameter_unquoted_value( | |
| 644 650 | } |
| 645 651 | } |
| 646 652 | |
| 647 | - fn more_please_body( |
| 648 | - continuation: fn(BitArray) -> Result(MultipartBody, Nil), |
| 649 | - chunk: BitArray, |
| 650 | - existing: BitArray, |
| 651 | - ) -> Result(MultipartBody, Nil) { |
| 652 | - fn(more) { |
| 653 | - use <- bool.guard(more == <<>>, return: Error(Nil)) |
| 654 | - continuation(<<existing:bits, more:bits>>) |
| 655 | - } |
| 656 | - |> MoreRequiredForBody(chunk, _) |
| 657 | - |> Ok |
| 658 | - } |
| 659 | - |
| 660 653 | /// A HTTP header is a key-value pair. Header keys must be all lowercase |
| 661 654 | /// characters. |
| 662 655 | pub type Header = |
| @@ -1,7 +1,7 @@ | |
| 1 1 | -module(gleam@http). |
| 2 2 | -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). |
| 3 3 | -define(FILEPATH, "src/gleam/http.gleam"). |
| 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]). |
| 4 | + -export([parse_method/1, method_to_string/1, scheme_to_string/1, scheme_from_string/1, parse_multipart_body/2, parse_content_disposition/1, parse_multipart_headers/2]). |
| 5 5 | -export_type([method/0, scheme/0, multipart_headers/0, multipart_body/0, content_disposition/0]). |
| 6 6 | |
| 7 7 | -if(?OTP_RELEASE >= 27). |
| @@ -423,26 +423,12 @@ scheme_from_string(Scheme) -> | |
| 423 423 | {error, nil} |
| 424 424 | end. |
| 425 425 | |
| 426 | - -file("src/gleam/http.gleam", 441). |
| 427 | - -spec skip_whitespace(bitstring()) -> bitstring(). |
| 428 | - skip_whitespace(Data) -> |
| 429 | - case Data of |
| 430 | - <<32, Data@1/binary>> -> |
| 431 | - skip_whitespace(Data@1); |
| 432 | - |
| 433 | - <<9, Data@1/binary>> -> |
| 434 | - skip_whitespace(Data@1); |
| 435 | - |
| 436 | - _ -> |
| 437 | - Data |
| 438 | - end. |
| 439 | - |
| 440 | - -file("src/gleam/http.gleam", 531). |
| 426 | + -file("src/gleam/http.gleam", 524). |
| 441 427 | -spec more_please_headers( |
| 442 | - fun((bitstring()) -> {ok, multipart_headers()} | {error, nil}), |
| 443 | - bitstring() |
| 428 | + bitstring(), |
| 429 | + fun((bitstring()) -> {ok, multipart_headers()} | {error, nil}) |
| 444 430 | ) -> {ok, multipart_headers()} | {error, nil}. |
| 445 | - more_please_headers(Continuation, Existing) -> |
| 431 | + more_please_headers(Existing, Continuation) -> |
| 446 432 | {ok, |
| 447 433 | {more_required_for_headers, |
| 448 434 | fun(More) -> |
| @@ -455,7 +441,141 @@ more_please_headers(Continuation, Existing) -> | |
| 455 441 | ) |
| 456 442 | end}}. |
| 457 443 | |
| 458 | - -file("src/gleam/http.gleam", 612). |
| 444 | + -file("src/gleam/http.gleam", 536). |
| 445 | + -spec more_please_body( |
| 446 | + bitstring(), |
| 447 | + bitstring(), |
| 448 | + fun((bitstring()) -> {ok, multipart_body()} | {error, nil}) |
| 449 | + ) -> {ok, multipart_body()} | {error, nil}. |
| 450 | + more_please_body(Chunk, Existing, Continuation) -> |
| 451 | + {ok, |
| 452 | + {more_required_for_body, |
| 453 | + Chunk, |
| 454 | + fun(More) -> |
| 455 | + gleam@bool:guard( |
| 456 | + More =:= <<>>, |
| 457 | + {error, nil}, |
| 458 | + fun() -> |
| 459 | + Continuation(<<Existing/bitstring, More/bitstring>>) |
| 460 | + end |
| 461 | + ) |
| 462 | + end}}. |
| 463 | + |
| 464 | + -file("src/gleam/http.gleam", 475). |
| 465 | + -spec parse_body_loop(bitstring(), bitstring(), integer(), bitstring()) -> {ok, |
| 466 | + multipart_body()} | |
| 467 | + {error, nil}. |
| 468 | + parse_body_loop(Data, Boundary, Boundary_bytes, Body) -> |
| 469 | + case Data of |
| 470 | + <<>> -> |
| 471 | + more_please_body( |
| 472 | + Body, |
| 473 | + Data, |
| 474 | + fun(Data@1) -> |
| 475 | + parse_body_loop(Data@1, Boundary, Boundary_bytes, <<>>) |
| 476 | + end |
| 477 | + ); |
| 478 | + |
| 479 | + <<"\r"/utf8>> -> |
| 480 | + more_please_body( |
| 481 | + Body, |
| 482 | + Data, |
| 483 | + fun(Data@1) -> |
| 484 | + parse_body_loop(Data@1, Boundary, Boundary_bytes, <<>>) |
| 485 | + end |
| 486 | + ); |
| 487 | + |
| 488 | + <<"\r\n"/utf8, Rest/bitstring>> -> |
| 489 | + case Rest of |
| 490 | + <<"--"/utf8, |
| 491 | + Found:Boundary_bytes/binary, |
| 492 | + "\r"/utf8, |
| 493 | + "\n"/utf8, |
| 494 | + _/bitstring>> when Found =:= Boundary -> |
| 495 | + {ok, {multipart_body, Body, false, Rest}}; |
| 496 | + |
| 497 | + <<"--"/utf8, |
| 498 | + Found@1:Boundary_bytes/binary, |
| 499 | + "-"/utf8, |
| 500 | + "-"/utf8, |
| 501 | + Rest@1/bitstring>> when Found@1 =:= Boundary -> |
| 502 | + {ok, {multipart_body, Body, true, Rest@1}}; |
| 503 | + |
| 504 | + <<_, _, _:Boundary_bytes/binary, _, _, _/bitstring>> -> |
| 505 | + parse_body_loop( |
| 506 | + Rest, |
| 507 | + Boundary, |
| 508 | + Boundary_bytes, |
| 509 | + <<Body/bitstring, "\r\n"/utf8>> |
| 510 | + ); |
| 511 | + |
| 512 | + _ -> |
| 513 | + more_please_body( |
| 514 | + Body, |
| 515 | + Data, |
| 516 | + fun(Data@2) -> |
| 517 | + parse_body_loop( |
| 518 | + Data@2, |
| 519 | + Boundary, |
| 520 | + Boundary_bytes, |
| 521 | + <<>> |
| 522 | + ) |
| 523 | + end |
| 524 | + ) |
| 525 | + end; |
| 526 | + |
| 527 | + <<Char, Data@3/bitstring>> -> |
| 528 | + parse_body_loop( |
| 529 | + Data@3, |
| 530 | + Boundary, |
| 531 | + Boundary_bytes, |
| 532 | + <<Body/bitstring, Char>> |
| 533 | + ); |
| 534 | + |
| 535 | + _ -> |
| 536 | + erlang:error(#{gleam_error => panic, |
| 537 | + message => <<"unreachable"/utf8>>, |
| 538 | + file => <<?FILEPATH/utf8>>, |
| 539 | + module => <<"gleam/http"/utf8>>, |
| 540 | + function => <<"parse_body_loop"/utf8>>, |
| 541 | + line => 520}) |
| 542 | + end. |
| 543 | + |
| 544 | + -file("src/gleam/http.gleam", 463). |
| 545 | + -spec do_parse_multipart_body(bitstring(), bitstring(), integer()) -> {ok, |
| 546 | + multipart_body()} | |
| 547 | + {error, nil}. |
| 548 | + do_parse_multipart_body(Data, Boundary, Boundary_bytes) -> |
| 549 | + case Data of |
| 550 | + <<"--"/utf8, Found:Boundary_bytes/binary, _/binary>> when Found =:= Boundary -> |
| 551 | + {ok, {multipart_body, <<>>, false, Data}}; |
| 552 | + |
| 553 | + _ -> |
| 554 | + parse_body_loop(Data, Boundary, Boundary_bytes, <<>>) |
| 555 | + end. |
| 556 | + |
| 557 | + -file("src/gleam/http.gleam", 454). |
| 558 | + ?DOC( |
| 559 | + " Parse the body for part of a multipart message, as defined in RFC 2045. The\n" |
| 560 | + " body is everything until the next boundary. This function is generally to be\n" |
| 561 | + " called after calling `parse_multipart_headers` for a given part.\n" |
| 562 | + "\n" |
| 563 | + " This function will accept input of any size, it is up to the caller to limit\n" |
| 564 | + " it if needed.\n" |
| 565 | + "\n" |
| 566 | + " To enable streaming parsing of multipart messages, this function will return\n" |
| 567 | + " a continuation if there is not enough data to fully parse the body, along\n" |
| 568 | + " with the data that has been parsed so far. Further information is available\n" |
| 569 | + " in the documentation for `MultipartBody`.\n" |
| 570 | + ). |
| 571 | + -spec parse_multipart_body(bitstring(), binary()) -> {ok, multipart_body()} | |
| 572 | + {error, nil}. |
| 573 | + parse_multipart_body(Data, Boundary) -> |
| 574 | + Boundary@1 = gleam_stdlib:identity(Boundary), |
| 575 | + Boundary_bytes = erlang:byte_size(Boundary@1), |
| 576 | + do_parse_multipart_body(Data, Boundary@1, Boundary_bytes). |
| 577 | + |
| 578 | + -file("src/gleam/http.gleam", 618). |
| 459 579 | -spec parse_rfc_2045_parameter_quoted_value(binary(), binary(), binary()) -> {ok, |
| 460 580 | {{binary(), binary()}, binary()}} | |
| 461 581 | {error, nil}. |
| @@ -468,18 +588,17 @@ parse_rfc_2045_parameter_quoted_value(Header, Name, Value) -> | |
| 468 588 | {ok, {{Name, Value}, Rest}}; |
| 469 589 | |
| 470 590 | {ok, {<<"\\"/utf8>>, Rest@1}} -> |
| 471 | - case gleam_stdlib:string_pop_grapheme(Rest@1) of |
| 472 | - {ok, X} -> |
| 473 | - {Grapheme, Rest@2} = X, |
| 591 | + gleam@result:'try'( |
| 592 | + gleam_stdlib:string_pop_grapheme(Rest@1), |
| 593 | + fun(_use0) -> |
| 594 | + {Grapheme, Rest@2} = _use0, |
| 474 595 | parse_rfc_2045_parameter_quoted_value( |
| 475 596 | Rest@2, |
| 476 597 | Name, |
| 477 598 | <<Value/binary, Grapheme/binary>> |
| 478 | - ); |
| 479 | - |
| 480 | - {error, E} -> |
| 481 | - {error, E} |
| 482 | - end; |
| 599 | + ) |
| 600 | + end |
| 601 | + ); |
| 483 602 | |
| 484 603 | {ok, {Grapheme@1, Rest@3}} -> |
| 485 604 | parse_rfc_2045_parameter_quoted_value( |
| @@ -489,7 +608,7 @@ parse_rfc_2045_parameter_quoted_value(Header, Name, Value) -> | |
| 489 608 | ) |
| 490 609 | end. |
| 491 610 | |
| 492 | - -file("src/gleam/http.gleam", 629). |
| 611 | + -file("src/gleam/http.gleam", 635). |
| 493 612 | -spec parse_rfc_2045_parameter_unquoted_value(binary(), binary(), binary()) -> {{binary(), |
| 494 613 | binary()}, |
| 495 614 | binary()}. |
| @@ -515,7 +634,7 @@ parse_rfc_2045_parameter_unquoted_value(Header, Name, Value) -> | |
| 515 634 | ) |
| 516 635 | end. |
| 517 636 | |
| 518 | - -file("src/gleam/http.gleam", 600). |
| 637 | + -file("src/gleam/http.gleam", 606). |
| 519 638 | -spec parse_rfc_2045_parameter_value(binary(), binary()) -> {ok, |
| 520 639 | {{binary(), binary()}, binary()}} | |
| 521 640 | {error, nil}. |
| @@ -532,14 +651,15 @@ parse_rfc_2045_parameter_value(Header, Name) -> | |
| 532 651 | parse_rfc_2045_parameter_unquoted_value(Rest@1, Name, Grapheme)} |
| 533 652 | end. |
| 534 653 | |
| 535 | - -file("src/gleam/http.gleam", 589). |
| 654 | + -file("src/gleam/http.gleam", 595). |
| 536 655 | -spec parse_rfc_2045_parameter(binary(), binary()) -> {ok, |
| 537 656 | {{binary(), binary()}, binary()}} | |
| 538 657 | {error, nil}. |
| 539 658 | parse_rfc_2045_parameter(Header, Name) -> |
| 540 | - case gleam_stdlib:string_pop_grapheme(Header) of |
| 541 | - {ok, X} -> |
| 542 | - {Grapheme, Rest} = X, |
| 659 | + gleam@result:'try'( |
| 660 | + gleam_stdlib:string_pop_grapheme(Header), |
| 661 | + fun(_use0) -> |
| 662 | + {Grapheme, Rest} = _use0, |
| 543 663 | case Grapheme of |
| 544 664 | <<"="/utf8>> -> |
| 545 665 | parse_rfc_2045_parameter_value(Rest, Name); |
| @@ -549,13 +669,11 @@ parse_rfc_2045_parameter(Header, Name) -> | |
| 549 669 | Rest, |
| 550 670 | <<Name/binary, (string:lowercase(Grapheme))/binary>> |
| 551 671 | ) |
| 552 | - end; |
| 672 | + end |
| 673 | + end |
| 674 | + ). |
| 553 675 | |
| 554 | - {error, E} -> |
| 555 | - {error, E} |
| 556 | - end. |
| 557 | - |
| 558 | - -file("src/gleam/http.gleam", 571). |
| 676 | + -file("src/gleam/http.gleam", 577). |
| 559 677 | -spec parse_rfc_2045_parameters(binary(), list({binary(), binary()})) -> {ok, |
| 560 678 | list({binary(), binary()})} | |
| 561 679 | {error, nil}. |
| @@ -575,23 +693,16 @@ parse_rfc_2045_parameters(Header, Parameters) -> | |
| 575 693 | |
| 576 694 | {ok, {Grapheme, Rest@1}} -> |
| 577 695 | Acc = string:lowercase(Grapheme), |
| 578 | - begin |
| 579 | - Result = parse_rfc_2045_parameter(Rest@1, Acc), |
| 580 | - case Result of |
| 581 | - {ok, X} -> |
| 582 | - {Parameter, Rest@2} = X, |
| 583 | - parse_rfc_2045_parameters( |
| 584 | - Rest@2, |
| 585 | - [Parameter | Parameters] |
| 586 | - ); |
| 587 | - |
| 588 | - {error, E} -> |
| 589 | - {error, E} |
| 696 | + gleam@result:'try'( |
| 697 | + parse_rfc_2045_parameter(Rest@1, Acc), |
| 698 | + fun(_use0) -> |
| 699 | + {Parameter, Rest@2} = _use0, |
| 700 | + parse_rfc_2045_parameters(Rest@2, [Parameter | Parameters]) |
| 590 701 | end |
| 591 | - end |
| 702 | + ) |
| 592 703 | end. |
| 593 704 | |
| 594 | - -file("src/gleam/http.gleam", 553). |
| 705 | + -file("src/gleam/http.gleam", 559). |
| 595 706 | -spec parse_content_disposition_type(binary(), binary()) -> {ok, |
| 596 707 | content_disposition()} | |
| 597 708 | {error, nil}. |
| @@ -602,33 +713,24 @@ parse_content_disposition_type(Header, Name) -> | |
| 602 713 | |
| 603 714 | {ok, {<<" "/utf8>>, Rest}} -> |
| 604 715 | Result = parse_rfc_2045_parameters(Rest, []), |
| 605 | - case Result of |
| 606 | - {ok, X} -> |
| 607 | - {ok, {content_disposition, Name, X}}; |
| 608 | - |
| 609 | - {error, E} -> |
| 610 | - {error, E} |
| 611 | - end; |
| 716 | + gleam@result:map( |
| 717 | + Result, |
| 718 | + fun(Parameters) -> {content_disposition, Name, Parameters} end |
| 719 | + ); |
| 612 720 | |
| 613 721 | {ok, {<<"\t"/utf8>>, Rest}} -> |
| 614 722 | Result = parse_rfc_2045_parameters(Rest, []), |
| 615 | - case Result of |
| 616 | - {ok, X} -> |
| 617 | - {ok, {content_disposition, Name, X}}; |
| 618 | - |
| 619 | - {error, E} -> |
| 620 | - {error, E} |
| 621 | - end; |
| 723 | + gleam@result:map( |
| 724 | + Result, |
| 725 | + fun(Parameters) -> {content_disposition, Name, Parameters} end |
| 726 | + ); |
| 622 727 | |
| 623 728 | {ok, {<<";"/utf8>>, Rest}} -> |
| 624 729 | Result = parse_rfc_2045_parameters(Rest, []), |
| 625 | - case Result of |
| 626 | - {ok, X} -> |
| 627 | - {ok, {content_disposition, Name, X}}; |
| 628 | - |
| 629 | - {error, E} -> |
| 630 | - {error, E} |
| 631 | - end; |
| 730 | + gleam@result:map( |
| 731 | + Result, |
| 732 | + fun(Parameters) -> {content_disposition, Name, Parameters} end |
| 733 | + ); |
| 632 734 | |
| 633 735 | {ok, {Grapheme, Rest@1}} -> |
| 634 736 | parse_content_disposition_type( |
| @@ -637,340 +739,241 @@ parse_content_disposition_type(Header, Name) -> | |
| 637 739 | ) |
| 638 740 | end. |
| 639 741 | |
| 640 | - -file("src/gleam/http.gleam", 547). |
| 742 | + -file("src/gleam/http.gleam", 553). |
| 641 743 | -spec parse_content_disposition(binary()) -> {ok, content_disposition()} | |
| 642 744 | {error, nil}. |
| 643 745 | parse_content_disposition(Header) -> |
| 644 746 | parse_content_disposition_type(Header, <<""/utf8>>). |
| 645 747 | |
| 646 | - -file("src/gleam/http.gleam", 647). |
| 647 | - -spec more_please_body( |
| 648 | - fun((bitstring()) -> {ok, multipart_body()} | {error, nil}), |
| 649 | - bitstring(), |
| 650 | - bitstring() |
| 651 | - ) -> {ok, multipart_body()} | {error, nil}. |
| 652 | - more_please_body(Continuation, Chunk, Existing) -> |
| 653 | - _pipe = fun(More) -> |
| 654 | - gleam@bool:guard( |
| 655 | - More =:= <<>>, |
| 656 | - {error, nil}, |
| 657 | - fun() -> Continuation(<<Existing/bitstring, More/bitstring>>) end |
| 658 | - ) |
| 659 | - end, |
| 660 | - _pipe@1 = {more_required_for_body, Chunk, _pipe}, |
| 661 | - {ok, _pipe@1}. |
| 662 | - |
| 663 | - -file("src/gleam/http.gleam", 320). |
| 664 | - -spec parse_body_loop(bitstring(), bitstring(), bitstring()) -> {ok, |
| 665 | - multipart_body()} | |
| 666 | - {error, nil}. |
| 667 | - parse_body_loop(Data, Boundary, Body) -> |
| 668 | - Dsize = erlang:byte_size(Data), |
| 669 | - Bsize = erlang:byte_size(Boundary), |
| 670 | - Required = 6 + Bsize, |
| 671 | - case Data of |
| 672 | - _ when Dsize < Required -> |
| 673 | - more_please_body( |
| 674 | - fun(_capture) -> parse_body_loop(_capture, Boundary, <<>>) end, |
| 675 | - Body, |
| 676 | - Data |
| 677 | - ); |
| 678 | - |
| 679 | - <<13, 10, Data@1/binary>> -> |
| 680 | - Desired = <<45, 45, Boundary/bitstring>>, |
| 681 | - Size = erlang:byte_size(Desired), |
| 682 | - Dsize@1 = erlang:byte_size(Data@1), |
| 683 | - Prefix = gleam_stdlib:bit_array_slice(Data@1, 0, Size), |
| 684 | - Rest = gleam_stdlib:bit_array_slice(Data@1, Size, Dsize@1 - Size), |
| 685 | - case {Prefix =:= {ok, Desired}, Rest} of |
| 686 | - {true, {ok, <<13, 10, _/binary>>}} -> |
| 687 | - {ok, {multipart_body, Body, false, Data@1}}; |
| 688 | - |
| 689 | - {true, {ok, <<45, 45, Data@2/binary>>}} -> |
| 690 | - {ok, {multipart_body, Body, true, Data@2}}; |
| 691 | - |
| 692 | - {false, _} -> |
| 693 | - parse_body_loop( |
| 694 | - Data@1, |
| 695 | - Boundary, |
| 696 | - <<Body/bitstring, 13, 10>> |
| 697 | - ); |
| 698 | - |
| 699 | - {_, _} -> |
| 700 | - {error, nil} |
| 701 | - end; |
| 702 | - |
| 703 | - <<Char, Data@3/binary>> -> |
| 704 | - parse_body_loop(Data@3, Boundary, <<Body/bitstring, Char>>); |
| 705 | - |
| 706 | - _ -> |
| 707 | - erlang:error(#{gleam_error => panic, |
| 708 | - message => <<"unreachable"/utf8>>, |
| 709 | - file => <<?FILEPATH/utf8>>, |
| 710 | - module => <<"gleam/http"/utf8>>, |
| 711 | - function => <<"parse_body_loop"/utf8>>, |
| 712 | - line => 361}) |
| 713 | - end. |
| 714 | - |
| 715 | - -file("src/gleam/http.gleam", 308). |
| 716 | - -spec parse_body_with_bit_array(bitstring(), bitstring()) -> {ok, |
| 717 | - multipart_body()} | |
| 718 | - {error, nil}. |
| 719 | - parse_body_with_bit_array(Data, Boundary) -> |
| 720 | - Bsize = erlang:byte_size(Boundary), |
| 721 | - Prefix = gleam_stdlib:bit_array_slice(Data, 0, 2 + Bsize), |
| 722 | - case Prefix =:= {ok, <<45, 45, Boundary/bitstring>>} of |
| 723 | - true -> |
| 724 | - {ok, {multipart_body, <<>>, false, Data}}; |
| 725 | - |
| 726 | - false -> |
| 727 | - parse_body_loop(Data, Boundary, <<>>) |
| 728 | - end. |
| 729 | - |
| 730 | - -file("src/gleam/http.gleam", 299). |
| 731 | - ?DOC( |
| 732 | - " Parse the body for part of a multipart message, as defined in RFC 2045. The\n" |
| 733 | - " body is everything until the next boundary. This function is generally to be\n" |
| 734 | - " called after calling `parse_multipart_headers` for a given part.\n" |
| 735 | - "\n" |
| 736 | - " This function will accept input of any size, it is up to the caller to limit\n" |
| 737 | - " it if needed.\n" |
| 738 | - "\n" |
| 739 | - " To enable streaming parsing of multipart messages, this function will return\n" |
| 740 | - " a continuation if there is not enough data to fully parse the body, along\n" |
| 741 | - " with the data that has been parsed so far. Further information is available\n" |
| 742 | - " in the documentation for `MultipartBody`.\n" |
| 743 | - ). |
| 744 | - -spec parse_multipart_body(bitstring(), binary()) -> {ok, multipart_body()} | |
| 745 | - {error, nil}. |
| 746 | - parse_multipart_body(Data, Boundary) -> |
| 747 | - _pipe = Boundary, |
| 748 | - _pipe@1 = gleam_stdlib:identity(_pipe), |
| 749 | - parse_body_with_bit_array(Data, _pipe@1). |
| 750 | - |
| 751 | - -file("src/gleam/http.gleam", 484). |
| 752 | - -spec parse_header_value( |
| 748 | + -file("src/gleam/http.gleam", 407). |
| 749 | + -spec parse_header_value_loop( |
| 753 750 | bitstring(), |
| 754 751 | list({binary(), binary()}), |
| 755 | - bitstring(), |
| 752 | + binary(), |
| 756 753 | bitstring() |
| 757 754 | ) -> {ok, multipart_headers()} | {error, nil}. |
| 758 | - parse_header_value(Data, Headers, Name, Value) -> |
| 759 | - Size = erlang:byte_size(Data), |
| 755 | + parse_header_value_loop(Data, Headers, Name, Value) -> |
| 760 756 | case Data of |
| 761 | - _ when Size < 4 -> |
| 762 | - _pipe@2 = fun(Data@1) -> _pipe = Data@1, |
| 763 | - _pipe@1 = skip_whitespace(_pipe), |
| 764 | - parse_header_value(_pipe@1, Headers, Name, Value) end, |
| 765 | - more_please_headers(_pipe@2, Data); |
| 757 | + <<>> -> |
| 758 | + more_please_headers( |
| 759 | + Data, |
| 760 | + fun(Data@1) -> |
| 761 | + parse_header_value_loop(Data@1, Headers, Name, Value) |
| 762 | + end |
| 763 | + ); |
| 766 764 | |
| 767 | - <<13, 10, 13, 10, Data@2/binary>> -> |
| 768 | - case gleam@bit_array:to_string(Name) of |
| 769 | - {ok, X} -> |
| 770 | - Name@1 = X, |
| 771 | - case gleam@bit_array:to_string(Value) of |
| 772 | - {ok, X@1} -> |
| 773 | - {ok, |
| 774 | - begin |
| 775 | - Headers@1 = lists:reverse( |
| 776 | - [{string:lowercase(Name@1), X@1} | |
| 777 | - Headers] |
| 778 | - ), |
| 779 | - {multipart_headers, Headers@1, Data@2} |
| 780 | - end}; |
| 765 | + <<_>> -> |
| 766 | + more_please_headers( |
| 767 | + Data, |
| 768 | + fun(Data@1) -> |
| 769 | + parse_header_value_loop(Data@1, Headers, Name, Value) |
| 770 | + end |
| 771 | + ); |
| 781 772 | |
| 782 | - {error, E} -> |
| 783 | - {error, E} |
| 784 | - end; |
| 773 | + <<_, _>> -> |
| 774 | + more_please_headers( |
| 775 | + Data, |
| 776 | + fun(Data@1) -> |
| 777 | + parse_header_value_loop(Data@1, Headers, Name, Value) |
| 778 | + end |
| 779 | + ); |
| 785 780 | |
| 786 | - {error, E@1} -> |
| 787 | - {error, E@1} |
| 788 | - end; |
| 781 | + <<_, _, _>> -> |
| 782 | + more_please_headers( |
| 783 | + Data, |
| 784 | + fun(Data@1) -> |
| 785 | + parse_header_value_loop(Data@1, Headers, Name, Value) |
| 786 | + end |
| 787 | + ); |
| 789 788 | |
| 790 | - <<13, 10, 32, Data@3/binary>> -> |
| 791 | - parse_header_value(Data@3, Headers, Name, Value); |
| 789 | + <<"\r\n\r\n"/utf8, Data@2/binary>> -> |
| 790 | + gleam@result:map( |
| 791 | + gleam@bit_array:to_string(Value), |
| 792 | + fun(Value@1) -> |
| 793 | + Headers@1 = lists:reverse( |
| 794 | + [{string:lowercase(Name), Value@1} | Headers] |
| 795 | + ), |
| 796 | + {multipart_headers, Headers@1, Data@2} |
| 797 | + end |
| 798 | + ); |
| 792 799 | |
| 793 | - <<13, 10, 9, Data@3/binary>> -> |
| 794 | - parse_header_value(Data@3, Headers, Name, Value); |
| 800 | + <<"\r\n "/utf8, Data@3/binary>> -> |
| 801 | + parse_header_value_loop(Data@3, Headers, Name, Value); |
| 795 802 | |
| 796 | - <<13, 10, Data@4/binary>> -> |
| 797 | - case gleam@bit_array:to_string(Name) of |
| 798 | - {ok, X@2} -> |
| 799 | - Name@2 = X@2, |
| 800 | - case gleam@bit_array:to_string(Value) of |
| 801 | - {ok, X@3} -> |
| 802 | - Headers@2 = [{string:lowercase(Name@2), X@3} | |
| 803 | - Headers], |
| 804 | - parse_header_name(Data@4, Headers@2, <<>>); |
| 803 | + <<"\r\n\t"/utf8, Data@3/binary>> -> |
| 804 | + parse_header_value_loop(Data@3, Headers, Name, Value); |
| 805 805 | |
| 806 | - {error, E@2} -> |
| 807 | - {error, E@2} |
| 808 | - end; |
| 809 | - |
| 810 | - {error, E@3} -> |
| 811 | - {error, E@3} |
| 812 | - end; |
| 806 | + <<"\r\n"/utf8, Data@4/binary>> -> |
| 807 | + gleam@result:'try'( |
| 808 | + gleam@bit_array:to_string(Value), |
| 809 | + fun(Value@2) -> |
| 810 | + Headers@2 = [{string:lowercase(Name), Value@2} | Headers], |
| 811 | + parse_header_name(Data@4, Headers@2) |
| 812 | + end |
| 813 | + ); |
| 813 814 | |
| 814 815 | <<Char, Rest/binary>> -> |
| 815 | - Value@1 = <<Value/bitstring, Char>>, |
| 816 | - parse_header_value(Rest, Headers, Name, Value@1); |
| 816 | + parse_header_value_loop( |
| 817 | + Rest, |
| 818 | + Headers, |
| 819 | + Name, |
| 820 | + <<Value/bitstring, Char>> |
| 821 | + ); |
| 817 822 | |
| 818 823 | _ -> |
| 819 824 | {error, nil} |
| 820 825 | end. |
| 821 826 | |
| 822 | - -file("src/gleam/http.gleam", 465). |
| 823 | - -spec parse_header_name(bitstring(), list({binary(), binary()}), bitstring()) -> {ok, |
| 827 | + -file("src/gleam/http.gleam", 359). |
| 828 | + -spec parse_header_name(bitstring(), list({binary(), binary()})) -> {ok, |
| 824 829 | multipart_headers()} | |
| 825 830 | {error, nil}. |
| 826 | - parse_header_name(Data, Headers, Name) -> |
| 827 | - case skip_whitespace(Data) of |
| 828 | - <<58, Data@1/binary>> -> |
| 829 | - _pipe = Data@1, |
| 830 | - _pipe@1 = skip_whitespace(_pipe), |
| 831 | - parse_header_value(_pipe@1, Headers, Name, <<>>); |
| 831 | + parse_header_name(Data, Headers) -> |
| 832 | + case Data of |
| 833 | + <<" "/utf8, Rest/bitstring>> -> |
| 834 | + parse_header_name(Rest, Headers); |
| 832 835 | |
| 833 | - <<Char, Data@2/binary>> -> |
| 834 | - parse_header_name(Data@2, Headers, <<Name/bitstring, Char>>); |
| 836 | + <<"\t"/utf8, Rest/bitstring>> -> |
| 837 | + parse_header_name(Rest, Headers); |
| 838 | + |
| 839 | + <<_, _/bitstring>> -> |
| 840 | + parse_header_name_loop(Data, Headers, <<>>); |
| 835 841 | |
| 836 842 | _ -> |
| 837 843 | more_please_headers( |
| 838 | - fun(_capture) -> parse_header_name(_capture, Headers, Name) end, |
| 839 | - Data |
| 844 | + Data, |
| 845 | + fun(_capture) -> parse_header_name(_capture, Headers) end |
| 840 846 | ) |
| 841 847 | end. |
| 842 848 | |
| 843 | - -file("src/gleam/http.gleam", 449). |
| 849 | + -file("src/gleam/http.gleam", 374). |
| 850 | + -spec parse_header_name_loop( |
| 851 | + bitstring(), |
| 852 | + list({binary(), binary()}), |
| 853 | + bitstring() |
| 854 | + ) -> {ok, multipart_headers()} | {error, nil}. |
| 855 | + parse_header_name_loop(Data, Headers, Name) -> |
| 856 | + case Data of |
| 857 | + <<":"/utf8, Data@1/bitstring>> -> |
| 858 | + case gleam@bit_array:to_string(Name) of |
| 859 | + {ok, Name@1} -> |
| 860 | + parse_header_value(Data@1, Headers, Name@1); |
| 861 | + |
| 862 | + {error, nil} -> |
| 863 | + {error, nil} |
| 864 | + end; |
| 865 | + |
| 866 | + <<Char, Data@2/bitstring>> -> |
| 867 | + parse_header_name_loop(Data@2, Headers, <<Name/bitstring, Char>>); |
| 868 | + |
| 869 | + _ -> |
| 870 | + more_please_headers( |
| 871 | + Data, |
| 872 | + fun(_capture) -> |
| 873 | + parse_header_name_loop(_capture, Headers, Name) |
| 874 | + end |
| 875 | + ) |
| 876 | + end. |
| 877 | + |
| 878 | + -file("src/gleam/http.gleam", 393). |
| 879 | + -spec parse_header_value(bitstring(), list({binary(), binary()}), binary()) -> {ok, |
| 880 | + multipart_headers()} | |
| 881 | + {error, nil}. |
| 882 | + parse_header_value(Data, Headers, Name) -> |
| 883 | + case Data of |
| 884 | + <<" "/utf8, Rest/bitstring>> -> |
| 885 | + parse_header_value(Rest, Headers, Name); |
| 886 | + |
| 887 | + <<"\t"/utf8, Rest/bitstring>> -> |
| 888 | + parse_header_value(Rest, Headers, Name); |
| 889 | + |
| 890 | + <<_, _/bitstring>> -> |
| 891 | + parse_header_value_loop(Data, Headers, Name, <<>>); |
| 892 | + |
| 893 | + _ -> |
| 894 | + more_please_headers( |
| 895 | + Data, |
| 896 | + fun(_capture) -> parse_header_value(_capture, Headers, Name) end |
| 897 | + ) |
| 898 | + end. |
| 899 | + |
| 900 | + -file("src/gleam/http.gleam", 345). |
| 844 901 | -spec do_parse_headers(bitstring()) -> {ok, multipart_headers()} | {error, nil}. |
| 845 902 | do_parse_headers(Data) -> |
| 846 903 | case Data of |
| 847 | - <<13, 10, 13, 10, Data@1/binary>> -> |
| 904 | + <<"\r\n\r\n"/utf8, Data@1/binary>> -> |
| 848 905 | {ok, {multipart_headers, [], Data@1}}; |
| 849 906 | |
| 850 | - <<13, 10, Data@2/binary>> -> |
| 851 | - parse_header_name(Data@2, [], <<>>); |
| 907 | + <<"\r\n"/utf8, Data@2/binary>> -> |
| 908 | + parse_header_name(Data@2, []); |
| 852 909 | |
| 853 | - <<13>> -> |
| 854 | - more_please_headers(fun do_parse_headers/1, Data); |
| 910 | + <<"\r"/utf8>> -> |
| 911 | + more_please_headers(Data, fun do_parse_headers/1); |
| 855 912 | |
| 856 913 | <<>> -> |
| 857 | - more_please_headers(fun do_parse_headers/1, Data); |
| 914 | + more_please_headers(Data, fun do_parse_headers/1); |
| 858 915 | |
| 859 916 | _ -> |
| 860 917 | {error, nil} |
| 861 918 | end. |
| 862 919 | |
| 863 | - -file("src/gleam/http.gleam", 365). |
| 864 | - -spec parse_headers_after_prelude(bitstring(), bitstring()) -> {ok, |
| 920 | + -file("src/gleam/http.gleam", 307). |
| 921 | + -spec skip_preamble(bitstring(), bitstring(), integer()) -> {ok, |
| 865 922 | multipart_headers()} | |
| 866 923 | {error, nil}. |
| 867 | - parse_headers_after_prelude(Data, Boundary) -> |
| 868 | - Dsize = erlang:byte_size(Data), |
| 869 | - Bsize = erlang:byte_size(Boundary), |
| 870 | - Required_size = Bsize + 4, |
| 871 | - case Dsize < Required_size of |
| 872 | - true -> |
| 873 | - more_please_headers( |
| 874 | - fun(_capture) -> |
| 875 | - parse_headers_after_prelude(_capture, Boundary) |
| 876 | - end, |
| 877 | - Data |
| 878 | - ); |
| 879 | - |
| 880 | - false -> |
| 881 | - case gleam_stdlib:bit_array_slice(Data, 0, Required_size - 2) of |
| 882 | - {ok, X} -> |
| 883 | - Prefix = X, |
| 884 | - case gleam_stdlib:bit_array_slice(Data, 2 + Bsize, 2) of |
| 885 | - {ok, X@1} -> |
| 886 | - Second = X@1, |
| 887 | - Desired = <<45, 45, Boundary/bitstring>>, |
| 888 | - case Prefix /= Desired of |
| 889 | - true -> |
| 890 | - {error, nil}; |
| 891 | - |
| 892 | - false -> |
| 893 | - case Second =:= <<45, 45>> of |
| 894 | - true -> |
| 895 | - Rest_size = Dsize - Required_size, |
| 896 | - case gleam_stdlib:bit_array_slice( |
| 897 | - Data, |
| 898 | - Required_size, |
| 899 | - Rest_size |
| 900 | - ) of |
| 901 | - {ok, X@2} -> |
| 902 | - {ok, |
| 903 | - {multipart_headers, |
| 904 | - [], |
| 905 | - X@2}}; |
| 906 | - |
| 907 | - {error, E} -> |
| 908 | - {error, E} |
| 909 | - end; |
| 910 | - |
| 911 | - false -> |
| 912 | - Start = Required_size - 2, |
| 913 | - Rest_size@1 = (Dsize - Required_size) |
| 914 | - + 2, |
| 915 | - case gleam_stdlib:bit_array_slice( |
| 916 | - Data, |
| 917 | - Start, |
| 918 | - Rest_size@1 |
| 919 | - ) of |
| 920 | - {ok, X@3} -> |
| 921 | - do_parse_headers(X@3); |
| 922 | - |
| 923 | - {error, E@1} -> |
| 924 | - {error, E@1} |
| 925 | - end |
| 926 | - end |
| 927 | - end; |
| 928 | - |
| 929 | - {error, E@2} -> |
| 930 | - {error, E@2} |
| 931 | - end; |
| 932 | - |
| 933 | - {error, E@3} -> |
| 934 | - {error, E@3} |
| 935 | - end |
| 936 | - end. |
| 937 | - |
| 938 | - -file("src/gleam/http.gleam", 407). |
| 939 | - -spec skip_preamble(bitstring(), bitstring()) -> {ok, multipart_headers()} | |
| 940 | - {error, nil}. |
| 941 | - skip_preamble(Data, Boundary) -> |
| 942 | - Data_size = erlang:byte_size(Data), |
| 943 | - Boundary_size = erlang:byte_size(Boundary), |
| 944 | - Required = Boundary_size + 4, |
| 924 | + skip_preamble(Data, Boundary, Boundary_bytes) -> |
| 945 925 | case Data of |
| 946 | - _ when Data_size < Required -> |
| 947 | - more_please_headers( |
| 948 | - fun(_capture) -> skip_preamble(_capture, Boundary) end, |
| 949 | - Data |
| 950 | - ); |
| 926 | + <<"\r\n--"/utf8, Rest/binary>> -> |
| 927 | + case Rest of |
| 928 | + <<Found:Boundary_bytes/binary, Rest@1/bitstring>> when Found =:= Boundary -> |
| 929 | + do_parse_headers(Rest@1); |
| 951 930 | |
| 952 | - <<13, 10, 45, 45, Data@1/binary>> -> |
| 953 | - case gleam_stdlib:bit_array_slice(Data@1, 0, Boundary_size) of |
| 954 | - {ok, Prefix} when Prefix =:= Boundary -> |
| 955 | - Start = Boundary_size, |
| 956 | - Length = erlang:byte_size(Data@1) - Boundary_size, |
| 957 | - case gleam_stdlib:bit_array_slice(Data@1, Start, Length) of |
| 958 | - {ok, X} -> |
| 959 | - do_parse_headers(X); |
| 931 | + <<_:Boundary_bytes/binary, _/bitstring>> -> |
| 932 | + skip_preamble(Rest, Boundary, Boundary_bytes); |
| 960 933 | |
| 961 | - {error, E} -> |
| 962 | - {error, E} |
| 963 | - end; |
| 964 | - |
| 965 | - {ok, _} -> |
| 966 | - skip_preamble(Data@1, Boundary); |
| 967 | - |
| 968 | - {error, _} -> |
| 969 | - {error, nil} |
| 934 | + _ -> |
| 935 | + more_please_headers( |
| 936 | + Data, |
| 937 | + fun(_capture) -> |
| 938 | + skip_preamble(_capture, Boundary, Boundary_bytes) |
| 939 | + end |
| 940 | + ) |
| 970 941 | end; |
| 971 942 | |
| 972 | - <<_, Data@2/binary>> -> |
| 973 | - skip_preamble(Data@2, Boundary); |
| 943 | + <<>> -> |
| 944 | + more_please_headers( |
| 945 | + Data, |
| 946 | + fun(_capture@1) -> |
| 947 | + skip_preamble(_capture@1, Boundary, Boundary_bytes) |
| 948 | + end |
| 949 | + ); |
| 950 | + |
| 951 | + <<"\r"/utf8>> -> |
| 952 | + more_please_headers( |
| 953 | + Data, |
| 954 | + fun(_capture@1) -> |
| 955 | + skip_preamble(_capture@1, Boundary, Boundary_bytes) |
| 956 | + end |
| 957 | + ); |
| 958 | + |
| 959 | + <<"\r\n"/utf8>> -> |
| 960 | + more_please_headers( |
| 961 | + Data, |
| 962 | + fun(_capture@1) -> |
| 963 | + skip_preamble(_capture@1, Boundary, Boundary_bytes) |
| 964 | + end |
| 965 | + ); |
| 966 | + |
| 967 | + <<"\r\n-"/utf8>> -> |
| 968 | + more_please_headers( |
| 969 | + Data, |
| 970 | + fun(_capture@1) -> |
| 971 | + skip_preamble(_capture@1, Boundary, Boundary_bytes) |
| 972 | + end |
| 973 | + ); |
| 974 | + |
| 975 | + <<_, Data@1/binary>> -> |
| 976 | + skip_preamble(Data@1, Boundary, Boundary_bytes); |
| 974 977 | |
| 975 978 | _ -> |
| 976 979 | erlang:error(#{gleam_error => panic, |
| @@ -978,7 +981,38 @@ skip_preamble(Data, Boundary) -> | |
| 978 981 | file => <<?FILEPATH/utf8>>, |
| 979 982 | module => <<"gleam/http"/utf8>>, |
| 980 983 | function => <<"skip_preamble"/utf8>>, |
| 981 | - line => 437}) |
| 984 | + line => 341}) |
| 985 | + end. |
| 986 | + |
| 987 | + -file("src/gleam/http.gleam", 280). |
| 988 | + -spec do_parse_multipart_headers(bitstring(), bitstring(), integer()) -> {ok, |
| 989 | + multipart_headers()} | |
| 990 | + {error, nil}. |
| 991 | + do_parse_multipart_headers(Data, Boundary, Boundary_bytes) -> |
| 992 | + case Data of |
| 993 | + <<"--"/utf8, Found:Boundary_bytes/binary, Rest/bitstring>> when Found =:= Boundary -> |
| 994 | + case Rest of |
| 995 | + <<"--"/utf8, Rest@1/bitstring>> -> |
| 996 | + {ok, {multipart_headers, [], Rest@1}}; |
| 997 | + |
| 998 | + <<_, _, _/bitstring>> -> |
| 999 | + do_parse_headers(Rest); |
| 1000 | + |
| 1001 | + _ -> |
| 1002 | + more_please_headers( |
| 1003 | + Data, |
| 1004 | + fun(Data@1) -> |
| 1005 | + do_parse_multipart_headers( |
| 1006 | + Data@1, |
| 1007 | + Boundary, |
| 1008 | + Boundary_bytes |
| 1009 | + ) |
| 1010 | + end |
| 1011 | + ) |
| 1012 | + end; |
| 1013 | + |
| 1014 | + _ -> |
| 1015 | + skip_preamble(Data, Boundary, Boundary_bytes) |
| 982 1016 | end. |
| 983 1017 | |
| 984 1018 | -file("src/gleam/http.gleam", 271). |
| @@ -1000,12 +1034,5 @@ skip_preamble(Data, Boundary) -> | |
| 1000 1034 | {error, nil}. |
| 1001 1035 | parse_multipart_headers(Data, Boundary) -> |
| 1002 1036 | Boundary@1 = gleam_stdlib:identity(Boundary), |
| 1003 | - Prefix = <<45, 45, Boundary@1/bitstring>>, |
| 1004 | - case gleam_stdlib:bit_array_slice(Data, 0, erlang:byte_size(Prefix)) =:= {ok, |
| 1005 | - Prefix} of |
| 1006 | - true -> |
| 1007 | - parse_headers_after_prelude(Data, Boundary@1); |
| 1008 | - |
| 1009 | - false -> |
| 1010 | - skip_preamble(Data, Boundary@1) |
| 1011 | - end. |
| 1037 | + Boundary_bytes = erlang:byte_size(Boundary@1), |
| 1038 | + do_parse_multipart_headers(Data, Boundary@1, Boundary_bytes). |
| @@ -12,10 +12,10 @@ | |
| 12 12 | -define(DOC(Str), -compile([])). |
| 13 13 | -endif. |
| 14 14 | |
| 15 | - -type request(EHR) :: {request, |
| 15 | + -type request(ECH) :: {request, |
| 16 16 | gleam@http:method(), |
| 17 17 | list({binary(), binary()}), |
| 18 | - EHR, |
| 18 | + ECH, |
| 19 19 | gleam@http:scheme(), |
| 20 20 | binary(), |
| 21 21 | gleam@option:option(integer()), |
| @@ -39,36 +39,33 @@ to_uri(Request) -> | |
| 39 39 | ?DOC(" Construct a request from a URI.\n"). |
| 40 40 | -spec from_uri(gleam@uri:uri()) -> {ok, request(binary())} | {error, nil}. |
| 41 41 | from_uri(Uri) -> |
| 42 | - case begin |
| 43 | - _pipe = erlang:element(2, Uri), |
| 44 | - _pipe@1 = gleam@option:unwrap(_pipe, <<""/utf8>>), |
| 45 | - gleam@http:scheme_from_string(_pipe@1) |
| 46 | - end of |
| 47 | - {ok, X} -> |
| 48 | - Scheme = X, |
| 49 | - case begin |
| 50 | - _pipe@2 = erlang:element(4, Uri), |
| 51 | - gleam@option:to_result(_pipe@2, nil) |
| 52 | - end of |
| 53 | - {ok, X@1} -> |
| 42 | + gleam@result:'try'( |
| 43 | + begin |
| 44 | + _pipe = erlang:element(2, Uri), |
| 45 | + _pipe@1 = gleam@option:unwrap(_pipe, <<""/utf8>>), |
| 46 | + gleam@http:scheme_from_string(_pipe@1) |
| 47 | + end, |
| 48 | + fun(Scheme) -> |
| 49 | + gleam@result:'try'( |
| 50 | + begin |
| 51 | + _pipe@2 = erlang:element(4, Uri), |
| 52 | + gleam@option:to_result(_pipe@2, nil) |
| 53 | + end, |
| 54 | + fun(Host) -> |
| 54 55 | Req = {request, |
| 55 56 | get, |
| 56 57 | [], |
| 57 58 | <<""/utf8>>, |
| 58 59 | Scheme, |
| 59 | - X@1, |
| 60 | + Host, |
| 60 61 | erlang:element(5, Uri), |
| 61 62 | erlang:element(6, Uri), |
| 62 63 | erlang:element(7, Uri)}, |
| 63 | - {ok, Req}; |
| 64 | - |
| 65 | - {error, E} -> |
| 66 | - {error, E} |
| 67 | - end; |
| 68 | - |
| 69 | - {error, E@1} -> |
| 70 | - {error, E@1} |
| 71 | - end. |
| 64 | + {ok, Req} |
| 65 | + end |
| 66 | + ) |
| 67 | + end |
| 68 | + ). |
| 72 69 | |
| 73 70 | -file("src/gleam/http/request.gleam", 75). |
| 74 71 | ?DOC( |
| @@ -92,7 +89,7 @@ get_header(Request, Key) -> | |
| 92 89 | " Header keys are always lowercase in `gleam_http`. To use any uppercase\n" |
| 93 90 | " letter is invalid.\n" |
| 94 91 | ). |
| 95 | - -spec set_header(request(EIB), binary(), binary()) -> request(EIB). |
| 92 | + -spec set_header(request(ECR), binary(), binary()) -> request(ECR). |
| 96 93 | set_header(Request, Key, Value) -> |
| 97 94 | Headers = gleam@list:key_set( |
| 98 95 | erlang:element(3, Request), |
| @@ -119,7 +116,7 @@ set_header(Request, Key, Value) -> | |
| 119 116 | " Header keys are always lowercase in `gleam_http`. To use any uppercase\n" |
| 120 117 | " letter is invalid.\n" |
| 121 118 | ). |
| 122 | - -spec prepend_header(request(EIE), binary(), binary()) -> request(EIE). |
| 119 | + -spec prepend_header(request(ECU), binary(), binary()) -> request(ECU). |
| 123 120 | prepend_header(Request, Key, Value) -> |
| 124 121 | Headers = [{string:lowercase(Key), Value} | erlang:element(3, Request)], |
| 125 122 | {request, |
| @@ -134,7 +131,7 @@ prepend_header(Request, Key, Value) -> | |
| 134 131 | |
| 135 132 | -file("src/gleam/http/request.gleam", 114). |
| 136 133 | ?DOC(" Set the body of the request, overwriting any existing body.\n"). |
| 137 | - -spec set_body(request(any()), EIJ) -> request(EIJ). |
| 134 | + -spec set_body(request(any()), ECZ) -> request(ECZ). |
| 138 135 | set_body(Req, Body) -> |
| 139 136 | {request, |
| 140 137 | erlang:element(2, Req), |
| @@ -148,7 +145,7 @@ set_body(Req, Body) -> | |
| 148 145 | |
| 149 146 | -file("src/gleam/http/request.gleam", 120). |
| 150 147 | ?DOC(" Update the body of a request using a given function.\n"). |
| 151 | - -spec map(request(EIL), fun((EIL) -> EIN)) -> request(EIN). |
| 148 | + -spec map(request(EDB), fun((EDB) -> EDD)) -> request(EDD). |
| 152 149 | map(Request, Transform) -> |
| 153 150 | _pipe = erlang:element(4, Request), |
| 154 151 | _pipe@1 = Transform(_pipe), |
| @@ -190,7 +187,7 @@ get_query(Request) -> | |
| 190 187 | " Set the query of the request.\n" |
| 191 188 | " Query params will be percent encoded before being added to the Request.\n" |
| 192 189 | ). |
| 193 | - -spec set_query(request(EIX), list({binary(), binary()})) -> request(EIX). |
| 190 | + -spec set_query(request(EDN), list({binary(), binary()})) -> request(EDN). |
| 194 191 | set_query(Req, Query) -> |
| 195 192 | Query@1 = begin |
| 196 193 | _pipe = gleam@list:map( |
| @@ -216,7 +213,7 @@ set_query(Req, Query) -> | |
| 216 213 | |
| 217 214 | -file("src/gleam/http/request.gleam", 173). |
| 218 215 | ?DOC(" Set the method of the request.\n"). |
| 219 | - -spec set_method(request(EJB), gleam@http:method()) -> request(EJB). |
| 216 | + -spec set_method(request(EDR), gleam@http:method()) -> request(EDR). |
| 220 217 | set_method(Req, Method) -> |
| 221 218 | {request, |
| 222 219 | Method, |
| @@ -251,17 +248,11 @@ new() -> | |
| 251 248 | to(Url) -> |
| 252 249 | _pipe = Url, |
| 253 250 | _pipe@1 = gleam_stdlib:uri_parse(_pipe), |
| 254 | - case _pipe@1 of |
| 255 | - {ok, X} -> |
| 256 | - from_uri(X); |
| 257 | - |
| 258 | - {error, E} -> |
| 259 | - {error, E} |
| 260 | - end. |
| 251 | + gleam@result:'try'(_pipe@1, fun from_uri/1). |
| 261 252 | |
| 262 253 | -file("src/gleam/http/request.gleam", 203). |
| 263 254 | ?DOC(" Set the scheme (protocol) of the request.\n"). |
| 264 | - -spec set_scheme(request(EJI), gleam@http:scheme()) -> request(EJI). |
| 255 | + -spec set_scheme(request(EDY), gleam@http:scheme()) -> request(EDY). |
| 265 256 | set_scheme(Req, Scheme) -> |
| 266 257 | {request, |
| 267 258 | erlang:element(2, Req), |
| @@ -275,7 +266,7 @@ set_scheme(Req, Scheme) -> | |
| 275 266 | |
| 276 267 | -file("src/gleam/http/request.gleam", 209). |
| 277 268 | ?DOC(" Set the host of the request.\n"). |
| 278 | - -spec set_host(request(EJL), binary()) -> request(EJL). |
| 269 | + -spec set_host(request(EEB), binary()) -> request(EEB). |
| 279 270 | set_host(Req, Host) -> |
| 280 271 | {request, |
| 281 272 | erlang:element(2, Req), |
| @@ -289,7 +280,7 @@ set_host(Req, Host) -> | |
| 289 280 | |
| 290 281 | -file("src/gleam/http/request.gleam", 215). |
| 291 282 | ?DOC(" Set the port of the request.\n"). |
| 292 | - -spec set_port(request(EJO), integer()) -> request(EJO). |
| 283 | + -spec set_port(request(EEE), integer()) -> request(EEE). |
| 293 284 | set_port(Req, Port) -> |
| 294 285 | {request, |
| 295 286 | erlang:element(2, Req), |
| @@ -303,7 +294,7 @@ set_port(Req, Port) -> | |
| 303 294 | |
| 304 295 | -file("src/gleam/http/request.gleam", 221). |
| 305 296 | ?DOC(" Set the path of the request.\n"). |
| 306 | - -spec set_path(request(EJR), binary()) -> request(EJR). |
| 297 | + -spec set_path(request(EEH), binary()) -> request(EEH). |
| 307 298 | set_path(Req, Path) -> |
| 308 299 | {request, |
| 309 300 | erlang:element(2, Req), |
| @@ -324,7 +315,7 @@ set_path(Req, Path) -> | |
| 324 315 | " function cannot guarentee that previous cookies with the same name are\n" |
| 325 316 | " replaced.\n" |
| 326 317 | ). |
| 327 | - -spec set_cookie(request(EJU), binary(), binary()) -> request(EJU). |
| 318 | + -spec set_cookie(request(EEK), binary(), binary()) -> request(EEK). |
| 328 319 | set_cookie(Req, Name, Value) -> |
| 329 320 | {Cookies, Headers} = begin |
| 330 321 | _pipe = gleam@list:key_pop(erlang:element(3, Req), <<"cookie"/utf8>>), |
| @@ -377,7 +368,7 @@ get_cookies(Req) -> | |
| 377 368 | " Remove a cookie from the request. If no cookie is found return the request\n" |
| 378 369 | " unchanged. This will not remove the cookie from the client.\n" |
| 379 370 | ). |
| 380 | - -spec remove_cookie(request(EKA), binary()) -> request(EKA). |
| 371 | + -spec remove_cookie(request(EEQ), binary()) -> request(EEQ). |
| 381 372 | remove_cookie(Req, Name) -> |
| 382 373 | case gleam@list:key_pop(erlang:element(3, Req), <<"cookie"/utf8>>) of |
| 383 374 | {ok, {Cookies_string, Headers}} -> |
Loading more files…