Fix some documentation issues (#70)

This commit is contained in:
Connor Prussin 2017-09-26 07:47:05 -07:00 committed by GitHub
parent 3fd5cf0179
commit d8eb77d666
12 changed files with 100 additions and 76 deletions

View File

@ -10,6 +10,9 @@ BOWER := bower
NODE := node NODE := node
NPM := npm NPM := npm
# Options to pass to pulp when building
BUILD_OPTIONS := -- --stash --censor-lib --strict
# Package manifest files # Package manifest files
BOWERJSON := bower.json BOWERJSON := bower.json
@ -47,7 +50,7 @@ $(BUILD): $(COMPONENTS) $(SOURCES)
$(PULP) build \ $(PULP) build \
--src-path $(SRCPATH) \ --src-path $(SRCPATH) \
--build-path $(BUILD) \ --build-path $(BUILD) \
-- --stash --censor-lib --strict $(BUILD_OPTIONS)
touch $(BUILD) touch $(BUILD)
build: $(BUILD) build: $(BUILD)
@ -89,7 +92,7 @@ test: $(BUILD) $(TESTSOURCES) $(EXAMPLESOURCES)
--include $(EXAMPLESPATH) \ --include $(EXAMPLESPATH) \
--build-path $(BUILD) \ --build-path $(BUILD) \
--main $(TESTMAIN) \ --main $(TESTMAIN) \
-- --stash --censor-lib --strict $(BUILD_OPTIONS)
# Launch a repl with all modules loaded # Launch a repl with all modules loaded
repl: $(COMPONENTS) $(SOURCES) $(TESTSOURCES) $(EXAMPLESOURCES) repl: $(COMPONENTS) $(SOURCES) $(TESTSOURCES) $(EXAMPLESOURCES)

View File

@ -7,14 +7,24 @@
A purescript HTTP server framework. A purescript HTTP server framework.
HTTPure is:
- Well-tested (see our [tests](./test))
- Well-documented (see our [documentation](./docs))
- Built to take advantage of PureScript language features for flexible and
extensible routing
- Pure (no `set`, `get`, `use`, etc)
## Status ## Status
This project is currently an early-stage work in progress. It is not This project is currently fairly stable, but has not reached it's 1.0 release
production-ready yet. You can track what's left before it gets production-ready yet. You can track what's left before it gets there by looking at our
by looking at [roadmap](https://github.com/cprussin/purescript-httpure/projects). The API
our [roadmap](https://github.com/cprussin/purescript-httpure/projects). If you'd signatures are _mostly_ stable, but are subject to change before the 1.0 release
like to help us get there quicker, please contribute! To get started, check if there's a good reason to change them.
our [contributing guide](Contributing.md).
If you'd like to help us get to 1.0 quicker, please contribute! To get started,
check our [contributing guide](Contributing.md).
## Installation ## Installation
@ -27,10 +37,9 @@ bower install --save purescript-httpure
```purescript ```purescript
module Main where module Main where
import Prelude (pure, ($)) import Prelude (($))
import Control.Monad.Eff.Console as Console import Control.Monad.Eff.Console as Console
import Data.StrMap as StrMap
import HTTPure as HTTPure import HTTPure as HTTPure
main :: HTTPure.ServerM (console :: Console.CONSOLE) main :: HTTPure.ServerM (console :: Console.CONSOLE)

View File

@ -15,11 +15,11 @@ import Node.Stream as Stream
import HTTPure.HTTPureM as HTTPureM import HTTPure.HTTPureM as HTTPureM
-- | The Body type is just sugar for a String, that will be sent or received in -- | The `Body` type is just sugar for a `String`, that will be sent or received
-- | the HTTP body. -- | in the HTTP body.
type Body = String type Body = String
-- | Extract the contents of the body of the HTTP Request. -- | Extract the contents of the body of the HTTP `Request`.
read :: forall e. HTTP.Request -> Aff.Aff (HTTPureM.HTTPureEffects e) Body read :: forall e. HTTP.Request -> Aff.Aff (HTTPureM.HTTPureEffects e) Body
read request = Aff.makeAff \_ success -> do read request = Aff.makeAff \_ success -> do
let stream = HTTP.requestAsStream request let stream = HTTP.requestAsStream request
@ -28,7 +28,7 @@ read request = Aff.makeAff \_ success -> do
void $ ST.modifySTRef buf ((<>) str) void $ ST.modifySTRef buf ((<>) str)
Stream.onEnd stream $ ST.readSTRef buf >>= success Stream.onEnd stream $ ST.readSTRef buf >>= success
-- | Write a body to the given HTTP Response and close it. -- | Write a `Body` to the given HTTP `Response` and close it.
write :: forall e. HTTP.Response -> Body -> Eff.Eff (http :: HTTP.HTTP | e) Unit write :: forall e. HTTP.Response -> Body -> Eff.Eff (http :: HTTP.HTTP | e) Unit
write response body = void do write response body = void do
_ <- Stream.writeString stream Encoding.UTF8 body $ pure unit _ <- Stream.writeString stream Encoding.UTF8 body $ pure unit

View File

@ -17,33 +17,34 @@ import Node.HTTP as HTTP
import HTTPure.Lookup as Lookup import HTTPure.Lookup as Lookup
-- | The Headers type is just sugar for a StrMap of Strings that represents the -- | The `Headers` type is just sugar for a `StrMap` of `Strings` that
-- | set of headers sent or received in an HTTP request or response. -- | represents the set of headers in an HTTP request or response.
newtype Headers = Headers (StrMap.StrMap String) newtype Headers = Headers (StrMap.StrMap String)
-- | Given a string, return the matching headers. This search is -- | Given a string, return the value of the matching header, or an empty string
-- | case-insensitive. -- | if no match exists. This search is case-insensitive.
instance lookupHeaders :: Lookup.Lookup Headers String String where instance lookupHeaders :: Lookup.Lookup Headers String String where
lookup (Headers headers') = lookup (Headers headers') =
Maybe.fromMaybe "" <<< flip StrMap.lookup headers' <<< StringUtil.toLower Maybe.fromMaybe "" <<< flip StrMap.lookup headers' <<< StringUtil.toLower
-- | Allow a headers set to be represented as a string. -- | Allow a `Headers` to be represented as a string. This string is formatted
-- | in HTTP headers format.
instance showHeaders :: Show Headers where instance showHeaders :: Show Headers where
show (Headers headers') = show (Headers headers') =
StrMap.foldMap showField headers' <> "\n" StrMap.foldMap showField headers' <> "\n"
where where
showField key value = key <> ": " <> value <> "\n" showField key value = key <> ": " <> value <> "\n"
-- | Compare two Headers objects by comparing the underlying StrMaps. -- | Compare two `Headers` objects by comparing the underlying `StrMaps`.
instance eqHeaders :: Eq Headers where instance eqHeaders :: Eq Headers where
eq (Headers a) (Headers b) = eq a b eq (Headers a) (Headers b) = eq a b
-- | Get the headers out of a HTTP Request object. -- | Get the headers out of a HTTP `Request` object.
read :: HTTP.Request -> Headers read :: HTTP.Request -> Headers
read = HTTP.requestHeaders >>> Headers read = HTTP.requestHeaders >>> Headers
-- | Given an HTTP Response and a Headers object, return an effect that will -- | Given an HTTP `Response` and a `Headers` object, return an effect that will
-- | write the Headers to the Response. -- | write the `Headers` to the `Response`.
write :: forall e. write :: forall e.
HTTP.Response -> HTTP.Response ->
Headers -> Headers ->
@ -51,6 +52,6 @@ write :: forall e.
write response (Headers headers') = void $ write response (Headers headers') = void $
TraversableWithIndex.traverseWithIndex (HTTP.setHeader response) headers' TraversableWithIndex.traverseWithIndex (HTTP.setHeader response) headers'
-- | Convert an Array of Tuples of 2 Strings to a Headers object. -- | Convert an `Array` of `Tuples` of 2 `Strings` to a `Headers` object.
headers :: Array (Tuple.Tuple String String) -> Headers headers :: Array (Tuple.Tuple String String) -> Headers
headers = StrMap.fromFoldable >>> Headers headers = StrMap.fromFoldable >>> Headers

View File

@ -10,24 +10,33 @@ import Data.Maybe as Maybe
import Data.Monoid as Monoid import Data.Monoid as Monoid
import Data.StrMap as StrMap import Data.StrMap as StrMap
-- | Types that implement the Lookup class can be looked up by some key to -- | Types that implement the `Lookup` class can be looked up by some key to
-- | retrieve some value. For instance, you could have an implementation for -- | retrieve some value. For instance, you could have an implementation for
-- | String (Maybe String) Int where `lookup string index` returns `Just` the -- | `String (Maybe String) Int` where `lookup s i` returns `Just` the
-- | character in `string` at `index`, or `Nothing` if `index` is out of bounds. -- | character in `s` at `i`, or `Nothing` if `i` is out of bounds.
class Lookup a v k where class Lookup a v k where
-- | Given some type and a key on that type, extract some value that
-- | corresponds to that key.
lookup :: a -> k -> v lookup :: a -> k -> v
-- | !! can be used as an infix operator instead of using the `lookup` function. -- | `!!` is inspired by `!!` in `Data.Array`, but note that it differs from
-- | `!!` in `Data.Array` in that the default instance for `Arrays` with `Int`
-- | key types is defined on `Arrays` of some members of `Monoids`, and will
-- | always return a value and will not return `Maybes`. If the requested index
-- | is out of bounds, then this implementation will return `mempty` instead of
-- | `Nothing`.
infixl 8 lookup as !! infixl 8 lookup as !!
-- | A default instance of Lookup for an Array of some type of Monoid. Note that -- | A default instance of `Lookup` for an `Array` of some type of `Monoid`.
-- | this is different from `!!` defined in `Data.Array` in that it does not -- | Note that this is different from `!!` defined in `Data.Array` in that it
-- | return a Maybe. If the index is out of bounds, the return value is mempty. -- | does not return a `Maybe`. If the index is out of bounds, the return value
-- | is `mempty`.
instance lookupArray :: Monoid.Monoid m => Lookup (Array m) m Int where instance lookupArray :: Monoid.Monoid m => Lookup (Array m) m Int where
lookup arr = Maybe.fromMaybe Monoid.mempty <<< Array.index arr lookup arr = Maybe.fromMaybe Monoid.mempty <<< Array.index arr
-- | A default instance of Lookup for a StrMap of some type of Monoid. If the -- | A default instance of `Lookup` for a `StrMap` of some type of `Monoid`. If
-- | key does not exist in the StrMap, then the return value is mempty. -- | the key does not exist in the `StrMap`, then the return value is `mempty`.
instance lookupStrMap :: Monoid.Monoid m => instance lookupStrMap :: Monoid.Monoid m =>
Lookup (StrMap.StrMap m) m String where Lookup (StrMap.StrMap m) m String where
lookup strMap = Maybe.fromMaybe Monoid.mempty <<< flip StrMap.lookup strMap lookup strMap = Maybe.fromMaybe Monoid.mempty <<< flip StrMap.lookup strMap

View File

@ -20,12 +20,12 @@ data Method
| Trace | Trace
| Patch | Patch
-- | If two Methods are the same constructor, they are equal. -- | If two `Methods` are the same constructor, they are equal.
derive instance generic :: Generic.Generic Method derive instance generic :: Generic.Generic Method
instance eq :: Eq.Eq Method where instance eq :: Eq.Eq Method where
eq = Generic.gEq eq = Generic.gEq
-- | Convert a constructor to a string. -- | Convert a constructor to a `String`.
instance show :: Show.Show Method where instance show :: Show.Show Method where
show Get = "Get" show Get = "Get"
show Post = "Post" show Post = "Post"
@ -37,7 +37,7 @@ instance show :: Show.Show Method where
show Trace = "Trace" show Trace = "Trace"
show Patch = "Patch" show Patch = "Patch"
-- | Take an HTTP Request and return the Method for that request. -- | Take an HTTP `Request` and extract the `Method` for that request.
read :: HTTP.Request -> Method read :: HTTP.Request -> Method
read request = case HTTP.requestMethod request of read request = case HTTP.requestMethod request of
"POST" -> Post "POST" -> Post

View File

@ -10,15 +10,15 @@ import Data.Maybe as Maybe
import Data.String as String import Data.String as String
import Node.HTTP as HTTP import Node.HTTP as HTTP
-- | The Path type is just sugar for an Array of String segments that are sent -- | The `Path` type is just sugar for an `Array` of `String` segments that are
-- | in a request and indicates the path of the resource being requested. Note -- | sent in a request and indicates the path of the resource being requested.
-- | that this type has an implementation of Lookup for `Int` keys defined by -- | Note that this type has an implementation of `Lookup` for `Int` keys
-- | `lookpArray` in `Lookup.purs` because `lookupArray` is defined for any -- | defined by `lookupArray` in [Lookup.purs](./Lookup.purs) because
-- | `Array` of `Monoids`. So you can do something like `path !! 2` to get the -- | `lookupArray` is defined for any `Array` of `Monoids`. So you can do
-- | path segment at index 2. -- | something like `path !! 2` to get the path segment at index 2.
type Path = Array String type Path = Array String
-- | Given an HTTP Request object, extract the Path. -- | Given an HTTP `Request` object, extract the `Path`.
read :: HTTP.Request -> Path read :: HTTP.Request -> Path
read = HTTP.requestURL >>> split "?" >>> first >>> split "/" >>> nonempty read = HTTP.requestURL >>> split "?" >>> first >>> split "/" >>> nonempty
where where

View File

@ -12,17 +12,17 @@ import Data.StrMap as StrMap
import Data.Tuple as Tuple import Data.Tuple as Tuple
import Node.HTTP as HTTP import Node.HTTP as HTTP
-- | The Query type is a StrMap of Strings, with one entry per query parameter -- | The `Query` type is a `StrMap` of `Strings`, with one entry per query
-- | in the request. For any query parameters that don't have values -- | parameter in the request. For any query parameters that don't have values
-- | (`/some/path?query`), the value in the StrMap for that parameter will be -- | (`/some/path?query`), the value in the `StrMap` for that parameter will be
-- | the string "true". Note that this type has an implementation of Lookup for -- | the string `"true"`. Note that this type has an implementation of `Lookup`
-- | `String` keys defined by `lookpStrMap` in `Lookup.purs` because -- | for `String` keys defined by `lookpStrMap` in `Lookup.purs` because
-- | `lookupStrMap` is defined for any `StrMap` of `Monoids`. So you can do -- | `lookupStrMap` is defined for any `StrMap` of `Monoids`. So you can do
-- | something like `query !! "foo"` to get the value of the query parameter -- | something like `query !! "foo"` to get the value of the query parameter
-- | "foo". -- | "foo".
type Query = StrMap.StrMap String type Query = StrMap.StrMap String
-- | The StrMap of query segments in the given HTTP Request. -- | The `StrMap` of query segments in the given HTTP `Request`.
read :: HTTP.Request -> Query read :: HTTP.Request -> Query
read = read =
HTTP.requestURL >>> split "?" >>> last >>> split "&" >>> nonempty >>> toStrMap HTTP.requestURL >>> split "?" >>> last >>> split "&" >>> nonempty >>> toStrMap

View File

@ -15,8 +15,8 @@ import HTTPure.Method as Method
import HTTPure.Path as Path import HTTPure.Path as Path
import HTTPure.Query as Query import HTTPure.Query as Query
-- | A Route is a function that takes a Method, a Path, a Query, a Header, and a -- | The `Request` type is a `Record` type that includes fields for accessing
-- | Body, and returns a Response monad. -- | the different parts of the HTTP request.
type Request = type Request =
{ method :: Method.Method { method :: Method.Method
, path :: Path.Path , path :: Path.Path
@ -25,8 +25,8 @@ type Request =
, body :: Body.Body , body :: Body.Body
} }
-- | Given an HTTP Request object, this method will convert it to an HTTPure -- | Given an HTTP `Request` object, this method will convert it to an HTTPure
-- | Request object. -- | `Request` object.
fromHTTPRequest :: forall e. fromHTTPRequest :: forall e.
HTTP.Request -> HTTP.Request ->
Aff.Aff (HTTPureM.HTTPureEffects e) Request Aff.Aff (HTTPureM.HTTPureEffects e) Request

View File

@ -84,17 +84,17 @@ import HTTPure.Headers as Headers
import HTTPure.HTTPureM as HTTPureM import HTTPure.HTTPureM as HTTPureM
import HTTPure.Status as Status import HTTPure.Status as Status
-- | The ResponseM type simply conveniently wraps up an HTTPure monad that -- | The `ResponseM` type simply conveniently wraps up an HTTPure monad that
-- | returns a response. This type is the return type of all router/route -- | returns a response. This type is the return type of all router/route
-- | methods. -- | methods.
type ResponseM e = HTTPureM.HTTPureM e Response type ResponseM e = HTTPureM.HTTPureM e Response
-- | A response is a status code, headers, and a body. -- | A `Response` is a status code, headers, and a body.
data Response = Response Status.Status Headers.Headers Body.Body data Response = Response Status.Status Headers.Headers Body.Body
-- | Given an HTTP response and a HTTPure response, this method will return a -- | Given an HTTP `Response` and a HTTPure `Response`, this method will return
-- | monad encapsulating writing the HTTPure response to the HTTP response and -- | a monad encapsulating writing the HTTPure `Response` to the HTTP `Response`
-- | closing the HTTP response. -- | and closing the HTTP `Response`.
send :: forall e. HTTP.Response -> Response -> HTTPureM.HTTPureM e Unit send :: forall e. HTTP.Response -> Response -> HTTPureM.HTTPureM e Unit
send httpresponse (Response status headers body) = do send httpresponse (Response status headers body) = do
Status.write httpresponse $ status Status.write httpresponse $ status

View File

@ -21,18 +21,19 @@ import HTTPure.HTTPureM as HTTPureM
import HTTPure.Request as Request import HTTPure.Request as Request
import HTTPure.Response as Response import HTTPure.Response as Response
-- | The ServerM type simply conveniently wraps up an HTTPure monad that -- | The `ServerM` type simply conveniently wraps up an HTTPure monad that
-- | returns a Unit. This type is the return type of the HTTPure serve and -- | returns a `Unit`. This type is the return type of the HTTPure serve and
-- | related methods. -- | related methods.
type ServerM e = HTTPureM.HTTPureM e Unit type ServerM e = HTTPureM.HTTPureM e Unit
-- | The SecureServerM type is the same as the ServerM type, but it includes -- | The `SecureServerM` type is the same as the `ServerM` type, but it includes
-- | effects for working with the filesystem (to load the key and certificate). -- | effects for working with the filesystem (to load the key and certificate).
type SecureServerM e = ServerM (fs :: FS.FS | e) type SecureServerM e = ServerM (fs :: FS.FS | e)
-- | This function takes a method which takes a request and returns a ResponseM, -- | This function takes a method which takes a `Request` and returns a
-- | an HTTP request, and an HTTP response. It runs the request, extracts the -- | `ResponseM`, an HTTP `Request`, and an HTTP `Response`. It runs the
-- | Response from the ResponseM, and sends the Response to the HTTP Response. -- | request, extracts the `Response` from the `ResponseM`, and sends the
-- | `Response` to the HTTP `Response`.
handleRequest :: forall e. handleRequest :: forall e.
(Request.Request -> Response.ResponseM e) -> (Request.Request -> Response.ResponseM e) ->
HTTP.Request -> HTTP.Request ->
@ -43,9 +44,9 @@ handleRequest router request response =
req <- Request.fromHTTPRequest request req <- Request.fromHTTPRequest request
EffClass.liftEff $ router req >>= Response.send response EffClass.liftEff $ router req >>= Response.send response
-- | Given a ListenOptions Record, a function mapping Request to ResponseM, and -- | Given a `ListenOptions` object, a function mapping `Request` to
-- | an HTTPureM containing effects to run on boot, creates and runs a HTTPure -- | `ResponseM`, and an `HTTPureM` containing effects to run on boot, creates
-- | server without SSL. -- | and runs a HTTPure server without SSL.
bootHTTP :: forall e. bootHTTP :: forall e.
HTTP.ListenOptions -> HTTP.ListenOptions ->
(Request.Request -> Response.ResponseM e) -> (Request.Request -> Response.ResponseM e) ->
@ -55,8 +56,8 @@ bootHTTP options router onStarted =
HTTP.createServer (handleRequest router) >>= \server -> HTTP.createServer (handleRequest router) >>= \server ->
HTTP.listen server options onStarted HTTP.listen server options onStarted
-- | Given a ListenOptions Record, a path to a cert file, a path to a private -- | Given a `ListenOptions` object, a path to a cert file, a path to a private
-- | key file, a function mapping Request to ResponseM, and an HTTPureM -- | key file, a function mapping `Request` to `ResponseM`, and an `HTTPureM`
-- | containing effects to run on boot, creates and runs a HTTPure server with -- | containing effects to run on boot, creates and runs a HTTPure server with
-- | SSL. -- | SSL.
bootHTTPS :: forall e. bootHTTPS :: forall e.
@ -76,7 +77,7 @@ bootHTTPS options cert key router onStarted = do
HTTPS.key := HTTPS.keyString key' <> HTTPS.key := HTTPS.keyString key' <>
HTTPS.cert := HTTPS.certString cert' HTTPS.cert := HTTPS.certString cert'
-- | Given a port number, return a HTTP.ListenOptions Record. -- | Given a port number, return a `HTTP.ListenOptions` `Record`.
listenOptions :: Int -> HTTP.ListenOptions listenOptions :: Int -> HTTP.ListenOptions
listenOptions port = listenOptions port =
{ hostname: "localhost" { hostname: "localhost"
@ -85,9 +86,10 @@ listenOptions port =
} }
-- | Create and start a server. This is the main entry point for HTTPure. Takes -- | Create and start a server. This is the main entry point for HTTPure. Takes
-- | a port number on which to listen, a function mapping Request to ResponseM, -- | a port number on which to listen, a function mapping `Request` to
-- | and an HTTPureM containing effects to run after the server has booted -- | `ResponseM`, and an `HTTPureM` containing effects to run after the server
-- | (usually logging). Returns an HTTPureM containing the server's effects. -- | has booted (usually logging). Returns an `HTTPureM` containing the server's
-- | effects.
serve :: forall e. serve :: forall e.
Int -> Int ->
(Request.Request -> Response.ResponseM e) -> (Request.Request -> Response.ResponseM e) ->
@ -100,7 +102,7 @@ serve = bootHTTP <<< listenOptions
-- | 1. A port number -- | 1. A port number
-- | 2. A path to a cert file -- | 2. A path to a cert file
-- | 3. A path to a private key file -- | 3. A path to a private key file
-- | 4. A handler method which maps Request to ResponseM -- | 4. A handler method which maps `Request` to `ResponseM`
-- | 5. A callback to call when the server is up -- | 5. A callback to call when the server is up
serve' :: forall e. serve' :: forall e.
Int -> Int ->

View File

@ -78,10 +78,10 @@ import Prelude
import Control.Monad.Eff as Eff import Control.Monad.Eff as Eff
import Node.HTTP as HTTP import Node.HTTP as HTTP
-- | The Status type enumerates all valid HTTP response status codes. -- | The `Status` type enumerates all valid HTTP response status codes.
type Status = Int type Status = Int
-- | Write a status to a given HTTP Response. -- | Write a status to a given HTTP `Response`.
write :: forall e. write :: forall e.
HTTP.Response -> HTTP.Response ->
Status -> Status ->