diff --git a/gleam.toml b/gleam.toml index 4321100..a8c5d97 100644 --- a/gleam.toml +++ b/gleam.toml @@ -21,6 +21,7 @@ logging = ">= 1.2.0 and < 2.0.0" directories = ">= 1.0.0 and < 2.0.0" houdini = ">= 1.0.0 and < 2.0.0" filepath = ">= 1.1.2 and < 2.0.0" +gleam_yielder = ">= 1.1.0 and < 2.0.0" [dev-dependencies] gleeunit = ">= 1.0.0 and < 2.0.0" diff --git a/manifest.toml b/manifest.toml index 93a7183..40e96da 100644 --- a/manifest.toml +++ b/manifest.toml @@ -8,10 +8,10 @@ packages = [ { name = "filepath", version = "1.1.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "filepath", source = "hex", outer_checksum = "B06A9AF0BF10E51401D64B98E4B627F1D2E48C154967DA7AF4D0914780A6D40A" }, { name = "gleam_crypto", version = "1.5.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_crypto", source = "hex", outer_checksum = "50774BAFFF1144E7872814C566C5D653D83A3EBF23ACC3156B757A1B6819086E" }, { name = "gleam_erlang", version = "1.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_erlang", source = "hex", outer_checksum = "1124AD3AA21143E5AF0FC5CF3D9529F6DB8CA03E43A55711B60B6B7B3874375C" }, - { name = "gleam_http", version = "4.2.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_http", source = "hex", outer_checksum = "FFE29C3832698AC3EF6202922EC534EE19540152D01A7C2D22CB97482E4AF211" }, + { name = "gleam_http", version = "4.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_http", source = "hex", outer_checksum = "82EA6A717C842456188C190AFB372665EA56CE13D8559BF3B1DD9E40F619EE0C" }, { name = "gleam_json", version = "3.0.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_json", source = "hex", outer_checksum = "874FA3C3BB6E22DD2BB111966BD40B3759E9094E05257899A7C08F5DE77EC049" }, { name = "gleam_otp", version = "1.1.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_stdlib"], otp_app = "gleam_otp", source = "hex", outer_checksum = "7987CBEBC8060B88F14575DEF546253F3116EBE2A5DA6FD82F38243FCE97C54B" }, - { name = "gleam_stdlib", version = "0.64.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "EA2E13FC4E65750643E078487D5EF360BEBCA5EBBBA12042FB589C19F53E35C0" }, + { name = "gleam_stdlib", version = "0.65.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "7C69C71D8C493AE11A5184828A77110EB05A7786EBF8B25B36A72F879C3EE107" }, { name = "gleam_yielder", version = "1.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_yielder", source = "hex", outer_checksum = "8E4E4ECFA7982859F430C57F549200C7749823C106759F4A19A78AEA6687717A" }, { name = "gleeunit", version = "1.6.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "FDC68A8C492B1E9B429249062CD9BAC9B5538C6FBF584817205D0998C42E1DAC" }, { name = "glisten", version = "8.0.1", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_otp", "gleam_stdlib", "logging", "telemetry"], otp_app = "glisten", source = "hex", outer_checksum = "534BB27C71FB9E506345A767C0D76B17A9E9199934340C975DC003C710E3692D" }, @@ -35,6 +35,7 @@ gleam_erlang = { version = ">= 1.0.0 and < 2.0.0" } gleam_http = { version = ">= 3.5.0 and < 5.0.0" } gleam_json = { version = ">= 3.0.0 and < 4.0.0" } gleam_stdlib = { version = ">= 0.50.0 and < 2.0.0" } +gleam_yielder = { version = ">= 1.1.0 and < 2.0.0" } gleeunit = { version = ">= 1.0.0 and < 2.0.0" } houdini = { version = ">= 1.0.0 and < 2.0.0" } logging = { version = ">= 1.2.0 and < 2.0.0" } diff --git a/src/wisp.gleam b/src/wisp.gleam index 2aeffcc..0a90a2c 100644 --- a/src/wisp.gleam +++ b/src/wisp.gleam @@ -23,6 +23,7 @@ import gleam/result import gleam/string import gleam/string_tree.{type StringTree} import gleam/uri +import gleam/yielder.{type Yielder} import houdini import logging import marceau @@ -52,6 +53,15 @@ pub type Body { /// function to convert it. /// Bytes(BytesTree) + /// A body of binary chunked data, stored as a `Yielder(BytesTree)`. + /// + /// If you have a `BitArray` you can use the `bytes_tree.from_bit_array` + /// function to convert it. + /// + /// If you have a `StringTree` you can use the `bytes_tree.from_string_tree` + /// function to convert it. + /// + Chunks(Yielder(BytesTree)) /// A body of the contents of a file. /// /// This will be sent efficiently using the `send_file` function of the diff --git a/src/wisp/simulate.gleam b/src/wisp/simulate.gleam index fc790cd..0a4cdcb 100644 --- a/src/wisp/simulate.gleam +++ b/src/wisp/simulate.gleam @@ -8,9 +8,11 @@ import gleam/list import gleam/option.{None, Some} import gleam/result import gleam/string +import gleam/string_tree import gleam/uri +import gleam/yielder import simplifile -import wisp.{type Request, type Response, Bytes, File, Text} +import wisp.{type Request, type Response, Bytes, Chunks, File, Text} /// Create a test request that can be used to test your request handler /// functions. @@ -279,6 +281,14 @@ pub fn read_body(response: Response) -> String { as "the body file range was not valid UTF-8" string } + Chunks(yield) -> { + yielder.fold(yield, "", fn(acc, chunk) { + let assert Ok(string) = + bytes_tree.to_bit_array(chunk) |> bit_array.to_string + as "the response body was non-UTF8 binary data" + acc <> string + }) + } } } @@ -306,6 +316,12 @@ pub fn read_body_bits(response: Response) -> BitArray { as "the body was a file, but the limit and offset were invalid" sliced } + Chunks(yield) -> { + yielder.fold(yield, bit_array.from_string(""), fn(acc, chunk) { + let data = bytes_tree.to_bit_array(chunk) + bit_array.append(acc, data) + }) + } } } diff --git a/src/wisp/wisp_mist.gleam b/src/wisp/wisp_mist.gleam index 5e80dec..0b44597 100644 --- a/src/wisp/wisp_mist.gleam +++ b/src/wisp/wisp_mist.gleam @@ -84,6 +84,7 @@ fn mist_response(response: wisp.Response) -> HttpResponse(mist.ResponseData) { wisp.Text(text) -> mist.Bytes(bytes_tree.from_string(text)) wisp.Bytes(bytes) -> mist.Bytes(bytes) wisp.File(path:, offset:, limit:) -> mist_send_file(path, offset, limit) + wisp.Chunks(yield) -> mist.Chunked(yield) } response |> response.set_body(body)