Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

websockets #72

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions gleam.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ mist = ">= 0.13.0 and < 2.0.0"
simplifile = ">= 1.4.0 and != 1.6.0 and < 2.0.0"
marceau = ">= 1.1.0 and < 2.0.0"
logging = ">= 1.0.0 and < 2.0.0"
gleam_otp = ">= 0.10.0 and < 1.0.0"

[dev-dependencies]
gleeunit = "~> 1.0"
1 change: 1 addition & 0 deletions manifest.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ gleam_crypto = { version = ">= 1.0.0 and < 2.0.0" }
gleam_erlang = { version = ">= 0.21.0 and < 2.0.0" }
gleam_http = { version = ">= 3.5.0 and < 4.0.0" }
gleam_json = { version = ">= 0.6.0 and < 2.0.0" }
gleam_otp = { version = ">= 0.10.0 and < 1.0.0"}
gleam_stdlib = { version = ">= 0.29.0 and < 2.0.0" }
gleeunit = { version = "~> 1.0" }
logging = { version = ">= 1.0.0 and < 2.0.0" }
Expand Down
42 changes: 40 additions & 2 deletions src/wisp.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import gleam/dict.{type Dict}
import gleam/dynamic.{type Dynamic}
import gleam/erlang
import gleam/erlang/atom.{type Atom}
import gleam/erlang/process
import gleam/http.{type Method}
import gleam/http/cookie
import gleam/http/request.{type Request as HttpRequest}
Expand All @@ -17,6 +18,7 @@ import gleam/int
import gleam/json
import gleam/list
import gleam/option.{type Option}
import gleam/otp/actor
import gleam/result
import gleam/string
import gleam/string_builder.{type StringBuilder}
Expand Down Expand Up @@ -52,7 +54,12 @@ pub fn mist_handler(
secret_key_base: String,
) -> fn(HttpRequest(mist.Connection)) -> HttpResponse(mist.ResponseData) {
fn(request: HttpRequest(_)) {
let connection = make_connection(mist_body_reader(request), secret_key_base)
let connection =
make_connection(
mist_body_reader(request),
secret_key_base,
option.Some(request.body),
)
let request = request.set_body(request, connection)

use <- exception.defer(fn() {
Expand Down Expand Up @@ -95,6 +102,7 @@ fn mist_response(response: Response) -> HttpResponse(mist.ResponseData) {
Text(text) -> mist.Bytes(bytes_builder.from_string_builder(text))
Bytes(bytes) -> mist.Bytes(bytes)
File(path) -> mist_send_file(path)
Websocket(x) -> mist.Websocket(x)
}
response
|> response.set_body(body)
Expand Down Expand Up @@ -145,6 +153,8 @@ pub type Body {
/// in place of any with an empty body.
///
Empty

Websocket(process.Selector(process.ProcessDown))
bgwdotdev marked this conversation as resolved.
Show resolved Hide resolved
}

/// An alias for a HTTP response containing a `Body`.
Expand Down Expand Up @@ -605,10 +615,15 @@ pub opaque type Connection {
read_chunk_size: Int,
secret_key_base: String,
temporary_directory: String,
mist_conn: Option(mist.Connection),
bgwdotdev marked this conversation as resolved.
Show resolved Hide resolved
)
}

fn make_connection(body_reader: Reader, secret_key_base: String) -> Connection {
fn make_connection(
body_reader: Reader,
secret_key_base: String,
mist: Option(mist.Connection),
) -> Connection {
// TODO: replace `/tmp` with appropriate for the OS
let prefix = "/tmp/gleam-wisp/"
let temporary_directory = join_path(prefix, random_slug())
Expand All @@ -619,6 +634,7 @@ fn make_connection(body_reader: Reader, secret_key_base: String) -> Connection {
read_chunk_size: 1_000_000,
temporary_directory: temporary_directory,
secret_key_base: secret_key_base,
mist_conn: mist,
)
}

Expand Down Expand Up @@ -1832,5 +1848,27 @@ pub fn create_canned_connection(
make_connection(
fn(_size) { Ok(Chunk(body, fn(_size) { Ok(ReadingFinished) })) },
secret_key_base,
option.None,
)
}

pub fn websocket(
req: Request,
handler handler: fn(a, mist.WebsocketConnection, mist.WebsocketMessage(b)) ->
actor.Next(b, a),
on_init on_init: fn(mist.WebsocketConnection) ->
#(a, Option(process.Selector(b))),
on_close on_close: fn(a) -> Nil,
) -> Response {
bgwdotdev marked this conversation as resolved.
Show resolved Hide resolved
let assert option.Some(x) =
req.body.mist_conn
|> option.map(request.set_body(req, _))
let resp = mist.websocket(x, handler, on_init, on_close)
case resp.status, resp.body {
200, mist.Websocket(x) ->
ok()
|> set_body(Websocket(x))
400, _ -> bad_request()
_, _ -> internal_server_error()
}
}
6 changes: 3 additions & 3 deletions src/wisp/testing.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import gleam/string
import gleam/string_builder
import gleam/uri
import simplifile
import wisp.{type Request, type Response, Bytes, Empty, File, Text}
import wisp.{type Request, type Response, Bytes, Empty, File, Text, Websocket}

/// The default secret key base used for test requests.
/// This should never be used outside of tests.
Expand Down Expand Up @@ -226,7 +226,7 @@ pub fn patch_json(
///
pub fn string_body(response: Response) -> String {
case response.body {
Empty -> ""
Empty | Websocket(_) -> ""
Text(builder) -> string_builder.to_string(builder)
Bytes(bytes) -> {
let data = bytes_builder.to_bit_array(bytes)
Expand All @@ -249,7 +249,7 @@ pub fn string_body(response: Response) -> String {
///
pub fn bit_array_body(response: Response) -> BitArray {
case response.body {
Empty -> <<>>
Empty | Websocket(_) -> <<>>
Bytes(builder) -> bytes_builder.to_bit_array(builder)
Text(builder) ->
bytes_builder.to_bit_array(bytes_builder.from_string_builder(builder))
Expand Down