2025-02-25 14:55:22 -06:00
fmt
2024-12-01 17:14:19 -06:00
2024-12-01 11:57:24 -06:00
fmt
2024-12-01 17:11:10 -06:00
fmt
2024-12-01 17:13:45 -06:00
fmt
2024-12-01 17:13:45 -06:00
2024-12-01 16:27:17 -06:00
2024-12-01 16:27:17 -06:00
fmt
2024-12-01 17:11:10 -06:00
2024-12-01 16:28:13 -06:00
2025-02-25 14:55:22 -06:00
2024-12-04 21:51:15 -06:00
2025-02-12 12:26:30 -06:00

axon

WIP

HTTP server library inspired by axum, allowing best-in-class expressive routing.

root :: Get -> Path "/" _ -> Aff String
root _ _ = pure "Hello, world!"

main :: Effect Unit
main = Axon.serve (root `Handle.or` Handle.Default.notFound)

-- GET localhost:8000/      -> 200 OK "Hello, world!"
-- GET localhost:8000/foo   -> 404 Not Found

Request Handlers

Request handler functions have any number of parameters that are RequestParts and return an Aff Response (or any MonadAff).

RequestParts

  • Request
    • Always succeeds; provides the entire request
  • Combinators
    • Unit
      • Always succeeds
    • a /\ b
      • Tuple of a and b, where a and b are RequestParts.
    • Maybe a
      • a must be RequestParts. If a can't be extracted, the handler will still succeed and this will be Nothing. If a was extracted, it's wrapped in Just.
    • Either a b
      • a and b must be RequestParts. Succeeds if either a or b succeeds (preferring a). Fails if both fail.
  • Body
    • String
      • succeeds when request has a non-empty body that is valid UTF-8
    • Json a
      • succeeds when request has a String body (see above) that can be parsed into a using DecodeJson.
    • Buffer
      • succeeds when request has a nonempty body.
    • Stream
      • succeeds when request has a nonempty body.
  • Headers
    • Header a
      • a must be TypedHeader from Axon.Header.Typed. Allows statically (ex. ContentType Type.MIME.Json) or dynamically (ex. ContentType String) matching request headers.
    • HeaderMap
      • All headers provided in the request
  • Path
    • Path a c
      • Statically match the path of the request, and extract parameters. See Axon.Request.Parts.Path. (TODO: this feels too magical, maybe follow axum's prior art of baking paths into the router declaration?)
  • Method
    • Get
    • Post
    • Put
    • Patch
    • Delete
    • Options
    • Connect
    • Trace

Similarly to the structural extraction of request parts; handlers can use Axon.Response.Construct.ToResponse for easily constructing responses.

ToResponse

  • Combinators
    • Status /\ a
      • Special case to make sure any Status in a tuple will take priority over any default statuses within. TODO: This case (overlapping with a /\ b requires the class to be "sealed" in an instance chain. Want a clean way around this so consumers can implement ToResponse.)
    • a /\ b
      • Merges toResponse a and toResponse b, using b on conflicts
  • Status
    • Axon.Response.Status.Status
  • Body
    • Axon.Response.Body.Body
    • String
    • Node.Buffer.Buffer
    • Node.Stream.Readable a (for all a)
    • Axon.Response.Construct.Json a
      • a must be EncodeJson. This will set the body to a stringified, and set Content-Type to application/json.
  • Headers
    • ToResponse is implemented for all implementors of TypedHeader
    • TODO: Map String String
Description
No description provided
Readme 393 KiB
Languages
PureScript 96.4%
JavaScript 3.6%