Packages
glisten
0.6.2
9.0.1
9.0.0
9.0.0-rc1
8.0.3
8.0.2
8.0.1
8.0.0
8.0.0-rc1
7.0.1
7.0.0
6.0.0
5.0.0
4.0.0
3.0.0
2.0.0
1.0.0
0.11.0
0.10.2
0.10.1
0.10.0
0.9.3
0.9.2
0.9.1
0.9.0
0.8.2
0.8.1
0.8.0
0.7.0
0.6.9
0.6.8
0.6.7
0.6.6
0.6.5
0.6.4
0.6.3
0.6.2
0.6.1
0.6.0
0.5.1
0.5.0
0.4.0
0.3.2
0.3.1
0.3.0
0.2.2
0.2.1
0.2.0
0.1.3
0.1.2
0.1.1
0.1.0
a shiny Gleam TCP/TLS server
Current section
Files
Jump to
Current section
Files
src/glisten.gleam
import gleam/dynamic.{Dynamic}
import gleam/erlang/process
import gleam/otp/actor
import gleam/result
import glisten/acceptor.{Pool, over_ssl}
import glisten/socket.{Closed, ListenSocket, Timeout}
import glisten/tcp
import glisten/ssl
import gleam/otp/actor
import glisten/ssl
import glisten/socket/options.{Certfile, Keyfile}
/// Reasons that `serve` might fail
pub type StartError {
ListenerClosed
ListenerTimeout
AcceptorTimeout
AcceptorFailed(process.ExitReason)
AcceptorCrashed(Dynamic)
}
/// Sets up a TCP listener with the given acceptor pool. The second argument
/// can be obtained from the `glisten/acceptor.{acceptor_pool}` function.
pub fn serve(
port: Int,
with_pool: fn(ListenSocket) -> Pool(data),
) -> Result(Nil, StartError) {
try _ =
port
|> tcp.listen([])
|> result.map_error(fn(err) {
case err {
Closed -> ListenerClosed
Timeout -> ListenerTimeout
}
})
|> result.then(fn(socket) {
socket
|> with_pool
|> acceptor.start_pool
|> result.map_error(fn(err) {
case err {
actor.InitTimeout -> AcceptorTimeout
actor.InitFailed(reason) -> AcceptorFailed(reason)
actor.InitCrashed(reason) -> AcceptorCrashed(reason)
}
})
})
Ok(Nil)
}
external fn start_ssl() -> Result(Nil, Dynamic) =
"ssl_ffi" "start_ssl"
/// Sets up a SSL listener with the given acceptor pool. The second argument
/// can be obtained from the `glisten/acceptor.{acceptor_pool}` function.
pub fn serve_ssl(
port port: Int,
certfile certfile: String,
keyfile keyfile: String,
with_pool with_pool: fn(ListenSocket) -> Pool(data),
) -> Result(Nil, StartError) {
assert Ok(_nil) = start_ssl()
try _ =
port
|> ssl.listen([Certfile(certfile), Keyfile(keyfile)])
|> result.map_error(fn(err) {
case err {
Closed -> ListenerClosed
Timeout -> ListenerTimeout
}
})
|> result.then(fn(socket) {
socket
|> over_ssl(with_pool)
|> acceptor.start_pool
|> result.map_error(fn(err) {
case err {
actor.InitTimeout -> AcceptorTimeout
actor.InitFailed(reason) -> AcceptorFailed(reason)
actor.InitCrashed(reason) -> AcceptorCrashed(reason)
}
})
})
Ok(Nil)
}