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

View File

@ -7,14 +7,24 @@
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
This project is currently an early-stage work in progress. It is not
production-ready yet. You can track what's left before it gets production-ready
by looking at
our [roadmap](https://github.com/cprussin/purescript-httpure/projects). If you'd
like to help us get there quicker, please contribute! To get started, check
our [contributing guide](Contributing.md).
This project is currently fairly stable, but has not reached it's 1.0 release
yet. You can track what's left before it gets there by looking at our
[roadmap](https://github.com/cprussin/purescript-httpure/projects). The API
signatures are _mostly_ stable, but are subject to change before the 1.0 release
if there's a good reason to change them.
If you'd like to help us get to 1.0 quicker, please contribute! To get started,
check our [contributing guide](Contributing.md).
## Installation
@ -27,10 +37,9 @@ bower install --save purescript-httpure
```purescript
module Main where
import Prelude (pure, ($))
import Prelude (($))
import Control.Monad.Eff.Console as Console
import Data.StrMap as StrMap
import HTTPure as HTTPure
main :: HTTPure.ServerM (console :: Console.CONSOLE)

View File

@ -15,11 +15,11 @@ import Node.Stream as Stream
import HTTPure.HTTPureM as HTTPureM
-- | The Body type is just sugar for a String, that will be sent or received in
-- | the HTTP body.
-- | The `Body` type is just sugar for a `String`, that will be sent or received
-- | in the HTTP body.
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 request = Aff.makeAff \_ success -> do
let stream = HTTP.requestAsStream request
@ -28,7 +28,7 @@ read request = Aff.makeAff \_ success -> do
void $ ST.modifySTRef buf ((<>) str)
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 response body = void do
_ <- Stream.writeString stream Encoding.UTF8 body $ pure unit

View File

@ -17,33 +17,34 @@ import Node.HTTP as HTTP
import HTTPure.Lookup as Lookup
-- | The Headers type is just sugar for a StrMap of Strings that represents the
-- | set of headers sent or received in an HTTP request or response.
-- | The `Headers` type is just sugar for a `StrMap` of `Strings` that
-- | represents the set of headers in an HTTP request or response.
newtype Headers = Headers (StrMap.StrMap String)
-- | Given a string, return the matching headers. This search is
-- | case-insensitive.
-- | Given a string, return the value of the matching header, or an empty string
-- | if no match exists. This search is case-insensitive.
instance lookupHeaders :: Lookup.Lookup Headers String String where
lookup (Headers headers') =
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
show (Headers headers') =
StrMap.foldMap showField headers' <> "\n"
where
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
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.requestHeaders >>> Headers
-- | Given an HTTP Response and a Headers object, return an effect that will
-- | write the Headers to the Response.
-- | Given an HTTP `Response` and a `Headers` object, return an effect that will
-- | write the `Headers` to the `Response`.
write :: forall e.
HTTP.Response ->
Headers ->
@ -51,6 +52,6 @@ write :: forall e.
write response (Headers headers') = void $
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 = StrMap.fromFoldable >>> Headers

View File

@ -10,24 +10,33 @@ import Data.Maybe as Maybe
import Data.Monoid as Monoid
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
-- | String (Maybe String) Int where `lookup string index` returns `Just` the
-- | character in `string` at `index`, or `Nothing` if `index` is out of bounds.
-- | `String (Maybe String) Int` where `lookup s i` returns `Just` the
-- | character in `s` at `i`, or `Nothing` if `i` is out of bounds.
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
-- | !! 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 !!
-- | A default instance of Lookup for an Array of some type of Monoid. Note that
-- | this is different from `!!` defined in `Data.Array` in that it does not
-- | return a Maybe. If the index is out of bounds, the return value is mempty.
-- | A default instance of `Lookup` for an `Array` of some type of `Monoid`.
-- | Note that this is different from `!!` defined in `Data.Array` in that it
-- | 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
lookup arr = Maybe.fromMaybe Monoid.mempty <<< Array.index arr
-- | A default instance of Lookup for a StrMap of some type of Monoid. If the
-- | key does not exist in the StrMap, then the return value is mempty.
-- | A default instance of `Lookup` for a `StrMap` of some type of `Monoid`. If
-- | the key does not exist in the `StrMap`, then the return value is `mempty`.
instance lookupStrMap :: Monoid.Monoid m =>
Lookup (StrMap.StrMap m) m String where
lookup strMap = Maybe.fromMaybe Monoid.mempty <<< flip StrMap.lookup strMap

View File

@ -20,12 +20,12 @@ data Method
| Trace
| 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
instance eq :: Eq.Eq Method where
eq = Generic.gEq
-- | Convert a constructor to a string.
-- | Convert a constructor to a `String`.
instance show :: Show.Show Method where
show Get = "Get"
show Post = "Post"
@ -37,7 +37,7 @@ instance show :: Show.Show Method where
show Trace = "Trace"
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 request = case HTTP.requestMethod request of
"POST" -> Post

View File

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

View File

@ -12,17 +12,17 @@ import Data.StrMap as StrMap
import Data.Tuple as Tuple
import Node.HTTP as HTTP
-- | The Query type is a StrMap of Strings, with one entry per query 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
-- | the string "true". Note that this type has an implementation of Lookup for
-- | `String` keys defined by `lookpStrMap` in `Lookup.purs` because
-- | The `Query` type is a `StrMap` of `Strings`, with one entry per query
-- | 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
-- | the string `"true"`. Note that this type has an implementation of `Lookup`
-- | for `String` keys defined by `lookpStrMap` in `Lookup.purs` because
-- | `lookupStrMap` is defined for any `StrMap` of `Monoids`. So you can do
-- | something like `query !! "foo"` to get the value of the query parameter
-- | "foo".
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.requestURL >>> split "?" >>> last >>> split "&" >>> nonempty >>> toStrMap

View File

@ -15,8 +15,8 @@ import HTTPure.Method as Method
import HTTPure.Path as Path
import HTTPure.Query as Query
-- | A Route is a function that takes a Method, a Path, a Query, a Header, and a
-- | Body, and returns a Response monad.
-- | The `Request` type is a `Record` type that includes fields for accessing
-- | the different parts of the HTTP request.
type Request =
{ method :: Method.Method
, path :: Path.Path
@ -25,8 +25,8 @@ type Request =
, body :: Body.Body
}
-- | Given an HTTP Request object, this method will convert it to an HTTPure
-- | Request object.
-- | Given an HTTP `Request` object, this method will convert it to an HTTPure
-- | `Request` object.
fromHTTPRequest :: forall e.
HTTP.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.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
-- | methods.
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
-- | Given an HTTP response and a HTTPure response, this method will return a
-- | monad encapsulating writing the HTTPure response to the HTTP response and
-- | closing the HTTP response.
-- | Given an HTTP `Response` and a HTTPure `Response`, this method will return
-- | a monad encapsulating writing the HTTPure `Response` to the HTTP `Response`
-- | and closing the HTTP `Response`.
send :: forall e. HTTP.Response -> Response -> HTTPureM.HTTPureM e Unit
send httpresponse (Response status headers body) = do
Status.write httpresponse $ status

View File

@ -21,18 +21,19 @@ import HTTPure.HTTPureM as HTTPureM
import HTTPure.Request as Request
import HTTPure.Response as Response
-- | 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
-- | 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
-- | related methods.
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).
type SecureServerM e = ServerM (fs :: FS.FS | e)
-- | This function takes a method which takes a request and returns a ResponseM,
-- | an HTTP request, and an HTTP response. It runs the request, extracts the
-- | Response from the ResponseM, and sends the Response to the HTTP Response.
-- | This function takes a method which takes a `Request` and returns a
-- | `ResponseM`, an HTTP `Request`, and an HTTP `Response`. It runs the
-- | request, extracts the `Response` from the `ResponseM`, and sends the
-- | `Response` to the HTTP `Response`.
handleRequest :: forall e.
(Request.Request -> Response.ResponseM e) ->
HTTP.Request ->
@ -43,9 +44,9 @@ handleRequest router request response =
req <- Request.fromHTTPRequest request
EffClass.liftEff $ router req >>= Response.send response
-- | Given a ListenOptions Record, a function mapping Request to ResponseM, and
-- | an HTTPureM containing effects to run on boot, creates and runs a HTTPure
-- | server without SSL.
-- | Given a `ListenOptions` object, a function mapping `Request` to
-- | `ResponseM`, and an `HTTPureM` containing effects to run on boot, creates
-- | and runs a HTTPure server without SSL.
bootHTTP :: forall e.
HTTP.ListenOptions ->
(Request.Request -> Response.ResponseM e) ->
@ -55,8 +56,8 @@ bootHTTP options router onStarted =
HTTP.createServer (handleRequest router) >>= \server ->
HTTP.listen server options onStarted
-- | Given a ListenOptions Record, a path to a cert file, a path to a private
-- | key file, a function mapping Request to ResponseM, and an HTTPureM
-- | 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`
-- | containing effects to run on boot, creates and runs a HTTPure server with
-- | SSL.
bootHTTPS :: forall e.
@ -76,7 +77,7 @@ bootHTTPS options cert key router onStarted = do
HTTPS.key := HTTPS.keyString key' <>
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 port =
{ hostname: "localhost"
@ -85,9 +86,10 @@ listenOptions port =
}
-- | 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,
-- | and an HTTPureM containing effects to run after the server has booted
-- | (usually logging). Returns an HTTPureM containing the server's effects.
-- | a port number on which to listen, a function mapping `Request` to
-- | `ResponseM`, and an `HTTPureM` containing effects to run after the server
-- | has booted (usually logging). Returns an `HTTPureM` containing the server's
-- | effects.
serve :: forall e.
Int ->
(Request.Request -> Response.ResponseM e) ->
@ -100,7 +102,7 @@ serve = bootHTTP <<< listenOptions
-- | 1. A port number
-- | 2. A path to a cert 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
serve' :: forall e.
Int ->

View File

@ -78,10 +78,10 @@ import Prelude
import Control.Monad.Eff as Eff
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
-- | Write a status to a given HTTP Response.
-- | Write a status to a given HTTP `Response`.
write :: forall e.
HTTP.Response ->
Status ->