### Run Headers Example Server Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Examples/Headers/Readme.md Use this command to run the example server. Ensure you have nix installed. ```bash nix-shell --run 'example Headers' ``` -------------------------------- ### Run Example Server with Nix Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Examples/HelloWorld/Readme.md Use this command to run the example server if you have Nix installed. ```bash nix-shell --run 'example HelloWorld' ``` -------------------------------- ### Run Async Response Example Server Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Examples/AsyncResponse/Readme.md Use this command to start the example server with Nix. ```bash nix-shell --run 'example AsyncResponse' ``` -------------------------------- ### Run Post Example Server Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Examples/Post/Readme.md Use this command to run the example server using nix-shell. Ensure you have nix installed. ```bash nix-shell --run 'example Post' ``` -------------------------------- ### Run Example Server Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Examples/ExtensibleMiddleware/Readme.md Use this command to execute the example server. Ensure you have Spago installed and the project dependencies are set up. ```bash spago -x test.dhall run --main Examples.ExtensibleMiddleware.Main ``` -------------------------------- ### Run SSL Example Server with Nix Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Examples/SSL/Readme.md Use this command to run the SSL example server if you have Nix installed. ```bash nix-shell --run 'example SSL' ``` -------------------------------- ### Run MultiRoute Example Server Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Examples/MultiRoute/Readme.md Use this command to run the example server with Nix. Ensure you have Nix installed and configured. ```bash nix-shell --run 'example MultiRoute' ``` -------------------------------- ### Run Query Parameters Example Server (without Nix) Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Examples/QueryParameters/Readme.md Alternatively, run the example server using spago if you do not have nix-shell installed. ```bash spago -x test.dhall run --main Examples.QueryParameters.Main ``` -------------------------------- ### Run MultiRoute Example Server without Nix Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Examples/MultiRoute/Readme.md Use this command to run the example server if you do not have Nix installed. Ensure Spago is installed and configured. ```bash spago -x test.dhall run --main Examples.MultiRoute.Main ``` -------------------------------- ### Run Async Response Example Server (without Nix) Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Examples/AsyncResponse/Readme.md Use this command to start the example server without Nix, using Spago. ```bash spago -x test.dhall run --main Examples.AsyncResponse.Main ``` -------------------------------- ### Run Path Segments Example Server Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Examples/PathSegments/Readme.md Use this command to run the example server with nix-shell. Ensure you have nix installed. ```bash nix-shell --run 'example PathSegments' ``` -------------------------------- ### Run Example Server without Nix Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Examples/HelloWorld/Readme.md Use this command to run the example server if you do not have Nix installed, assuming spago is available. ```bash spago -x test.dhall run --main Examples.HelloWorld.Main ``` -------------------------------- ### Run Chunked Example Server Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Examples/Chunked/Readme.md Use this command to run the example server for sending chunked data. Ensure you have nix-shell installed. ```bash nix-shell --run 'example Chunked' ``` -------------------------------- ### Run Chunked Example Server (without nix) Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Examples/Chunked/Readme.md Alternative command to run the example server if you are not using nix-shell. Ensure spago is installed. ```bash spago -x test.dhall run --main Examples.Chunked.Main ``` -------------------------------- ### Basic HTTPurple Server Setup Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/Readme.md A minimal example demonstrating how to set up a basic HTTP server with a single route using HTTPurple. This requires defining a route type and a router function. ```purescript module Main where import Prelude hiding ((/)) import HTTPurple data Route = Hello String derive instance Generic Route _ route :: RouteDuplex' Route route = mkRoute { "Hello": "hello" / segment } main :: ServerM main = serve { port: 8080 } { route, router } where router { route: Hello name } = ok $ "hello " <> name ``` -------------------------------- ### Run Headers Example Server (without nix) Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Examples/Headers/Readme.md Alternative command to run the example server if you are not using nix. ```bash spago -x test.dhall run --main Examples.Headers.Main ``` -------------------------------- ### Run Post Example Server (without nix) Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Examples/Post/Readme.md Use this command to run the example server without nix-shell. This requires spago to be installed and configured. ```bash spago -x test.dhall run --main Examples.Post.Main ``` -------------------------------- ### Start HTTPurple Server with Custom Options in Purescript Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Differences.md This Purescript example demonstrates how to start an HTTPurple server with custom configuration, including hostname, port, SSL certificates, a notFoundHandler, and custom handlers for server start and closing. ```purescript main :: ServerM main = serve { hostname: "localhost" , port: 9000 , certFile: "./Certificate.cer" , keyFile: "./Key.key" , notFoundHandler , onStarted: log "Server started 🚀" , closingHandler: NoClosingHandler } { route, router } where notFoundHandler :: Request Unit -> ResponseM notFoundHandler = const $ ok "Nothing to see here" ``` -------------------------------- ### Run Middleware Example Server Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Examples/Middleware/Readme.md Use this command to run the example server with Nix. ```bash nix-shell --run 'example Middleware' ``` -------------------------------- ### Run Query Parameters Example Server Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Examples/QueryParameters/Readme.md Use this command to run the example server for query parameters. It requires nix-shell. ```bash nix-shell --run 'example QueryParameters' ``` -------------------------------- ### Run Json Parsing Example with Nix Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Examples/JsonParsing/Readme.md Use this command to run the JSON parsing example server if you have Nix installed. ```bash nix-shell --run 'example JsonParsing' ``` -------------------------------- ### Run SSL Example Server without Nix Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Examples/SSL/Readme.md Use this command to run the SSL example server if you have Spago installed and are not using Nix. ```bash spago -x test.dhall run --main Examples.SSL.Main ``` -------------------------------- ### Run Binary Response Example with Nix Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Examples/BinaryResponse/Readme.md Execute the binary response example server using Nix. ```bash nix-shell --run 'example BinaryResponse' ``` -------------------------------- ### Run HTTPurple Examples Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/Readme.md Command to execute the example applications provided with HTTPurple. The startup banner will detail available routes. ```bash spago -x test.dhall run --main Examples..Main ``` -------------------------------- ### Run Path Segments Example Server (without nix) Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Examples/PathSegments/Readme.md Use this command to run the example server without nix. Ensure you have spago installed. ```bash spago -x test.dhall run --main Examples.PathSegments.Main ``` -------------------------------- ### Run Binary Response Example with Spago Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Examples/BinaryResponse/Readme.md Execute the binary response example server using Spago. ```bash spago -x test.dhall run --main Examples.BinaryResponse.Main ``` -------------------------------- ### Run Json Parsing Example without Nix Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Examples/JsonParsing/Readme.md Use this command to run the JSON parsing example server if you do not have Nix installed. Ensure Spago is set up. ```bash spago -x test.dhall run --main Examples.JsonParsing.Main ``` -------------------------------- ### Run Middleware Example Server (without Nix) Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Examples/Middleware/Readme.md Use this command to run the example server without Nix. ```bash spago -x test.dhall run --main Examples.Middleware.Main ``` -------------------------------- ### Run Binary Request Example Server Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Examples/BinaryRequest/Readme.md Use this command to run the binary request example server using Nix. ```bash nix-shell --run 'example BinaryRequest' ``` -------------------------------- ### Install Morgan Middleware Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Middleware.md Install the 'morgan' package for HTTP request logging. ```bash npm install morgan --save ``` -------------------------------- ### Run Binary Request Example Server (Spago) Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Examples/BinaryRequest/Readme.md Alternatively, run the binary request example server using Spago. ```bash spago -x test.dhall run --main Examples.BinaryRequest.Main ``` -------------------------------- ### Run Node.js Middleware Example Server Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Examples/NodeMiddleware/Readme.md To run the example server, use the 'spago' command with the provided arguments. Ensure you have 'test.dhall' and the 'Examples.NodeMiddleware.Main' module configured. ```bash spago -x test.dhall run --main Examples.NodeMiddleware.Main ``` -------------------------------- ### Start HTTPurple Server with Defaults in Purescript Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Differences.md This Purescript snippet shows the simplest way to start an HTTPurple server using default options. It requires only the route and router definitions. ```purescript main :: ServerM main = serve {} { route, router } ``` -------------------------------- ### Install Yoga-JSON Driver Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Requests.md Install the Yoga-JSON driver for JSON parsing with HTTPurple. ```bash spago install httpurple-yoga-json ``` -------------------------------- ### Install Helmet Middleware Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Middleware.md Install the 'helmet' package to add security headers to HTTP responses. ```bash npm install helmet --save ``` -------------------------------- ### Start an HTTP Server with Basic Routing Source: https://context7.com/sigma-andex/purescript-httpurple/llms.txt Starts an HTTP server using the `serve` function with a defined route and a simple router. Requires `Prelude`, `HTTPurple`, and `Routing.Duplex` imports. The server listens on localhost:8080. ```purescript module Main where import Prelude import Data.Generic.Rep (class Generic) import Effect.Console (log) import HTTPurple (ServerM, ok, serve) import Routing.Duplex as RD import Routing.Duplex.Generic as RG data Route = SayHello derive instance Generic Route _ route :: RD.RouteDuplex' Route route = RD.root $ RG.sum { "SayHello": RG.noArgs } main :: ServerM main = serve { hostname: "localhost", port: 8080, onStarted } { route, router: const $ ok "hello world!" } where onStarted = log "Server now up on port 8080" -- Test with: curl localhost:8080 -- => hello world! ``` -------------------------------- ### Serve Application with Middlewares Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Middleware.md Configures and starts the HTTP server using `serve`. It binds the `sayHelloRoute` to the `middlewareStack` applied to the `sayHello` handler, listening on localhost:8080. ```purescript main = serve { hostname: "localhost", port: 8080 } { route: sayHelloRoute, router: middlewareStack sayHello } ``` -------------------------------- ### Install Argonaut Driver Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Requests.md Install the Argonaut driver for JSON parsing with HTTPurple. ```bash spago install httpurple-argonaut ``` -------------------------------- ### Start an HTTPS Server with SSL Certificates Source: https://context7.com/sigma-andex/purescript-httpurple/llms.txt Starts an HTTPS server by providing `certFile` and `keyFile` paths in the listen options of the `serve` function. This enables secure communication over HTTPS. Requires `Aff` for asynchronous operations. ```purescript module Main where import Prelude import Data.Generic.Rep (class Generic) import Effect.Aff (Aff) import HTTPurple (Request, Response, ServerM, ok, serve) import Routing.Duplex as RD import Routing.Duplex.Generic as RG data Route = Test derive instance Generic Route _ route :: RD.RouteDuplex' Route route = RD.root $ RG.sum { "Test": RG.noArgs } main :: ServerM main = serve { hostname: "localhost" , port: 8080 , certFile: "./Certificate.cer" , keyFile: "./Key.key" } { route, router: const $ ok "hello secure world!" } -- Test with: curl --insecure https://localhost:8080 -- => hello secure world! ``` -------------------------------- ### Full Request Handling Example Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Requests.md A complete example demonstrating the typical flow of handling a JSON request: parsing, validation, business logic, and JSON output. ```purescript router { route: Home, method: Post, body } = usingCont do jsonRequest :: MyRequest <- fromJson Argonaut.jsonDecoder body -- parse the json input input :: MyValidatedInput <- fromValidated validateMyRequest jsonRequest -- validate the input data output :: MyOutput <- lift $ doSomethingAndReturnAff input -- do your business logic ok' jsonHeaders $ toJson Argonaut.jsonEncoder output -- return output as json ``` -------------------------------- ### Query HTTPurple Server with httpie Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/Readme.md Example of how to query the running HTTPurple server using the httpie command-line tool. ```bash ➜ http http://localhost:8080/hello/🗺 ``` -------------------------------- ### Configure Full Server Settings Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Basics.md An example demonstrating the full range of server settings that can be overridden in HTTPurple, including hostname, port, SSL files, and custom handlers. ```json { hostname: "localhost" , port: 9000 , certFile: "./Certificate.cer" , keyFile: "./Key.key" , notFoundHandler: custom404Handler , onStarted: log "Server started 🚀" , closingHandler: NoClosingHandler } ``` -------------------------------- ### Install HTTPurple with Spago Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/Readme.md Use this command to add HTTPurple to your PureScript project dependencies. ```bash spago install httpurple ``` -------------------------------- ### Serve Binary File Response Source: https://context7.com/sigma-andex/purescript-httpurple/llms.txt Use `ok'` with `header` to set the content type and provide a `Buffer` for binary responses like images. This example reads an image file. ```purescript module Main where import Prelude import Data.Generic.Rep (class Generic) import Effect.Aff (Aff) import Effect.Class (liftEffect) import HTTPurple (Request, Response, ResponseHeaders, ServerM, header, ok, ok', serve) import Node.FS.Aff (readFile) import Node.ChildProcess (defaultSpawnOptions, spawn, stdout) import Node.Stream (Readable) import Routing.Duplex as RD import Routing.Duplex.Generic as RG data Route = Image | Stream derive instance Generic Route _ route :: RD.RouteDuplex' Route route = RD.root $ RG.sum { "Image": RG.noArgs , "Stream": RG.noArgs } -- Serve binary file serveImage :: Aff Response serveImage = do buf <- readFile "./image.png" ok' (header "Content-Type" "image/png") buf -- Serve chunked stream serveStream :: Aff Response serveStream = do stream <- liftEffect $ stdout <$> spawn "bash" ["-c", "echo hello; sleep 1; echo world"] defaultSpawnOptions ok stream -- Automatically sets Transfer-Encoding: chunked router :: Request Route -> Aff Response router { route: Image } = serveImage router { route: Stream } = serveStream main :: ServerM main = serve { port: 8080 } { route, router } ``` -------------------------------- ### POST /api/users Source: https://context7.com/sigma-andex/purescript-httpurple/llms.txt Starts an HTTP server with the provided routing configuration. It accepts listen options (port, hostname, SSL certificates) and routing settings (route definition and router function). ```APIDOC ## serve - Start an HTTP Server ### Description Starts an HTTP server with the provided routing configuration. It accepts listen options (port, hostname, SSL certificates) and routing settings (route definition and router function). ### Method POST ### Endpoint /api/users ### Parameters #### Path Parameters - **userId** (string) - Required - The ID of the user to retrieve. #### Query Parameters - **includeDetails** (boolean) - Optional - Whether to include detailed user information. #### Request Body - **username** (string) - Required - The username for the new user. - **email** (string) - Required - The email address for the new user. ### Request Example ```json { "username": "johndoe", "email": "john.doe@example.com" } ``` ### Response #### Success Response (200) - **id** (string) - The unique identifier for the created user. - **message** (string) - A confirmation message. #### Response Example ```json { "id": "user123", "message": "User created successfully" } ``` ``` -------------------------------- ### Middleware Execution Order Example Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Middleware.md Illustrates the execution flow of composed middleware. Although composed right-to-left, the middleware functions execute left-to-right when a request is processed. ```purescript middleware letter router request = do EffectClass.liftEffect $ Console.log $ "Starting Middleware " <> letter response <- router request EffectClass.liftEffect $ Console.log $ "Ending Middleware " <> letter pure response main = HTTPure.serve port composedRouter $ Console.log "Server is up!" where composedRouter = middleware "A" <<< middleware "B" $ router ``` -------------------------------- ### Bash command for HTTPurple server status Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Differences.md This bash command indicates that the HTTPurple 🪁 server has started and is running on the default address and port. ```bash HTTPurple 🪁 up and running on http://0.0.0.0:8080 ``` -------------------------------- ### Define Routes with routing-duplex in Purescript Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Differences.md This example demonstrates defining routes using the 'routing-duplex' library in Purescript for HTTPurple. It includes basic routes, routes with string segments, and routes with query parameters and optional sorting. ```purescript module Main where import Prelude hiding ((/)) import Data.Either (Either(..)) import Data.Generic.Rep (class Generic) import Data.Maybe (Maybe(..)) import Data.Tuple (Tuple(..)) import HTTPurple data Route = Home | Profile String | Account String | Search { q :: String, sorting :: Maybe Sort } derive instance Generic Route _ data Sort = Asc | Desc derive instance Generic Sort _ sortToString :: Sort -> String sortToString = case _ of Asc -> "asc" Desc -> "desc" sortFromString :: String -> Either String Sort sortFromString = case _ of "asc" -> Right Asc "desc" -> Right Desc val -> Left $ "Not a sort: " <> val sort :: RouteDuplex' String -> RouteDuplex' Sort sort = as sortToString sortFromString api :: RouteDuplex' Route api = mkRoute { "Home": noArgs , "Profile": "profile" / string segment , "Account": "account" / string segment , "Search": "search" ? { q: string, sorting: optional <<< sort } } main :: ServerM main = serve { port: 8080 } { route: api, router: apiRouter } where apiRouter { route: Home } = ok "hello world!" apiRouter { route: Profile profile } = ok $ "hello " <> profile <> "!" apiRouter { route: Account account } = found' redirect "" where reverseRoute = print api $ Profile account redirect = headers { "Location": reverseRoute } apiRouter { route: Search { q, sorting } } = ok $ "searching for query " <> q <> " " <> case sorting of Just Asc -> "ascending" Just Desc -> "descending" Nothing -> "defaulting to ascending" ``` -------------------------------- ### Basic HTTP Responses: ok, created, notFound Source: https://context7.com/sigma-andex/purescript-httpurple/llms.txt Use HTTPurple's response helper functions for standard HTTP status codes. Examples include `ok` (200), `created` (201), `badRequest` (400), `unauthorized` (401), `notFound` (404), and `internalServerError` (500). ```purescript module Main where import Prelude hiding ((/)) import Data.Generic.Rep (class Generic) import Effect.Aff (Aff) import HTTPurple (Request, Response, ServerM, ok, created, accepted, noContent, badRequest, unauthorized, forbidden, notFound, internalServerError, serve) import Routing.Duplex as RD import Routing.Duplex.Generic as RG import Routing.Duplex.Generic.Syntax ((/)) data Route = Success | Create | Fail | Auth | Missing | Error derive instance Generic Route _ route :: RD.RouteDuplex' Route route = RD.root $ RG.sum { "Success": "success" / RG.noArgs , "Create": "create" / RG.noArgs , "Fail": "fail" / RG.noArgs , "Auth": "auth" / RG.noArgs , "Missing": "missing" / RG.noArgs , "Error": "error" / RG.noArgs } router :: Request Route -> Aff Response router { route: Success } = ok "Success!" -- 200 router { route: Create } = created -- 201 (no body) router { route: Fail } = badRequest "Invalid input" -- 400 router { route: Auth } = unauthorized -- 401 router { route: Missing } = notFound -- 404 router { route: Error } = internalServerError "Oops!" -- 500 main :: ServerM main = serve { port: 8080 } { route, router } ``` -------------------------------- ### Define Route Data Type and Mapping Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Routing.md Define a data type for your routes and create a mapping between its constructors and URL paths using `mkRoute`. This example shows a 'SayHello' route with a string parameter. ```purescript import HTTPurple -- We define a data type representing our route -- In this case, a single route `SayHello` that accepts one parameter data Route = SayHello String derive instance Generic Route _ -- a generic instance is needed -- The mapping between our data constructor `SayHello` and -- the route /hello/ route :: RouteDuplex' Route route = mkRoute { "SayHello": "hello" / string segment } -- We then start the http server passing the route and a handler function (router) main :: ServerM main = serve {} { route, router } where router { route: SayHello name } = ok $ "hello " <> name <> "!" ``` -------------------------------- ### Authenticator Middleware Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Middleware.md An example middleware that adds user information to the request based on an 'X-Token' header. It requires the `Union` type class for extending the request and `Nub` to ensure type safety. The middleware either adds `Just "John Doe"` or `Nothing` to the `user` field. ```purescript authenticator :: forall route extIn extOut. Nub (RequestR route extOut) (RequestR route extOut) => Union extIn (user :: Maybe String) extOut => Middleware route extIn extOut authenticator router request@{ headers } = case Headers.lookup headers "X-Token" of Just token | token == "123" -> router $ merge request { user: Just "John Doe" } _ -> router $ merge request { user: Nothing :: Maybe String } ``` -------------------------------- ### Matching HTTP Methods in HTTPurple Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Routing.md Route requests based on their HTTP method using standard pattern matching. Supports methods like `Post` and `Get`, with a fallback for unhandled methods. ```purescript router { method: HTTPurple.Post } = HTTPurple.ok "received a post" router { method: HTTPurple.Get } = HTTPurple.ok "received a get" router { method } = HTTPurple.ok $ "received a " <> show method ``` -------------------------------- ### Create a Basic HTTPurple Server Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Basics.md Use `HTTPurple.serve` to create a server. This function takes server configuration and a router. Ensure all necessary imports are included. ```purescript import Prelude hiding ((/)) import HTTPurple data Route = Hello String derive instance Generic Route _ route :: RouteDuplex' Route route = mkRoute { "Hello": "hello" / segment } main :: ServerM main = serve { port: 8080 } { route, router } where router { route: Hello name } = ok $ "hello " <> name ``` -------------------------------- ### Create an SSL-Enabled HTTPurple Server Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Basics.md Configure an SSL-enabled server by providing `certFile` and `keyFile` paths to the `HTTPurple.serve` function. This is typically handled at the infrastructure level. ```purescript main :: HTTPurple.ServerM main = HTTPurple.serve { port: 443, certFile : "./Certificate.cer", keyFile: "./Key.key" } { route, router } ... ``` -------------------------------- ### Compose and Serve with Middleware Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Middleware.md Demonstrates how to compose multiple middleware functions and pass the resulting composed router to the HTTPurple server. ```purescript main = HTTPure.serve port composedRouter $ Console.log "Server is up!" where composedRouter = middlewareA <<< middlewareB <<< middlewareC $ router ``` -------------------------------- ### Output JSON Response Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Requests.md Use the `toJson` function to encode your output data as JSON for the response. This example uses Argonaut's JSON encoder. ```purescript router { route: Home, method: Post, body } = usingCont do jsonRequest :: MyRequest <- fromJson Argonaut.jsonDecoder body input :: MyValidatedInput <- fromValidated validateMyRequest jsonRequest output :: MyOutput <- lift $ doSomethingAndReturnAff input ok' jsonHeaders $ toJson Argonaut.jsonEncoder output ``` -------------------------------- ### Input Validation with `fromValidated` Source: https://context7.com/sigma-andex/purescript-httpurple/llms.txt Use `fromValidated` to automatically handle validation failures by returning a 400 Bad Request response. This example validates a username's length. ```purescript module Main where import Prelude import Data.Either (Either(..)) import Data.Generic.Rep (class Generic) import Data.String (length) import HTTPurple (ServerM, fromValidated, ok, serve, usingCont) import Routing.Duplex as RD import Routing.Duplex.Generic as RG data Route = Test derive instance Generic Route _ route :: RD.RouteDuplex' Route route = RD.root $ RG.sum { "Test": RG.noArgs } -- Validation function validateUsername :: String -> Either String String validateUsername name | length name < 3 = Left "Username must be at least 3 characters" | length name > 20 = Left "Username must be at most 20 characters" | otherwise = Right name main :: ServerM main = serve { port: 8080 } { route, router } where router _ = usingCont do validName <- fromValidated validateUsername "John" ok $ "Valid username: " <> validName ``` -------------------------------- ### Define Routes with Path and Query Parameters Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Routing.md Defines three routes: home, products with path parameters, and search with query parameters. The 'sorting' parameter is optional. Requires defining a Route data type and a corresponding RouteDuplex'. ```purescript data Route = Home | Products String String -- the product route with two path parameters | Search { q :: String, sorting :: Maybe String } -- the search route with two query parameters, whereby sorting is optional derive instance Generic Route _ -- Next we define the route (mapping) route :: RouteDuplex' Route route = mkRoute { "Home": noArgs -- the root route / , "Products": "categories" / string segment / "products" / string segment , "Search": "search" ? { q: string, sorting: optional <<< string } } -- Finally, we pass the route (mapping) to the server and also define a route handler main :: ServerM main = serve { port: 8080 } { route: route, router } where router { route: Home } = ok "home" router { route: Products category product } = do ok $ "category=" <> category <> ", product=" <> product router { route: Search { q, sorting } } = ok $ "searching=" <> q <> "," <> case sorting of Just "asc" -> "ascending" _ -> "descending" ``` -------------------------------- ### Run HTTPurple Test Suite Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/Readme.md Command to execute the test suite for the HTTPurple library. ```bash spago -x test.dhall test ``` -------------------------------- ### Run HTTPurple Server Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/Readme.md Command to compile and run the PureScript HTTPurple server. ```bash ➜ spago run ``` -------------------------------- ### Creating a Singleton Response Header Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Responses.md Shows how to create a single response header using the `HTTPure.header` function. This is useful for setting specific headers like 'Content-Type'. ```purescript headers = HTTPure.header "Content-Type" "application/json" ``` -------------------------------- ### Manually Constructing a Response Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Responses.md Demonstrates how to manually construct a response object. This is generally not recommended over using response helpers. ```purescript router _ = pure $ { status: 200, headers: HTTPure.headers [], body: "foo" } ``` -------------------------------- ### Request Time Middleware Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Middleware.md A middleware that adds the current JavaScript Date to the request. It uses `liftEffect JSDate.now` to get the current time and adds it as a `time` field to the request. Requires `Union` and `Nub` type classes. ```purescript requestTime :: forall route extIn extOut. Nub (RequestR route extOut) (RequestR route extOut) => Union extIn (time :: JSDate) extOut => Middleware route extIn extOut requestTime router request = do time <- liftEffect JSDate.now router $ merge request { time } ``` -------------------------------- ### User Authentication API Source: https://context7.com/sigma-andex/purescript-httpurple/llms.txt Enable HTTPS by providing `certFile` and `keyFile` paths in the listen options. ```APIDOC ## serve with SSL/HTTPS ### Description Enable HTTPS by providing `certFile` and `keyFile` paths in the listen options. ### Method GET ### Endpoint /api/auth/login ### Parameters #### Query Parameters - **token** (string) - Required - The authentication token. ### Request Example ```json { "token": "your_auth_token_here" } ``` ### Response #### Success Response (200) - **isAuthenticated** (boolean) - Indicates if the user is authenticated. - **userId** (string) - The ID of the authenticated user, if available. #### Response Example ```json { "isAuthenticated": true, "userId": "user456" } ``` ``` -------------------------------- ### Set up Hot Module Reloading Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Basics.md Configure `package.json` and create an `index.js` to enable hot module reloading with `spago build -w` and `nodemon`. This allows for live updates during development. ```javascript import * as Main from './output/Main/index.js' Main.main() ``` ```json ... "scripts": { "hot": "spago build -w & nodemon \"node index.js\"" }, "type": "module", ... ``` -------------------------------- ### Define Route for SayHello Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Middleware.md Defines a simple route type `SayHello` and its corresponding `RouteDuplex'` instance using `root` and `sum` combinators. This sets up a basic route that can be handled by the server. ```purescript data SayHello = SayHello derive instance Generic SayHello _ sayHelloRoute :: RD.RouteDuplex' SayHello sayHelloRoute = RD.root $ RG.sum { "SayHello": RG.noArgs } ``` -------------------------------- ### Creating Response Headers from a Record Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Responses.md Illustrates creating `HTTPure.Headers` from a record, allowing for multiple headers and array values for headers like 'Set-Cookie'. ```purescript headers = HTTPure.headers { "Content-Type": "application/json", "Set-Cookie": ["cookie-value-1", "cookie-value-2"], "X-My-CustomHeader": "some-value" } ``` -------------------------------- ### Define Route and Handler with Middlewares Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Middleware.md Set up a Purescript server route and handler that utilizes the composed Node.js middlewares. The handler accesses the 'user' field added by the authenticator middleware. ```purescript data Route = Hello derive instance Generic Route _ route :: RouteDuplex' Route route = mkRoute { "Hello": noArgs } main :: ServerM main = serveNodeMiddleware { port: 8080 } { route, router: router, nodeMiddleware } where router { route: Hello, user } = case Nullable.toMaybe user of Just u -> ok $ "hello user " <> u Nothing -> ok $ "hello anonymous" ``` -------------------------------- ### Compose API and Meta Routes Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Routing.md Demonstrates composing two distinct route definitions ('ApiRoute' and 'MetaRoute') using the '<+>' operator and combining their handlers with 'orElse'. This allows for structuring routing logic into separate modules. ```purescript data ApiRoute = Home derive instance Generic Route _ api :: RouteDuplex' ApiRoute api = mkRoute { "Home": G.noArgs } data MetaRoute = Health derive instance Generic MetaRoute _ meta :: RouteDuplex' MetaRoute meta = mkRoute { "Health": "health" / G.noArgs } ``` ```purescript main :: ServerM main = serve { port: 8080, notFoundHandler } { route: api <+> meta, router: apiRouter `orElse` metaRouter } where apiRouter { route: Home } = ok "hello world!" metaRouter { route: Health } = ok "{\"status\":\"ok\"}" ``` -------------------------------- ### Route Prefixes in HTTPurple Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Routing.md Organize routes using prefixes like `/v1/` with the `prefix` method. For nested prefixes like `/api/v1/`, chain multiple `prefix` calls. ```purescript import HTTPurple data Route = Home -- list of paths derive instance Generic Route _ route :: RouteDuplex' Route route = root $ prefix "v1" $ sum { "Home": noArgs } main :: ServerM main = serve {} { route, router } where router { route: Home } = ok $ "hello 🗺!" ``` -------------------------------- ### Parse Query Parameters with params, flag, and optional Source: https://context7.com/sigma-andex/purescript-httpurple/llms.txt Parse query parameters using `params`. Use `flag` for boolean presence and `optional` for values that may be absent. This allows for flexible query string handling. ```purescript module Main where import Prelude import Data.Generic.Rep (class Generic) import Data.Maybe (Maybe(..)) import Effect.Aff (Aff) import HTTPurple (Request, Response, ServerM, notFound, ok, serve) import Routing.Duplex (RouteDuplex') import Routing.Duplex as RD import Routing.Duplex.Generic as G data Route = Route { foo :: Boolean, bar :: Maybe String, baz :: Maybe String } derive instance Generic Route _ route :: RouteDuplex' Route route = RD.root $ G.sum { "Route": RD.params { foo: RD.flag <<< RD.string , bar: RD.optional <<< RD.string , baz: RD.optional <<< RD.string } } router :: Request Route -> Aff Response router { route: Route { foo: true } } = ok "foo flag present" router { route: Route { bar: Just "test" } } = ok "bar equals test" router { route: Route { baz: Just value } } = ok value router _ = notFound main :: ServerM main = serve { port: 8080 } { route, router } -- Test with: -- curl localhost:8080?foo # => foo flag present -- curl localhost:8080?bar=test # => bar equals test -- curl localhost:8080?baz=anything # => anything ``` -------------------------------- ### Compose Logging and Header Middlewares Source: https://context7.com/sigma-andex/purescript-httpurple/llms.txt Chains logging and header manipulation middlewares using function composition (`<<<`). Ensure logging and header logic are applied in the desired order. ```purescript module Main where import Prelude hiding ((/)) import Data.Generic.Rep (class Generic) import Effect.Aff (Aff) import Effect.Class (liftEffect) import Effect.Console (log) import HTTPurple (Request, Response, ServerM, fullPath, header, ok, ok', serve) import Routing.Duplex as RD import Routing.Duplex.Generic as RG data Route = Test derive instance Generic Route _ route :: RD.RouteDuplex' Route route = RD.root $ RG.sum { "Test": RG.noArgs } -- Logging middleware loggingMiddleware :: forall route. (Request route -> Aff Response) -> Request route -> Aff Response loggingMiddleware router request = do liftEffect $ log $ "Request: " <> fullPath request response <- router request liftEffect $ log "Request complete" pure response -- Header middleware headerMiddleware :: forall route. (Request route -> Aff Response) -> Request route -> Aff Response headerMiddleware router request = do response@{ headers } <- router request pure $ response { headers = header "X-Powered-By" "HTTPurple" <> headers } -- Compose middlewares middlewareStack :: forall route. (Request route -> Aff Response) -> Request route -> Aff Response middlewareStack = loggingMiddleware <<< headerMiddleware -- Handler handler :: Request Route -> Aff Response handler _ = ok "Hello!" main :: ServerM main = serve { port: 8080 } { route, router: middlewareStack handler } ``` -------------------------------- ### Appending Response Headers Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Responses.md Demonstrates how to combine multiple `HTTPure.ResponseHeaders` objects using the `Semigroup` instance. This allows for building complex header sets. ```purescript headers = HTTPure.header "X-Header-A" "valueA" <> HTTPure.header "X-Header-B" "valueB" ``` -------------------------------- ### Compose Node Middlewares in Purescript Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Middleware.md Compose multiple Node.js middlewares (morgan, helmet, authenticator) into a single Purescript NodeMiddlewareStack. ```purescript nodeMiddleware ​:: NodeMiddlewareStack () AuthenticatorR nodeMiddleware = NodeMiddlewareStack $ usingMiddleware morgan >=> usingMiddleware helmet >=> usingMiddleware authenticator ``` -------------------------------- ### Export Morgan FFI Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Middleware.md Create a Foreign Function Interface (FFI) for the 'morgan' middleware in Purescript. ```javascript import { default as M } from "morgan"; export const morgan = M("tiny") ``` -------------------------------- ### Define Custom Newtypes for Route Arguments Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Routing.md Introduces newtypes for 'Category' and 'Product' to provide more specific type information for path parameters. Requires defining the newtypes and their instances, then updating the route data constructor and mapping. ```purescript newtype Category = Category String instance Newtype Category String newtype Product = Product String instance Newtype Product String ``` ```purescript | Products Category Product ``` ```purescript category :: RouteDuplex' Category category = _Newtype R.segment product :: RouteDuplex' Product product = _Newtype segment ``` ```purescript "Products": "categories" / category / "products" / product ``` -------------------------------- ### Server with Node.js Middleware Support Source: https://context7.com/sigma-andex/purescript-httpurple/llms.txt Integrates Node.js/Express-style middlewares using `serveNodeMiddleware`. This allows extending the request object with additional data, such as user authentication. Requires `NodeMiddleware` and `NodeMiddlewareStack` from `HTTPurple`. ```purescript module Main where import Prelude import Data.Generic.Rep (class Generic) import Data.Maybe (Maybe(..)) import Data.Nullable (Nullable, toMaybe) import Effect.Aff (Aff) import HTTPurple (ExtRequest, NodeMiddleware, NodeMiddlewareStack(..), Response, ServerM, ok, serveNodeMiddleware, usingMiddleware) import Routing.Duplex as RD import Routing.Duplex.Generic as RG foreign import authenticator :: NodeMiddleware (user :: Nullable String) nodeMiddleware :: NodeMiddlewareStack () (user :: Nullable String) nodeMiddleware = NodeMiddlewareStack $ usingMiddleware authenticator data Route = SayHello derive instance Generic Route _ route :: RD.RouteDuplex' Route route = RD.root $ RG.sum { "SayHello": RG.noArgs } router :: ExtRequest Route (user :: Nullable String) -> Aff Response router { user } = case toMaybe user of Just u -> ok $ "hello " <> u Nothing -> ok "hello anonymous" main :: ServerM main = serveNodeMiddleware { hostname: "localhost", port: 8080 } { route, router, nodeMiddleware } ``` -------------------------------- ### Export Helmet FFI Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Middleware.md Create an FFI for the 'helmet' middleware, which adds security headers. ```javascript import { default as H } from "helmet"; export const helmet = H() ``` -------------------------------- ### Responses with Custom Headers: ok', response' Source: https://context7.com/sigma-andex/purescript-httpurple/llms.txt Add custom headers to responses using primed functions like `ok'` and `response'` along with `ResponseHeaders`. Combine multiple headers using the `<>` operator. Ensure `HTTPurple.Headers` is imported for the `headers` record. ```purescript module Main where import Prelude import Data.Generic.Rep (class Generic) import Effect.Aff (Aff) import HTTPurple (Request, Response, ResponseHeaders, ServerM, header, ok', serve) import HTTPurple.Headers (headers) import Routing.Duplex as RD import Routing.Duplex.Generic as RG data Route = Test derive instance Generic Route _ route :: RD.RouteDuplex' Route route = RD.root $ RG.sum { "Test": RG.noArgs } -- Create headers from a record responseHeaders :: ResponseHeaders responseHeaders = headers { "X-Custom-Header": "custom value" , "X-Another": "another value" } -- Or create a single header contentType :: ResponseHeaders contentType = header "Content-Type" "application/json" router :: Request Route -> Aff Response router _ = ok' (responseHeaders <> contentType) "{\"message\": \"hello\"}" main :: ServerM main = serve { port: 8080 } { route, router } -- Test with: curl -v localhost:8080 -- Response includes X-Custom-Header and Content-Type headers ``` -------------------------------- ### Add User Authentication to Request Source: https://context7.com/sigma-andex/purescript-httpurple/llms.txt Extends the request with user information based on the 'X-Token' header. Requires `Nub` and `Union` constraints for type-safe extension. Use `merge` to add new fields to the request record. ```purescript module Main where import Prelude import Data.Generic.Rep (class Generic) import Data.JSDate (JSDate) import Data.JSDate as JSDate import Data.Maybe (Maybe(..)) import Effect.Aff (Aff) import Effect.Class (liftEffect) import HTTPurple (ExtRequest, Middleware, Request, RequestR, Response, ServerM, ok, serve) import HTTPurple as Headers import Prim.Row (class Nub, class Union) import Record (merge) import Routing.Duplex as RD import Routing.Duplex.Generic as RG -- Middleware that adds user info based on X-Token header authenticator :: forall route extIn extOut. Nub (RequestR route extOut) (RequestR route extOut) => Union extIn (user :: Maybe String) extOut => Middleware route extIn extOut authenticator router request@{ headers } = case Headers.lookup headers "X-Token" of Just "secret" -> router $ merge request { user: Just "Admin" } _ -> router $ merge request { user: Nothing :: Maybe String } -- Middleware that adds request timestamp requestTime :: forall route extIn extOut. Nub (RequestR route extOut) (RequestR route extOut) => Union extIn (time :: JSDate) extOut => Middleware route extIn extOut requestTime router request = do time <- liftEffect JSDate.now router $ merge request { time } data Route = Test derive instance Generic Route _ route :: RD.RouteDuplex' Route route = RD.root $ RG.sum { "Test": RG.noArgs } -- Handler receives extended request with user and time handler :: ExtRequest Route (user :: Maybe String, time :: JSDate) -> Aff Response handler { user: Just name, time } = ok $ "Hello " <> name <> " at " <> JSDate.toTimeString time handler { user: Nothing, time } = ok $ "Hello anonymous at " <> JSDate.toTimeString time -- Compose middlewares middlewareStack :: (ExtRequest Route (user :: Maybe String, time :: JSDate) -> Aff Response) -> Request Route -> Aff Response middlewareStack = authenticator <<< requestTime main :: ServerM main = serve { port: 8080 } { route, router: middlewareStack handler } -- Test with: curl -H "X-Token: secret" localhost:8080 -- => Hello Admin at 12:34:56 GMT ``` -------------------------------- ### Reverse Routing with HTTPurple Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Routing.md Implement reverse routing for redirects or HATEOAS using the `print` function from `routing-duplex`. Ensure the `Route` data type and `route` definition are correctly set up. ```purescript data Route = Old | New route :: RouteDuplex' Route route = mkRoute { "Old": "old" / RG.noArgs , "New": "new" / RG.noArgs } main :: ServerM main = serve { port: 8080 } { route, router } where router { route: Old } = found' redirect "" where redirect = headers [ Tuple "Location" $ print route $ New account ] ``` -------------------------------- ### Catch-all Route in HTTPurple Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Routing.md Create a catch-all route using the predefined `catchAll` function. This route captures any path not explicitly defined and can extract path segments as an `Array String`. ```purescript import HTTPurple data Route = CatchAll (Array String) -- list of paths derive instance Generic Route _ route :: RouteDuplex' Route route = mkRoute { "CatchAll": catchAll } main :: ServerM main = serve {} { route, router } where router { route: CatchAll paths } = ok $ "hello 🗺!" ``` -------------------------------- ### Import Morgan in Purescript Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Middleware.md Define the foreign import for the 'morgan' Node.js middleware in your Purescript file. The empty tuple '()' signifies that this middleware does not add any extra information to the request. ```purescript foreign import morgan :: NodeMiddleware () ``` -------------------------------- ### Compose Middleware Stack Source: https://github.com/sigma-andex/purescript-httpurple/blob/main/docs/Middleware.md Demonstrates composing the `authenticator` and `requestTime` middlewares using the function composition operator (`<<<`). This creates a single middleware stack that applies both functionalities. ```purescript middlewareStack :: forall route. (ExtRequest route (user :: Maybe String, time :: JSDate) -> ResponseM) -> Request route -> ResponseM middlewareStack = authenticator <<< requestTime ``` -------------------------------- ### Process Request Bodies: toString, toBuffer, toStream Source: https://context7.com/sigma-andex/purescript-httpurple/llms.txt Read request bodies as strings or buffers. Use `toString` for text and `toBuffer` for binary data. Ensure necessary imports are included. ```purescript module Main where import Prelude import Data.Generic.Rep (class Generic) import Effect.Aff (Aff) import HTTPurple (Request, Response, ServerM, ok, serve, toBuffer, toString) import Node.Buffer (size) import Effect.Class (liftEffect) import Routing.Duplex as RD import Routing.Duplex.Generic as RG data Route = Upload derive instance Generic Route _ route :: RD.RouteDuplex' Route route = RD.root $ RG.sum { "Upload": RG.noArgs } router :: Request Route -> Aff Response router { body } = do -- Read body as string str <- toString body -- Or read as buffer for binary data buf <- toBuffer body bufSize <- liftEffect $ size buf ok $ "Received " <> show bufSize <> " bytes: " <> str main :: ServerM main = serve { port: 8080 } { route, router } ```