Elm Web Server
An API with Node.js-bindings for Elm WebSocket/HTTP-servers.
Warnings
This package contains no native/kernel-code - All interop with Node.js is implemented using Elm's ports
-API. Modules with ports
are not intended for distribution on package-managers, as they can be unreliably implemented compared to regular Elm-modules, so open an issue if you encounter problems!
Elm, along with the Elm architecture, is designed for browser-applications; This project in an experimental attempt to embed the architecture inside Node.js.
Taking the unreasonable performance implications aside, it is fun to experience Elm as a shared language between client and server, with all of it's nice properties for refactoring and extension.
Features
- A small API to hook Elm's
Platform.program
intoNode/http
and/orWebsockets/ws
in Node.js. - Modules for working with Http-Request/Response & WebSocket messages on the server.
- Emulation for XmlHttpRequest & WebSocket to run
elm-lang/http
&elm-lang/websocket
on the server.
Installation
The package is implemented using JavaScript language-features supported >= v6.13.1
of Node.js.
The package is distributed through NPM:
npm install -S elm-web-server
if you're going to use the Server.WebSocket
-module, you will need to install the following package from NPM:
npm install -S ws
Open elm-package.json
and expose the internal Elm-modules from the package like this:
{
...
"source-directories": [
...
"node_modules/elm-web-server/source"
]
}
Take a look at the examples
-directory for inspiration.
JavaScript Interface
in Node.js, assuming an Elm module named Main
compiled to main.elm.js
in the same directory, the API can be used as such:
const Ews = require("elm-web-server")
const Http = require("http")
const Ws = require("ws")
const App = require("./main.elm.js")
const PORT = process.env.PORT || 3000
const worker = App.Main.worker()
const server = Http.createServer(Ews.createRequestListener(worker))
Ews.attachMessageListener(worker, new Ws.Server({ server }))
Ews.attachConsoleListener(worker)
server.listen(PORT, () => {
console.log(`listening at http://localhost:${PORT}`)
})
Importing elm-web-server
automatically exposes XmlHttpRequest
& WebSocket
globally to enable server-side usage of elm-lang/http
& elm-lang/websocket
.
Elm Interface
There is a couple of small modules for Elm, written to facilitate some basic server-logic.
Server.Http
The HTTP-module exposes utility for working with HTTP-requests/responses.
type alias Request =
{ connection : Connection
, method : Method
, headers : List Header
, url : Url
, body : Maybe String
}
type Error
= ConnectionClosed Connection
| Error String
listen : (Result Error Request -> msg) -> Sub msg
respondWith : (a -> String) -> Status -> List Header -> Maybe a -> Connection -> Response
respondWithJson : Status -> List Header -> Json.Encode.Value -> Connection -> Response
respondWithText : Status -> List Header -> String -> Connection -> Response
respondWithNothing : Status -> List Header -> Connection -> Response
send : Response -> Cmd msg
compareConnection : Connection -> Connection -> Bool
Server.Http.Url
The Http.Url module exposes types, decoding for Http-request urls.
toLocation
is helpful if you want to parse urls using evancz/url-parser
, as shown in examples/routing
.
type alias Url =
{ pathname : String
, search : String
}
decoder : Decoder Url
toLocation :
Url
->
{ href : String
, host : String
, hostname : String
, protocol : String
, origin : String
, port_ : String
, pathname : String
, search : String
, hash : String
, username : String
, password : String
}
Server.Http.Method
The Http.Method module exposes types, encoding, and decoding for Http-request methods.
type Method
= Get
| Head
| Post
| Put
| Delete
| Trace
| Options
| Connect
| Patch
| Method String
encode : Method -> Json.Encode.Value
decoder : Decoder Method
Server.Http.Status
The Http.Status module exposes types, encoding, and decoding for Http-request statuses.
type Status
= Ok
| Created
| Accepted
| NonAuthoritativeInformation
| NoContent
| ResetContent
| PartialContent
| MultiStatus
| AlreadyReported
| ImUsed
| MultipleChoices
| MovedPermanently
| Found
| SeeOther
| NotModified
| UseProxy
| SwitchProxy
| TemporaryRedirect
| PermanentRedirect
| BadRequest
| Unauthorized
| PaymentRequired
| Forbidden
| NotFound
| MethodNotAllowed
| NotAcceptable
| ProxyAuthenticationRequired
| RequestTimeout
| Conflict
| Gone
| LengthRequired
| PreconditionFailed
| PayloadTooLarge
| URITooLong
| UnsupporedMediaType
| RangeNotSatisfiable
| ExpectationFailed
| ImATeapot
| MisdirectedRequest
| UnprocessableEntity
| Locked
| FailedDependency
| UpgradeRequired
| PreconditionRequired
| TooManyRequests
| RequestHeaderFieldsTooLarge
| UnavailableForLegalReasons
| InternalServerError
| NotImplemented
| BadGateway
| ServiceUnavailable
| GatewayTimeout
| HTTPVersionNotSupported
| VariantAlsoNegotiates
| InsufficientStorage
| LoopDetected
| NotExtended
| NetworkAuthenticationRequired
| Status Int String
encode : Status -> Json.Encode.Value
decoder : Decoder Status
Server.Http.Header
The Http.Header module exposes types, encoding, and decoding for Http-request headers.
byteLength
is helpful if you want to set the ContentLength
-header, as shown in examples/routing
.
type Header
= ContentType MimeType
| Accept (List MimeType)
| ContentLength Int
| Header String String
type MimeType
= TextPlain
| TextHtml
| TextCss
| ApplicationJson
| ApplicationJavascript
| MimeType String
encode : List Header -> Json.Encode.Value
decoder : Decoder (List Header)
byteLength : String -> Int
Server.WebSocket
The WebSocket-module exposes utility for working with WebSocket connections & messages.
type Message
= Connected Connection
| Disconnected Connection
| Received Connection String
type Error
= ConnectionClosed Connection
| FailedToSend Connection String
| Error String
listen : (Result Error Message -> msg) -> Sub msg
send : String -> Connection -> Cmd msg
disconnect : Connection -> Cmd msg
compareConnection : Connection -> Connection -> Bool
Server.Console
The Console-module allows you to print information to the console in different formats.
log : String -> Cmd msg
logError : String -> Cmd msg
logWarning : String -> Cmd msg