Skip to content

Commit 78f39c0

Browse files
martinfojtiklpil
authored andcommitted
Refactor to use Wisp framework
1 parent 94f29a8 commit 78f39c0

File tree

9 files changed

+170
-167
lines changed

9 files changed

+170
-167
lines changed

.github/workflows/test.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ jobs:
1313
- uses: actions/checkout@v4
1414
- uses: erlef/setup-beam@v1
1515
with:
16-
otp-version: "26.0"
17-
gleam-version: "1.0.0"
16+
otp-version: "27"
17+
gleam-version: "1.9.1"
1818
rebar3-version: "3"
1919
- run: gleam test
2020
- run: gleam format --check src test

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM ghcr.io/gleam-lang/gleam:v0.25.3-erlang-alpine
1+
FROM ghcr.io/gleam-lang/gleam:v1.9.1-erlang-alpine
22

33
# Create a group and user to run as
44
RUN addgroup -S echogroup && adduser -S echouser -G echogroup

gleam.toml

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name = "reply"
2-
version = "1.0.0"
2+
version = "1.1.0"
33
licences = ["Apache-2.0"]
44
description = "A tiny echo server written in Gleam!"
55

@@ -10,10 +10,12 @@ links = [
1010
]
1111

1212
[dependencies]
13-
gleam_stdlib = "~> 0.25 or ~> 1.0"
14-
gleam_http = "~> 3.0"
15-
gleam_elli = "~> 2.0"
16-
gleam_erlang = "~> 0.17"
13+
gleam_stdlib = "~> 0.38"
14+
gleam_http = "~> 3.5"
15+
gleam_erlang = "~> 0.23"
16+
wisp = ">= 1.2.0 and < 2.0.0"
17+
mist = ">= 4.0.6 and < 5.0.0"
18+
envoy = ">= 1.0.2 and < 2.0.0"
1719

1820
[dev-dependencies]
1921
gleeunit = "~> 1.0"

manifest.toml

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,35 @@
22
# You typically do not need to edit this file
33

44
packages = [
5-
{ name = "elli", version = "3.3.0", build_tools = ["rebar3"], requirements = [], otp_app = "elli", source = "hex", outer_checksum = "698B13B33D05661DB9FE7EFCBA41B84825A379CCE86E486CF6AFF9285BE0CCF8" },
6-
{ name = "gleam_elli", version = "2.4.0", build_tools = ["gleam"], requirements = ["elli", "gleam_erlang", "gleam_http", "gleam_otp", "gleam_stdlib"], otp_app = "gleam_elli", source = "hex", outer_checksum = "433F5AF4ED92C55F3EBA8942610E974254EEF90F484AF26E3D775E33338DE832" },
7-
{ name = "gleam_erlang", version = "0.25.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_erlang", source = "hex", outer_checksum = "054D571A7092D2A9727B3E5D183B7507DAB0DA41556EC9133606F09C15497373" },
8-
{ name = "gleam_http", version = "3.6.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_http", source = "hex", outer_checksum = "8C07DF9DF8CC7F054C650839A51C30A7D3C26482AC241C899C1CEA86B22DBE51" },
9-
{ name = "gleam_otp", version = "0.10.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_stdlib"], otp_app = "gleam_otp", source = "hex", outer_checksum = "0B04FE915ACECE539B317F9652CAADBBC0F000184D586AAAF2D94C100945D72B" },
10-
{ name = "gleam_stdlib", version = "0.36.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "C0D14D807FEC6F8A08A7C9EF8DFDE6AE5C10E40E21325B2B29365965D82EB3D4" },
11-
{ name = "gleeunit", version = "1.0.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "D364C87AFEB26BDB4FB8A5ABDE67D635DC9FA52D6AB68416044C35B096C6882D" },
5+
{ name = "directories", version = "1.1.0", build_tools = ["gleam"], requirements = ["envoy", "gleam_stdlib", "platform", "simplifile"], otp_app = "directories", source = "hex", outer_checksum = "BDA521A4EB9EE3A7894F0DC863797878E91FF5C7826F7084B2E731E208BDB076" },
6+
{ name = "envoy", version = "1.0.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "envoy", source = "hex", outer_checksum = "95FD059345AA982E89A0B6E2A3BF1CF43E17A7048DCD85B5B65D3B9E4E39D359" },
7+
{ name = "exception", version = "2.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "exception", source = "hex", outer_checksum = "F5580D584F16A20B7FCDCABF9E9BE9A2C1F6AC4F9176FA6DD0B63E3B20D450AA" },
8+
{ name = "filepath", version = "1.1.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "filepath", source = "hex", outer_checksum = "B06A9AF0BF10E51401D64B98E4B627F1D2E48C154967DA7AF4D0914780A6D40A" },
9+
{ name = "gleam_crypto", version = "1.5.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_crypto", source = "hex", outer_checksum = "917BC8B87DBD584830E3B389CBCAB140FFE7CB27866D27C6D0FB87A9ECF35602" },
10+
{ name = "gleam_erlang", version = "0.34.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_erlang", source = "hex", outer_checksum = "0C38F2A128BAA0CEF17C3000BD2097EB80634E239CE31A86400C4416A5D0FDCC" },
11+
{ name = "gleam_http", version = "3.7.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_http", source = "hex", outer_checksum = "8A70D2F70BB7CFEB5DF048A2183FFBA91AF6D4CF5798504841744A16999E33D2" },
12+
{ name = "gleam_json", version = "2.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_json", source = "hex", outer_checksum = "C55C5C2B318533A8072D221C5E06E5A75711C129E420DD1CE463342106012E5D" },
13+
{ name = "gleam_otp", version = "0.16.1", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_stdlib"], otp_app = "gleam_otp", source = "hex", outer_checksum = "50DA1539FC8E8FA09924EB36A67A2BBB0AD6B27BCDED5A7EF627057CF69D035E" },
14+
{ name = "gleam_stdlib", version = "0.59.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "F8FEE9B35797301994B81AF75508CF87C328FE1585558B0FFD188DC2B32EAA95" },
15+
{ name = "gleam_yielder", version = "1.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_yielder", source = "hex", outer_checksum = "8E4E4ECFA7982859F430C57F549200C7749823C106759F4A19A78AEA6687717A" },
16+
{ name = "gleeunit", version = "1.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "0E6C83834BA65EDCAAF4FE4FB94AC697D9262D83E6F58A750D63C9F6C8A9D9FF" },
17+
{ name = "glisten", version = "7.0.1", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_otp", "gleam_stdlib", "logging", "telemetry"], otp_app = "glisten", source = "hex", outer_checksum = "1A53CF9FB3231A93FF7F1BD519A43DC968C1722F126CDD278403A78725FC5189" },
18+
{ name = "gramps", version = "3.0.1", build_tools = ["gleam"], requirements = ["gleam_crypto", "gleam_erlang", "gleam_http", "gleam_stdlib"], otp_app = "gramps", source = "hex", outer_checksum = "59194B3980110B403EE6B75330DB82CDE05FC8138491C2EAEACBC7AAEF30B2E8" },
19+
{ name = "hpack_erl", version = "0.3.0", build_tools = ["rebar3"], requirements = [], otp_app = "hpack", source = "hex", outer_checksum = "D6137D7079169D8C485C6962DFE261AF5B9EF60FBC557344511C1E65E3D95FB0" },
20+
{ name = "logging", version = "1.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "logging", source = "hex", outer_checksum = "1098FBF10B54B44C2C7FDF0B01C1253CAFACDACABEFB4B0D027803246753E06D" },
21+
{ name = "marceau", version = "1.3.0", build_tools = ["gleam"], requirements = [], otp_app = "marceau", source = "hex", outer_checksum = "2D1C27504BEF45005F5DFB18591F8610FB4BFA91744878210BDC464412EC44E9" },
22+
{ name = "mist", version = "4.0.6", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_http", "gleam_otp", "gleam_stdlib", "gleam_yielder", "glisten", "gramps", "hpack_erl", "logging"], otp_app = "mist", source = "hex", outer_checksum = "ED319E5A7F2056E08340B6976EA5E717F3C3BB36056219AF826D280D9C077952" },
23+
{ name = "platform", version = "1.0.0", build_tools = ["gleam"], requirements = [], otp_app = "platform", source = "hex", outer_checksum = "8339420A95AD89AAC0F82F4C3DB8DD401041742D6C3F46132A8739F6AEB75391" },
24+
{ name = "simplifile", version = "2.2.1", build_tools = ["gleam"], requirements = ["filepath", "gleam_stdlib"], otp_app = "simplifile", source = "hex", outer_checksum = "C88E0EE2D509F6D86EB55161D631657675AA7684DAB83822F7E59EB93D9A60E3" },
25+
{ name = "telemetry", version = "1.3.0", build_tools = ["rebar3"], requirements = [], otp_app = "telemetry", source = "hex", outer_checksum = "7015FC8919DBE63764F4B4B87A95B7C0996BD539E0D499BE6EC9D7F3875B79E6" },
26+
{ name = "wisp", version = "1.6.0", build_tools = ["gleam"], requirements = ["directories", "exception", "gleam_crypto", "gleam_erlang", "gleam_http", "gleam_json", "gleam_stdlib", "logging", "marceau", "mist", "simplifile"], otp_app = "wisp", source = "hex", outer_checksum = "AE1C568FE30718C358D3B37666DF0A0743ECD96094AD98C9F4921475075F660A" },
1227
]
1328

1429
[requirements]
15-
gleam_elli = { version = "~> 2.0" }
16-
gleam_erlang = { version = "~> 0.17" }
17-
gleam_http = { version = "~> 3.0" }
18-
gleam_stdlib = { version = "~> 0.25 or ~> 1.0" }
30+
envoy = { version = ">= 1.0.2 and < 2.0.0" }
31+
gleam_erlang = { version = "~> 0.23" }
32+
gleam_http = { version = "~> 3.5" }
33+
gleam_stdlib = { version = "~> 0.38" }
1934
gleeunit = { version = "~> 1.0" }
35+
mist = { version = ">= 4.0.6 and < 5.0.0" }
36+
wisp = { version = ">= 1.2.0 and < 2.0.0" }

src/reply.gleam

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,28 @@
1-
import gleam/erlang/os
21
import gleam/erlang/process
3-
import gleam/http/elli
42
import gleam/int
5-
import gleam/io
63
import gleam/result
7-
import gleam/string
8-
import reply/web
4+
import envoy
5+
import mist
6+
import wisp
7+
import wisp/wisp_mist
8+
import reply/router
99

1010
pub fn main() {
11+
wisp.configure_logger()
12+
1113
let port =
12-
os.get_env("PORT")
14+
envoy.get("PORT")
1315
|> result.then(int.parse)
1416
|> result.unwrap(3000)
1517

18+
let secret_key_base = wisp.random_string(64)
19+
1620
// Start the web server process
1721
let assert Ok(_) =
18-
web.stack()
19-
|> elli.start(on_port: port)
20-
21-
["Started listening on localhost:", int.to_string(port), " ✨"]
22-
|> string.concat
23-
|> io.println
22+
wisp_mist.handler(router.handle_request, secret_key_base)
23+
|> mist.new
24+
|> mist.port(port)
25+
|> mist.start_http
2426

2527
// Put the main process to sleep while the web server does its thing
2628
process.sleep_forever()

src/reply/router.gleam

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import reply/web
2+
import wisp.{type Request, type Response}
3+
4+
pub fn handle_request(req: Request) -> Response {
5+
use req <- web.middleware(req)
6+
7+
case wisp.path_segments(req) {
8+
["echo"] -> web.reply(req)
9+
["hello", name] -> web.hello(name)
10+
_ -> web.not_found()
11+
}
12+
}

src/reply/web.gleam

Lines changed: 43 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,61 @@
1-
import gleam/bit_array
2-
import gleam/bytes_builder
3-
import gleam/http.{Get, Post}
4-
import gleam/http/request
51
import gleam/http/response
6-
import gleam/http/service
2+
import gleam/http.{Post}
3+
import gleam/http/request
74
import gleam/result
85
import gleam/string
9-
import reply/web/logger
6+
import wisp.{type Request, type Response}
107

11-
fn reply(request) {
12-
let content_type =
13-
request
14-
|> request.get_header("content-type")
15-
|> result.unwrap("application/octet-stream")
8+
pub fn middleware(
9+
req: Request,
10+
handle_request: fn(Request) -> Response,
11+
) -> wisp.Response {
12+
let req = wisp.method_override(req)
13+
use <- wisp.log_request(req)
14+
use <- wisp.rescue_crashes
15+
use req <- wisp.handle_head(req)
16+
17+
use <- default_responses
1618

17-
response.new(200)
18-
|> response.set_body(request.body)
19-
|> response.prepend_header("content-type", content_type)
19+
handle_request(req)
2020
}
2121

22-
fn not_found() {
23-
let body =
24-
"There's nothing here. Try POSTing to /echo"
25-
|> bit_array.from_string
22+
pub fn default_responses(handle_request: fn() -> Response){
23+
let response = handle_request()
2624

27-
response.new(404)
28-
|> response.set_body(body)
29-
|> response.prepend_header("content-type", "text/plain")
25+
response.set_header(response, "made-with", "Gleam")
3026
}
3127

32-
fn hello(name) {
33-
let reply = case string.lowercase(name) {
34-
"mike" -> "Hello, Joe!"
35-
_ -> string.concat(["Hello, ", name, "!"])
28+
pub fn reply(request: Request) {
29+
case request.method {
30+
Post -> reply_post_response(request)
31+
_ -> wisp.method_not_allowed([Post])
3632
}
37-
38-
response.new(200)
39-
|> response.set_body(bit_array.from_string(reply))
40-
|> response.prepend_header("content-type", "text/plain")
4133
}
4234

43-
pub fn service(request) {
44-
let path = request.path_segments(request)
35+
fn reply_post_response(request: Request) {
36+
use body <- wisp.require_string_body(request)
4537

46-
case request.method, path {
47-
Post, ["echo"] -> reply(request)
48-
Get, ["hello", name] -> hello(name)
49-
_, _ -> not_found()
38+
let content_type = request.get_header(request, "content-type")
39+
|> result.unwrap("application/octet-stream")
40+
41+
wisp.ok()
42+
|> wisp.set_header("content-type", content_type)
43+
|> wisp.string_body(body)
44+
}
45+
46+
pub fn hello(name) {
47+
let reply = case string.lowercase(name) {
48+
"mike" -> "Hello, Joe!"
49+
_ -> string.concat(["Hello, ", name, "!"])
5050
}
51+
52+
wisp.ok()
53+
|> wisp.set_header("content-type", "text/plain")
54+
|> wisp.string_body(reply)
5155
}
5256

53-
pub fn stack() {
54-
service
55-
|> service.prepend_response_header("made-with", "Gleam")
56-
|> service.map_response_body(bytes_builder.from_bit_array)
57-
|> logger.middleware
57+
pub fn not_found() {
58+
wisp.not_found()
59+
|> wisp.set_header("content-type", "text/plain")
60+
|> wisp.string_body("There's nothing here. Try POSTing to /echo")
5861
}

src/reply/web/logger.gleam

Lines changed: 0 additions & 29 deletions
This file was deleted.

0 commit comments

Comments
 (0)