diff --git a/examples/gleam.toml b/examples/gleam.toml index d2aa8a2..7940a24 100644 --- a/examples/gleam.toml +++ b/examples/gleam.toml @@ -4,6 +4,7 @@ description = "A collection of Wisp examples" [dependencies] wisp = { path = ".." } +wisp_mist = { path = "../wisp_mist" } mist = ">= 5.0.0 and < 6.0.0" gleam_stdlib = ">= 0.60.0 and < 1.0.0" gleam_erlang = ">= 1.0.0 and < 2.0.0" diff --git a/examples/manifest.toml b/examples/manifest.toml index 53e6dd4..15f49fb 100644 --- a/examples/manifest.toml +++ b/examples/manifest.toml @@ -28,7 +28,8 @@ packages = [ { name = "simplifile", version = "2.3.0", build_tools = ["gleam"], requirements = ["filepath", "gleam_stdlib"], otp_app = "simplifile", source = "hex", outer_checksum = "0A868DAC6063D9E983477981839810DC2E553285AB4588B87E3E9C96A7FB4CB4" }, { name = "telemetry", version = "1.3.0", build_tools = ["rebar3"], requirements = [], otp_app = "telemetry", source = "hex", outer_checksum = "7015FC8919DBE63764F4B4B87A95B7C0996BD539E0D499BE6EC9D7F3875B79E6" }, { name = "tiny_database", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_json", "gleam_stdlib", "simplifile", "youid"], source = "local", path = "utilities/tiny_database" }, - { name = "wisp", version = "2.0.1", build_tools = ["gleam"], requirements = ["directories", "exception", "filepath", "gleam_crypto", "gleam_erlang", "gleam_http", "gleam_json", "gleam_stdlib", "houdini", "logging", "marceau", "mist", "simplifile"], source = "local", path = ".." }, + { name = "wisp", version = "2.1.0", build_tools = ["gleam"], requirements = ["directories", "exception", "filepath", "gleam_crypto", "gleam_erlang", "gleam_http", "gleam_json", "gleam_stdlib", "houdini", "logging", "marceau", "simplifile"], source = "local", path = ".." }, + { name = "wisp_mist", version = "1.0.0", build_tools = ["gleam"], requirements = ["exception", "gleam_http", "gleam_stdlib", "mist", "wisp"], source = "local", path = "../wisp_mist" }, { name = "youid", version = "1.5.1", build_tools = ["gleam"], requirements = ["gleam_crypto", "gleam_stdlib", "gleam_time"], otp_app = "youid", source = "hex", outer_checksum = "580E909FD704DB16416D5CB080618EDC2DA0F1BE4D21B490C0683335E3FFC5AF" }, ] @@ -43,3 +44,4 @@ gsv = { version = ">= 4.0.0 and < 5.0.0" } mist = { version = ">= 5.0.0 and < 6.0.0" } tiny_database = { path = "utilities/tiny_database" } wisp = { path = ".." } +wisp_mist = { path = "../wisp_mist" } diff --git a/examples/src/hello_world/app.gleam b/examples/src/hello_world/app.gleam index cc5a15c..e5d9e75 100644 --- a/examples/src/hello_world/app.gleam +++ b/examples/src/hello_world/app.gleam @@ -2,7 +2,7 @@ import gleam/erlang/process import hello_world/app/router import mist import wisp -import wisp/wisp_mist +import wisp_mist pub fn main() { // This sets the logger to print INFO level logs, and other sensible defaults diff --git a/examples/src/logging/app.gleam b/examples/src/logging/app.gleam index 01f97e8..c7d73bb 100644 --- a/examples/src/logging/app.gleam +++ b/examples/src/logging/app.gleam @@ -2,7 +2,7 @@ import gleam/erlang/process import logging/app/router import mist import wisp -import wisp/wisp_mist +import wisp_mist pub fn main() { wisp.configure_logger() diff --git a/examples/src/routing/app.gleam b/examples/src/routing/app.gleam index f435032..16c265b 100644 --- a/examples/src/routing/app.gleam +++ b/examples/src/routing/app.gleam @@ -2,7 +2,7 @@ import gleam/erlang/process import mist import routing/app/router import wisp -import wisp/wisp_mist +import wisp_mist pub fn main() { wisp.configure_logger() diff --git a/examples/src/serving_static_assets/app.gleam b/examples/src/serving_static_assets/app.gleam index 9aa71db..8e9b188 100644 --- a/examples/src/serving_static_assets/app.gleam +++ b/examples/src/serving_static_assets/app.gleam @@ -3,7 +3,7 @@ import mist import serving_static_assets/app/router import serving_static_assets/app/web.{Context} import wisp -import wisp/wisp_mist +import wisp_mist pub fn main() { wisp.configure_logger() diff --git a/examples/src/using_a_database/app.gleam b/examples/src/using_a_database/app.gleam index a1e0ceb..be93efb 100644 --- a/examples/src/using_a_database/app.gleam +++ b/examples/src/using_a_database/app.gleam @@ -4,7 +4,7 @@ import tiny_database import using_a_database/app/router import using_a_database/app/web import wisp -import wisp/wisp_mist +import wisp_mist pub const data_directory = "tmp/data" diff --git a/examples/src/working_with_cookies/app.gleam b/examples/src/working_with_cookies/app.gleam index 44e7e91..ca03197 100644 --- a/examples/src/working_with_cookies/app.gleam +++ b/examples/src/working_with_cookies/app.gleam @@ -1,7 +1,7 @@ import gleam/erlang/process import mist import wisp -import wisp/wisp_mist +import wisp_mist import working_with_cookies/app/router pub fn main() { diff --git a/examples/src/working_with_files/app.gleam b/examples/src/working_with_files/app.gleam index 5daf67f..afb0a3b 100644 --- a/examples/src/working_with_files/app.gleam +++ b/examples/src/working_with_files/app.gleam @@ -1,7 +1,7 @@ import gleam/erlang/process import mist import wisp -import wisp/wisp_mist +import wisp_mist import working_with_files/app/router pub fn main() { diff --git a/examples/src/working_with_form_data/app.gleam b/examples/src/working_with_form_data/app.gleam index 14917db..5c9a486 100644 --- a/examples/src/working_with_form_data/app.gleam +++ b/examples/src/working_with_form_data/app.gleam @@ -1,7 +1,7 @@ import gleam/erlang/process import mist import wisp -import wisp/wisp_mist +import wisp_mist import working_with_form_data/app/router pub fn main() { diff --git a/examples/src/working_with_json/app.gleam b/examples/src/working_with_json/app.gleam index 4ecac38..b86f444 100644 --- a/examples/src/working_with_json/app.gleam +++ b/examples/src/working_with_json/app.gleam @@ -1,7 +1,7 @@ import gleam/erlang/process import mist import wisp -import wisp/wisp_mist +import wisp_mist import working_with_json/app/router pub fn main() { diff --git a/examples/src/working_with_other_formats/app.gleam b/examples/src/working_with_other_formats/app.gleam index b6113f9..d842e7d 100644 --- a/examples/src/working_with_other_formats/app.gleam +++ b/examples/src/working_with_other_formats/app.gleam @@ -1,7 +1,7 @@ import gleam/erlang/process import mist import wisp -import wisp/wisp_mist +import wisp_mist import working_with_other_formats/app/router pub fn main() { diff --git a/gleam.toml b/gleam.toml index 4321100..e7201b8 100644 --- a/gleam.toml +++ b/gleam.toml @@ -14,7 +14,6 @@ gleam_erlang = ">= 1.0.0 and < 2.0.0" gleam_http = ">= 3.5.0 and < 5.0.0" gleam_json = ">= 3.0.0 and < 4.0.0" gleam_stdlib = ">= 0.50.0 and < 2.0.0" -mist = ">= 2.0.0 and < 6.0.0" simplifile = ">= 2.0.0 and < 3.0.0" marceau = ">= 1.1.0 and < 2.0.0" logging = ">= 1.2.0 and < 2.0.0" diff --git a/manifest.toml b/manifest.toml index 93a7183..beaf129 100644 --- a/manifest.toml +++ b/manifest.toml @@ -10,20 +10,13 @@ packages = [ { 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_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_yielder", version = "1.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_yielder", source = "hex", outer_checksum = "8E4E4ECFA7982859F430C57F549200C7749823C106759F4A19A78AEA6687717A" }, + { name = "gleam_stdlib", version = "0.65.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "7C69C71D8C493AE11A5184828A77110EB05A7786EBF8B25B36A72F879C3EE107" }, { 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" }, - { name = "gramps", version = "6.0.0", build_tools = ["gleam"], requirements = ["gleam_crypto", "gleam_erlang", "gleam_http", "gleam_stdlib"], otp_app = "gramps", source = "hex", outer_checksum = "8B7195978FBFD30B43DF791A8A272041B81E45D245314D7A41FC57237AA882A0" }, { name = "houdini", version = "1.2.0", build_tools = ["gleam"], requirements = [], otp_app = "houdini", source = "hex", outer_checksum = "5DB1053F1AF828049C2B206D4403C18970ABEF5C18671CA3C2D2ED0DD64F6385" }, - { name = "hpack_erl", version = "0.3.0", build_tools = ["rebar3"], requirements = [], otp_app = "hpack", source = "hex", outer_checksum = "D6137D7079169D8C485C6962DFE261AF5B9EF60FBC557344511C1E65E3D95FB0" }, { name = "logging", version = "1.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "logging", source = "hex", outer_checksum = "1098FBF10B54B44C2C7FDF0B01C1253CAFACDACABEFB4B0D027803246753E06D" }, { name = "marceau", version = "1.3.0", build_tools = ["gleam"], requirements = [], otp_app = "marceau", source = "hex", outer_checksum = "2D1C27504BEF45005F5DFB18591F8610FB4BFA91744878210BDC464412EC44E9" }, - { name = "mist", version = "5.0.3", build_tools = ["gleam"], requirements = ["exception", "gleam_erlang", "gleam_http", "gleam_otp", "gleam_stdlib", "gleam_yielder", "glisten", "gramps", "hpack_erl", "logging"], otp_app = "mist", source = "hex", outer_checksum = "7C4BE717A81305323C47C8A591E6B9BA4AC7F56354BF70B4D3DF08CC01192668" }, { name = "platform", version = "1.0.0", build_tools = ["gleam"], requirements = [], otp_app = "platform", source = "hex", outer_checksum = "8339420A95AD89AAC0F82F4C3DB8DD401041742D6C3F46132A8739F6AEB75391" }, { name = "simplifile", version = "2.3.0", build_tools = ["gleam"], requirements = ["filepath", "gleam_stdlib"], otp_app = "simplifile", source = "hex", outer_checksum = "0A868DAC6063D9E983477981839810DC2E553285AB4588B87E3E9C96A7FB4CB4" }, - { name = "telemetry", version = "1.3.0", build_tools = ["rebar3"], requirements = [], otp_app = "telemetry", source = "hex", outer_checksum = "7015FC8919DBE63764F4B4B87A95B7C0996BD539E0D499BE6EC9D7F3875B79E6" }, ] [requirements] @@ -39,5 +32,4 @@ 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" } marceau = { version = ">= 1.1.0 and < 2.0.0" } -mist = { version = ">= 2.0.0 and < 6.0.0" } simplifile = { version = ">= 2.0.0 and < 3.0.0" } diff --git a/wisp_ewe/.github/workflows/test.yml b/wisp_ewe/.github/workflows/test.yml new file mode 100644 index 0000000..4a7fe22 --- /dev/null +++ b/wisp_ewe/.github/workflows/test.yml @@ -0,0 +1,23 @@ +name: test + +on: + push: + branches: + - master + - main + pull_request: + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: erlef/setup-beam@v1 + with: + otp-version: "27.1.2" + gleam-version: "1.12.0" + rebar3-version: "3" + # elixir-version: "1" + - run: gleam deps download + - run: gleam test + - run: gleam format --check src test diff --git a/wisp_ewe/.gitignore b/wisp_ewe/.gitignore new file mode 100644 index 0000000..599be4e --- /dev/null +++ b/wisp_ewe/.gitignore @@ -0,0 +1,4 @@ +*.beam +*.ez +/build +erl_crash.dump diff --git a/wisp_ewe/README.md b/wisp_ewe/README.md new file mode 100644 index 0000000..1bb92b1 --- /dev/null +++ b/wisp_ewe/README.md @@ -0,0 +1,25 @@ +# wisp_ewe + +[![Package Version](https://img.shields.io/hexpm/v/wisp_ewe)](https://hex.pm/packages/wisp_ewe) +[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](https://hexdocs.pm/wisp_ewe/) + +An Ewe adapter for Wisp. + +```sh +gleam add wisp_ewe +``` + +## Example + +```gleam +pub fn main() -> Nil { + let secret_key_base = "..." + let assert Ok(_) = + handle_request + |> wisp_ewe.handler(secret_key_base) + |> ewe.new + |> ewe.listening(port: 8000) + |> ewe.start + process.sleep_forever() +} +``` \ No newline at end of file diff --git a/wisp_ewe/gleam.toml b/wisp_ewe/gleam.toml new file mode 100644 index 0000000..f45e487 --- /dev/null +++ b/wisp_ewe/gleam.toml @@ -0,0 +1,24 @@ +name = "wisp_ewe" +version = "1.0.0" + +# Fill out these fields if you intend to generate HTML documentation or publish +# your project to the Hex package manager. +# +# description = "" +# licences = ["Apache-2.0"] +# repository = { type = "github", user = "", repo = "" } +# links = [{ title = "Website", href = "" }] +# +# For a full reference of all the available options, you can have a look at +# https://gleam.run/writing-gleam/gleam-toml/. + +[dependencies] +gleam_stdlib = ">= 0.44.0 and < 2.0.0" +wisp = ">= 2.1.0 and < 3.0.0" +ewe = ">= 1.0.1 and < 2.0.0" +exception = ">= 2.1.0 and < 3.0.0" +gleam_http = ">= 4.2.0 and < 5.0.0" + +[dev-dependencies] +gleeunit = ">= 1.0.0 and < 2.0.0" +gleam_httpc = ">= 5.0.0 and < 6.0.0" diff --git a/wisp_ewe/manifest.toml b/wisp_ewe/manifest.toml new file mode 100644 index 0000000..8294a92 --- /dev/null +++ b/wisp_ewe/manifest.toml @@ -0,0 +1,40 @@ +# This file was generated by Gleam +# You typically do not need to edit this file + +packages = [ + { name = "compresso", version = "0.1.0", build_tools = ["gleam"], requirements = ["exception", "gleam_erlang", "gleam_stdlib", "gleam_yielder", "logging"], otp_app = "compresso", source = "hex", outer_checksum = "8BE29A1EDA42F70826ED148EAE40C46BB3FC18E78FE472663DB01DD4A38172D4" }, + { name = "directories", version = "1.2.0", build_tools = ["gleam"], requirements = ["envoy", "gleam_stdlib", "platform", "simplifile"], otp_app = "directories", source = "hex", outer_checksum = "D13090CFCDF6759B87217E8DDD73A75903A700148A82C1D33799F333E249BF9E" }, + { name = "envoy", version = "1.0.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "envoy", source = "hex", outer_checksum = "95FD059345AA982E89A0B6E2A3BF1CF43E17A7048DCD85B5B65D3B9E4E39D359" }, + { name = "ewe", version = "1.0.1", build_tools = ["gleam"], requirements = ["compresso", "gleam_crypto", "gleam_erlang", "gleam_http", "gleam_otp", "gleam_stdlib", "gleam_yielder", "glisten", "logging"], otp_app = "ewe", source = "hex", outer_checksum = "ABA3D559AD607B7B2C116313815E4F9B5EFEA5C80CFB05E11678E06E16D22DAA" }, + { name = "exception", version = "2.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "exception", source = "hex", outer_checksum = "329D269D5C2A314F7364BD2711372B6F2C58FA6F39981572E5CA68624D291F8C" }, + { 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_httpc", version = "5.0.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_http", "gleam_stdlib"], otp_app = "gleam_httpc", source = "hex", outer_checksum = "C545172618D07811494E97AAA4A0FB34DA6F6D0061FDC8041C2F8E3BE2B2E48F" }, + { 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.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" }, + { name = "gramps", version = "6.0.0", build_tools = ["gleam"], requirements = ["gleam_crypto", "gleam_erlang", "gleam_http", "gleam_stdlib"], otp_app = "gramps", source = "hex", outer_checksum = "8B7195978FBFD30B43DF791A8A272041B81E45D245314D7A41FC57237AA882A0" }, + { name = "houdini", version = "1.2.0", build_tools = ["gleam"], requirements = [], otp_app = "houdini", source = "hex", outer_checksum = "5DB1053F1AF828049C2B206D4403C18970ABEF5C18671CA3C2D2ED0DD64F6385" }, + { name = "hpack_erl", version = "0.3.0", build_tools = ["rebar3"], requirements = [], otp_app = "hpack", source = "hex", outer_checksum = "D6137D7079169D8C485C6962DFE261AF5B9EF60FBC557344511C1E65E3D95FB0" }, + { name = "logging", version = "1.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "logging", source = "hex", outer_checksum = "1098FBF10B54B44C2C7FDF0B01C1253CAFACDACABEFB4B0D027803246753E06D" }, + { name = "marceau", version = "1.3.0", build_tools = ["gleam"], requirements = [], otp_app = "marceau", source = "hex", outer_checksum = "2D1C27504BEF45005F5DFB18591F8610FB4BFA91744878210BDC464412EC44E9" }, + { name = "mist", version = "5.0.3", build_tools = ["gleam"], requirements = ["exception", "gleam_erlang", "gleam_http", "gleam_otp", "gleam_stdlib", "gleam_yielder", "glisten", "gramps", "hpack_erl", "logging"], otp_app = "mist", source = "hex", outer_checksum = "7C4BE717A81305323C47C8A591E6B9BA4AC7F56354BF70B4D3DF08CC01192668" }, + { name = "platform", version = "1.0.0", build_tools = ["gleam"], requirements = [], otp_app = "platform", source = "hex", outer_checksum = "8339420A95AD89AAC0F82F4C3DB8DD401041742D6C3F46132A8739F6AEB75391" }, + { name = "simplifile", version = "2.3.0", build_tools = ["gleam"], requirements = ["filepath", "gleam_stdlib"], otp_app = "simplifile", source = "hex", outer_checksum = "0A868DAC6063D9E983477981839810DC2E553285AB4588B87E3E9C96A7FB4CB4" }, + { name = "telemetry", version = "1.3.0", build_tools = ["rebar3"], requirements = [], otp_app = "telemetry", source = "hex", outer_checksum = "7015FC8919DBE63764F4B4B87A95B7C0996BD539E0D499BE6EC9D7F3875B79E6" }, + { name = "wisp", version = "2.1.0", build_tools = ["gleam"], requirements = ["directories", "exception", "filepath", "gleam_crypto", "gleam_erlang", "gleam_http", "gleam_json", "gleam_stdlib", "houdini", "logging", "marceau", "mist", "simplifile"], otp_app = "wisp", source = "hex", outer_checksum = "362BDDD11BF48EB38CDE51A73BC7D1B89581B395CA998E3F23F11EC026151C54" }, +] + +[requirements] +ewe = { version = ">= 1.0.1 and < 2.0.0" } +exception = { version = ">= 2.1.0 and < 3.0.0" } +gleam_http = { version = ">= 4.2.0 and < 5.0.0" } +gleam_httpc = { version = ">= 5.0.0 and < 6.0.0" } +gleam_stdlib = { version = ">= 0.44.0 and < 2.0.0" } +gleeunit = { version = ">= 1.0.0 and < 2.0.0" } +wisp = { version = ">= 2.1.0 and < 3.0.0" } diff --git a/wisp_ewe/src/wisp_ewe.gleam b/wisp_ewe/src/wisp_ewe.gleam new file mode 100644 index 0000000..b2de661 --- /dev/null +++ b/wisp_ewe/src/wisp_ewe.gleam @@ -0,0 +1,100 @@ +import ewe.{type Request as EweRequest, type Response as EweResponse} +import exception +import gleam/http/request +import gleam/http/response +import gleam/option +import gleam/result +import gleam/string +import wisp.{type Request as WispRequest, type Response as WispResponse} +import wisp/internal + +/// Convert a Wisp request handler into a function that can be run with the Ewe +/// web server. +/// +/// # Examples +/// +/// ```gleam +/// pub fn main() { +/// let secret_key_base = "..." +/// let assert Ok(_) = +/// handle_request +/// |> wisp_ewe.handler(secret_key_base) +/// |> ewe.new +/// |> ewe.listening(port: 8000) +/// |> ewe.start +/// +/// process.sleep_forever() +/// } +/// ``` +/// +/// The secret key base is used for signing and encryption. To be able to +/// verify and decrypt messages you will need to use the same key each time +/// your program is run. Keep this value secret! Malicious people with this +/// value will likely be able to hack your application. +/// +pub fn handler( + handler: fn(WispRequest) -> WispResponse, + secret_key_base: String, +) -> fn(EweRequest) -> EweResponse { + fn(req) { + let conn = internal.make_connection(ewe_body_reader(req), secret_key_base) + let req = request.set_body(req, conn) + + use <- exception.defer(fn() { + let assert Ok(_) = wisp.delete_temporary_files(req) + }) + + handler(req) + |> ewe_response + } +} + +fn ewe_body_reader(req: EweRequest) -> internal.Reader { + case ewe.stream_body(req) { + Ok(consumer) -> wrap_ewe_consumer(consumer) + Error(_) -> fn(_) { Ok(internal.ReadingFinished) } + } +} + +fn wrap_ewe_consumer(consumer: ewe.Consumer) -> internal.Reader { + fn(size) { wrap_ewe_chunk(consumer(size)) } +} + +fn wrap_ewe_chunk( + chunk: Result(ewe.Stream, ewe.BodyError), +) -> Result(internal.Read, Nil) { + result.replace_error(chunk, Nil) + |> result.map(fn(chunk) { + case chunk { + ewe.Consumed(data:, next: consumer) -> + internal.Chunk(data, wrap_ewe_consumer(consumer)) + ewe.Done -> internal.ReadingFinished + } + }) +} + +fn ewe_response(resp: WispResponse) -> EweResponse { + case resp.body { + wisp.Text(text) -> response.set_body(resp, ewe.TextData(text)) + wisp.Bytes(bytes) -> response.set_body(resp, ewe.BytesData(bytes)) + wisp.File(path:, offset:, limit:) -> + ewe_send_file(resp, path, offset, limit) + } +} + +fn ewe_send_file( + resp: WispResponse, + path: String, + offset: Int, + limit: option.Option(Int), +) -> EweResponse { + case ewe.file(path, offset: option.Some(offset), limit:) { + Ok(file) -> response.set_body(resp, file) + Error(error) -> { + string.inspect(error) + |> wisp.log_error() + + response.new(500) |> response.set_body(ewe.Empty) + } + } +} diff --git a/wisp_ewe/test/wisp_ewe_test.gleam b/wisp_ewe/test/wisp_ewe_test.gleam new file mode 100644 index 0000000..3166572 --- /dev/null +++ b/wisp_ewe/test/wisp_ewe_test.gleam @@ -0,0 +1,33 @@ +import ewe +import gleam/http/request +import gleam/httpc +import gleeunit +import wisp +import wisp_ewe + +pub fn main() -> Nil { + gleeunit.main() +} + +pub fn handler_test() { + let secret_key_base = wisp.random_string(64) + + let assert Ok(_started) = + wisp_ewe.handler( + fn(_req) { + wisp.ok() + |> wisp.string_body("Hello, world!") + }, + secret_key_base, + ) + |> ewe.new + |> ewe.quiet + |> ewe.listening(port: 8000) + |> ewe.start + + let assert Ok(req) = request.to("http://localhost:8000") + let assert Ok(resp) = httpc.send(req) + + assert resp.status == 200 + assert resp.body == "Hello, world!" +} diff --git a/wisp_mist/.github/workflows/test.yml b/wisp_mist/.github/workflows/test.yml new file mode 100644 index 0000000..4a7fe22 --- /dev/null +++ b/wisp_mist/.github/workflows/test.yml @@ -0,0 +1,23 @@ +name: test + +on: + push: + branches: + - master + - main + pull_request: + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: erlef/setup-beam@v1 + with: + otp-version: "27.1.2" + gleam-version: "1.12.0" + rebar3-version: "3" + # elixir-version: "1" + - run: gleam deps download + - run: gleam test + - run: gleam format --check src test diff --git a/wisp_mist/.gitignore b/wisp_mist/.gitignore new file mode 100644 index 0000000..599be4e --- /dev/null +++ b/wisp_mist/.gitignore @@ -0,0 +1,4 @@ +*.beam +*.ez +/build +erl_crash.dump diff --git a/wisp_mist/README.md b/wisp_mist/README.md new file mode 100644 index 0000000..5b1bdc0 --- /dev/null +++ b/wisp_mist/README.md @@ -0,0 +1,25 @@ +# wisp_mist + +[![Package Version](https://img.shields.io/hexpm/v/wisp_mist)](https://hex.pm/packages/wisp_mist) +[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](https://hexdocs.pm/wisp_mist/) + +A Mist adapter for Wisp. + +```sh +gleam add wisp_mist +``` + +## Example + +```gleam +pub fn main() -> Nil { + let secret_key_base = "..." + let assert Ok(_) = + handle_request + |> wisp_mist.handler(secret_key_base) + |> mist.new + |> mist.port(8000) + |> mist.start + process.sleep_forever() +} +``` diff --git a/wisp_mist/gleam.toml b/wisp_mist/gleam.toml new file mode 100644 index 0000000..8847ce1 --- /dev/null +++ b/wisp_mist/gleam.toml @@ -0,0 +1,19 @@ +name = "wisp_mist" +version = "1.0.0" +gleam = ">= 1.11.0" +description = "A Mist adapter for Wisp" +licences = ["Apache-2.0"] + +repository = { type = "github", user = "gleam-wisp", repo = "wisp" } +links = [{ title = "Sponsor", href = "https://github.com/sponsors/lpil" }] + +[dependencies] +gleam_stdlib = ">= 0.44.0 and < 2.0.0" +mist = ">= 5.0.0 and < 6.0.0" +wisp = ">= 2.0.0 and < 3.0.0" +gleam_http = ">= 4.0.0 and < 5.0.0" +exception = ">= 2.0.0 and < 3.0.0" + +[dev-dependencies] +gleeunit = ">= 1.0.0 and < 2.0.0" +gleam_httpc = ">= 5.0.0 and < 6.0.0" diff --git a/wisp_mist/manifest.toml b/wisp_mist/manifest.toml new file mode 100644 index 0000000..6a668f9 --- /dev/null +++ b/wisp_mist/manifest.toml @@ -0,0 +1,38 @@ +# This file was generated by Gleam +# You typically do not need to edit this file + +packages = [ + { name = "directories", version = "1.2.0", build_tools = ["gleam"], requirements = ["envoy", "gleam_stdlib", "platform", "simplifile"], otp_app = "directories", source = "hex", outer_checksum = "D13090CFCDF6759B87217E8DDD73A75903A700148A82C1D33799F333E249BF9E" }, + { name = "envoy", version = "1.0.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "envoy", source = "hex", outer_checksum = "95FD059345AA982E89A0B6E2A3BF1CF43E17A7048DCD85B5B65D3B9E4E39D359" }, + { name = "exception", version = "2.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "exception", source = "hex", outer_checksum = "329D269D5C2A314F7364BD2711372B6F2C58FA6F39981572E5CA68624D291F8C" }, + { 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_httpc", version = "5.0.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_http", "gleam_stdlib"], otp_app = "gleam_httpc", source = "hex", outer_checksum = "C545172618D07811494E97AAA4A0FB34DA6F6D0061FDC8041C2F8E3BE2B2E48F" }, + { 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.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" }, + { name = "gramps", version = "6.0.0", build_tools = ["gleam"], requirements = ["gleam_crypto", "gleam_erlang", "gleam_http", "gleam_stdlib"], otp_app = "gramps", source = "hex", outer_checksum = "8B7195978FBFD30B43DF791A8A272041B81E45D245314D7A41FC57237AA882A0" }, + { name = "houdini", version = "1.2.0", build_tools = ["gleam"], requirements = [], otp_app = "houdini", source = "hex", outer_checksum = "5DB1053F1AF828049C2B206D4403C18970ABEF5C18671CA3C2D2ED0DD64F6385" }, + { name = "hpack_erl", version = "0.3.0", build_tools = ["rebar3"], requirements = [], otp_app = "hpack", source = "hex", outer_checksum = "D6137D7079169D8C485C6962DFE261AF5B9EF60FBC557344511C1E65E3D95FB0" }, + { name = "logging", version = "1.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "logging", source = "hex", outer_checksum = "1098FBF10B54B44C2C7FDF0B01C1253CAFACDACABEFB4B0D027803246753E06D" }, + { name = "marceau", version = "1.3.0", build_tools = ["gleam"], requirements = [], otp_app = "marceau", source = "hex", outer_checksum = "2D1C27504BEF45005F5DFB18591F8610FB4BFA91744878210BDC464412EC44E9" }, + { name = "mist", version = "5.0.3", build_tools = ["gleam"], requirements = ["exception", "gleam_erlang", "gleam_http", "gleam_otp", "gleam_stdlib", "gleam_yielder", "glisten", "gramps", "hpack_erl", "logging"], otp_app = "mist", source = "hex", outer_checksum = "7C4BE717A81305323C47C8A591E6B9BA4AC7F56354BF70B4D3DF08CC01192668" }, + { name = "platform", version = "1.0.0", build_tools = ["gleam"], requirements = [], otp_app = "platform", source = "hex", outer_checksum = "8339420A95AD89AAC0F82F4C3DB8DD401041742D6C3F46132A8739F6AEB75391" }, + { name = "simplifile", version = "2.3.0", build_tools = ["gleam"], requirements = ["filepath", "gleam_stdlib"], otp_app = "simplifile", source = "hex", outer_checksum = "0A868DAC6063D9E983477981839810DC2E553285AB4588B87E3E9C96A7FB4CB4" }, + { name = "telemetry", version = "1.3.0", build_tools = ["rebar3"], requirements = [], otp_app = "telemetry", source = "hex", outer_checksum = "7015FC8919DBE63764F4B4B87A95B7C0996BD539E0D499BE6EC9D7F3875B79E6" }, + { name = "wisp", version = "2.1.0", build_tools = ["gleam"], requirements = ["directories", "exception", "filepath", "gleam_crypto", "gleam_erlang", "gleam_http", "gleam_json", "gleam_stdlib", "houdini", "logging", "marceau", "mist", "simplifile"], otp_app = "wisp", source = "hex", outer_checksum = "362BDDD11BF48EB38CDE51A73BC7D1B89581B395CA998E3F23F11EC026151C54" }, +] + +[requirements] +exception = { version = ">= 2.0.0 and < 3.0.0" } +gleam_http = { version = ">= 4.0.0 and < 5.0.0" } +gleam_httpc = { version = ">= 5.0.0 and < 6.0.0" } +gleam_stdlib = { version = ">= 0.44.0 and < 2.0.0" } +gleeunit = { version = ">= 1.0.0 and < 2.0.0" } +mist = { version = ">= 5.0.0 and < 6.0.0" } +wisp = { version = ">= 2.0.0 and < 3.0.0" } diff --git a/src/wisp/wisp_mist.gleam b/wisp_mist/src/wisp_mist.gleam similarity index 80% rename from src/wisp/wisp_mist.gleam rename to wisp_mist/src/wisp_mist.gleam index 5e80dec..1082d4b 100644 --- a/src/wisp/wisp_mist.gleam +++ b/wisp_mist/src/wisp_mist.gleam @@ -26,7 +26,7 @@ import wisp/internal /// |> wisp_mist.handler(secret_key_base) /// |> mist.new /// |> mist.port(8000) -/// |> mist.start_http +/// |> mist.start /// process.sleep_forever() /// } /// ``` @@ -49,12 +49,9 @@ pub fn handler( let assert Ok(_) = wisp.delete_temporary_files(request) }) - let response = - request - |> handler - |> mist_response - - response + request + |> handler + |> mist_response } } @@ -80,26 +77,28 @@ fn wrap_mist_chunk( } fn mist_response(response: wisp.Response) -> HttpResponse(mist.ResponseData) { - let body = case response.body { - 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) + case response.body { + wisp.Text(text) -> + response.set_body(response, mist.Bytes(bytes_tree.from_string(text))) + wisp.Bytes(bytes) -> response.set_body(response, mist.Bytes(bytes)) + wisp.File(path:, offset:, limit:) -> + mist_send_file(response, path, offset, limit) } - response - |> response.set_body(body) } fn mist_send_file( + response: HttpResponse(wisp.Body), path: String, offset: Int, limit: option.Option(Int), -) -> mist.ResponseData { +) -> HttpResponse(mist.ResponseData) { case mist.send_file(path, offset:, limit:) { - Ok(body) -> body + Ok(body) -> response.set_body(response, body) Error(error) -> { wisp.log_error(string.inspect(error)) - // TODO: return 500 - mist.Bytes(bytes_tree.new()) + + response.new(500) + |> response.set_body(mist.Bytes(bytes_tree.new())) } } } diff --git a/wisp_mist/test/wisp_mist_test.gleam b/wisp_mist/test/wisp_mist_test.gleam new file mode 100644 index 0000000..059ebfc --- /dev/null +++ b/wisp_mist/test/wisp_mist_test.gleam @@ -0,0 +1,30 @@ +import gleam/http/request +import gleam/httpc +import gleeunit +import mist +import wisp +import wisp_mist + +pub fn main() -> Nil { + gleeunit.main() +} + +pub fn mist_adapter_test() { + let secret_key_base = wisp.random_string(64) + let handler = + wisp_mist.handler( + fn(_) { wisp.ok() |> wisp.string_body("Hello, world!") }, + secret_key_base, + ) + + let assert Ok(_) = + mist.new(handler) + |> mist.port(8000) + |> mist.start + + let assert Ok(req) = request.to("http://localhost:8000") + let assert Ok(res) = httpc.send(req) + + assert res.status == 200 + assert res.body == "Hello, world!" +}