Add post example (#41)
This commit is contained in:
parent
4ca1378f7d
commit
b8169e4fdb
10
docs/Examples/Post/Example.md
Normal file
10
docs/Examples/Post/Example.md
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
# Post Example
|
||||||
|
|
||||||
|
This is a basic example of handling a Post. It will respond to a HTTP POST on
|
||||||
|
any path with the post body in the response body.
|
||||||
|
|
||||||
|
To run the example server, run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make example EXAMPLE=Post
|
||||||
|
```
|
31
docs/Examples/Post/Main.purs
Normal file
31
docs/Examples/Post/Main.purs
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
module Post where
|
||||||
|
|
||||||
|
import Prelude
|
||||||
|
|
||||||
|
import Control.Monad.Eff.Console as Console
|
||||||
|
import Data.StrMap as StrMap
|
||||||
|
import HTTPure as HTTPure
|
||||||
|
|
||||||
|
-- | Serve the example server on this port
|
||||||
|
port :: Int
|
||||||
|
port = 8084
|
||||||
|
|
||||||
|
-- | Shortcut for `show port`
|
||||||
|
portS :: String
|
||||||
|
portS = show port
|
||||||
|
|
||||||
|
-- | Route to the correct handler
|
||||||
|
router :: forall e. HTTPure.Request -> HTTPure.ResponseM e
|
||||||
|
router (HTTPure.Post _ _ body) = pure $ HTTPure.OK StrMap.empty body
|
||||||
|
router _ = pure $ HTTPure.OK StrMap.empty ""
|
||||||
|
|
||||||
|
-- | Boot up the server
|
||||||
|
main :: forall e. HTTPure.ServerM (console :: Console.CONSOLE | e)
|
||||||
|
main = HTTPure.serve port router do
|
||||||
|
Console.log $ " ┌───────────────────────────────────────────┐"
|
||||||
|
Console.log $ " │ Server now up on port " <> portS <> " │"
|
||||||
|
Console.log $ " │ │"
|
||||||
|
Console.log $ " │ To test, run: │"
|
||||||
|
Console.log $ " │ > curl -XPOST --data test localhost:" <> portS <> " │"
|
||||||
|
Console.log $ " │ # => test │"
|
||||||
|
Console.log $ " └───────────────────────────────────────────┘"
|
@ -3,37 +3,48 @@ module HTTPure.IntegrationSpec where
|
|||||||
import Prelude
|
import Prelude
|
||||||
|
|
||||||
import Control.Monad.Eff.Class as EffClass
|
import Control.Monad.Eff.Class as EffClass
|
||||||
|
import Data.StrMap as StrMap
|
||||||
import Test.Spec as Spec
|
import Test.Spec as Spec
|
||||||
import Test.Spec.Assertions as Assertions
|
import Test.Spec.Assertions as Assertions
|
||||||
|
|
||||||
import HTTPure.SpecHelpers as SpecHelpers
|
import HTTPure.SpecHelpers as SpecHelpers
|
||||||
|
|
||||||
|
import Headers as Headers
|
||||||
import HelloWorld as HelloWorld
|
import HelloWorld as HelloWorld
|
||||||
import MultiRoute as MultiRoute
|
import MultiRoute as MultiRoute
|
||||||
import Headers as Headers
|
import Post as Post
|
||||||
|
|
||||||
|
headersSpec :: SpecHelpers.Test
|
||||||
|
headersSpec = Spec.it "runs the headers example" do
|
||||||
|
EffClass.liftEff Headers.main
|
||||||
|
header <- SpecHelpers.getHeader 8082 StrMap.empty "/" "X-Example"
|
||||||
|
header `Assertions.shouldEqual` "hello world!"
|
||||||
|
response <- SpecHelpers.get 8082 (StrMap.singleton "X-Input" "test") "/"
|
||||||
|
response `Assertions.shouldEqual` "test"
|
||||||
|
|
||||||
helloWorldSpec :: SpecHelpers.Test
|
helloWorldSpec :: SpecHelpers.Test
|
||||||
helloWorldSpec = Spec.it "runs the hello world example" do
|
helloWorldSpec = Spec.it "runs the hello world example" do
|
||||||
EffClass.liftEff HelloWorld.main
|
EffClass.liftEff HelloWorld.main
|
||||||
response <- SpecHelpers.get "http://localhost:8080"
|
response <- SpecHelpers.get 8080 StrMap.empty "/"
|
||||||
response `Assertions.shouldEqual` "hello world!"
|
response `Assertions.shouldEqual` "hello world!"
|
||||||
|
|
||||||
multiRouteSpec :: SpecHelpers.Test
|
multiRouteSpec :: SpecHelpers.Test
|
||||||
multiRouteSpec = Spec.it "runs the multi route example" do
|
multiRouteSpec = Spec.it "runs the multi route example" do
|
||||||
EffClass.liftEff MultiRoute.main
|
EffClass.liftEff MultiRoute.main
|
||||||
hello <- SpecHelpers.get "http://localhost:8081/hello"
|
hello <- SpecHelpers.get 8081 StrMap.empty "/hello"
|
||||||
hello `Assertions.shouldEqual` "hello"
|
hello `Assertions.shouldEqual` "hello"
|
||||||
goodbye <- SpecHelpers.get "http://localhost:8081/goodbye"
|
goodbye <- SpecHelpers.get 8081 StrMap.empty "/goodbye"
|
||||||
goodbye `Assertions.shouldEqual` "goodbye"
|
goodbye `Assertions.shouldEqual` "goodbye"
|
||||||
|
|
||||||
headersSpec :: SpecHelpers.Test
|
postSpec :: SpecHelpers.Test
|
||||||
headersSpec = Spec.it "runs the headers example" do
|
postSpec = Spec.it "runs the post example" do
|
||||||
EffClass.liftEff Headers.main
|
EffClass.liftEff Post.main
|
||||||
header <- SpecHelpers.getHeader "http://localhost:8082" "X-Example"
|
response <- SpecHelpers.post 8084 StrMap.empty "/" "test"
|
||||||
header `Assertions.shouldEqual` "hello world!"
|
response `Assertions.shouldEqual` "test"
|
||||||
|
|
||||||
integrationSpec :: SpecHelpers.Test
|
integrationSpec :: SpecHelpers.Test
|
||||||
integrationSpec = Spec.describe "Integration" do
|
integrationSpec = Spec.describe "Integration" do
|
||||||
|
headersSpec
|
||||||
helloWorldSpec
|
helloWorldSpec
|
||||||
multiRouteSpec
|
multiRouteSpec
|
||||||
headersSpec
|
postSpec
|
||||||
|
@ -21,7 +21,7 @@ serveSpec :: SpecHelpers.Test
|
|||||||
serveSpec = Spec.describe "serve" do
|
serveSpec = Spec.describe "serve" do
|
||||||
Spec.it "boots a server on the given port" do
|
Spec.it "boots a server on the given port" do
|
||||||
EffClass.liftEff $ Server.serve 7901 mockRouter $ pure unit
|
EffClass.liftEff $ Server.serve 7901 mockRouter $ pure unit
|
||||||
out <- SpecHelpers.get "http://localhost:7901/test"
|
out <- SpecHelpers.get 7901 StrMap.empty "/test"
|
||||||
out `Assertions.shouldEqual` "/test"
|
out `Assertions.shouldEqual` "/test"
|
||||||
|
|
||||||
serverSpec :: SpecHelpers.Test
|
serverSpec :: SpecHelpers.Test
|
||||||
|
@ -7,6 +7,7 @@ import Control.Monad.Eff as Eff
|
|||||||
import Control.Monad.Eff.Exception as Exception
|
import Control.Monad.Eff.Exception as Exception
|
||||||
import Control.Monad.ST as ST
|
import Control.Monad.ST as ST
|
||||||
import Data.Maybe as Maybe
|
import Data.Maybe as Maybe
|
||||||
|
import Data.Options as Options
|
||||||
import Data.String as StringUtil
|
import Data.String as StringUtil
|
||||||
import Data.StrMap as StrMap
|
import Data.StrMap as StrMap
|
||||||
import Node.Encoding as Encoding
|
import Node.Encoding as Encoding
|
||||||
@ -40,19 +41,29 @@ type Test = Spec.Spec TestEffects Unit
|
|||||||
-- | The type for the entire test suite.
|
-- | The type for the entire test suite.
|
||||||
type TestSuite = Eff.Eff TestEffects Unit
|
type TestSuite = Eff.Eff TestEffects Unit
|
||||||
|
|
||||||
-- | Given an HTTPClient.Request, close the request stream so the request can be
|
|
||||||
-- | fired.
|
|
||||||
endRequest :: forall e.
|
|
||||||
HTTPClient.Request -> Eff.Eff (http :: HTTP.HTTP | e) Unit
|
|
||||||
endRequest request = Stream.end (HTTPClient.requestAsStream request) $ pure unit
|
|
||||||
|
|
||||||
-- | Given a URL, a failure handler, and a success handler, create an HTTP
|
-- | Given a URL, a failure handler, and a success handler, create an HTTP
|
||||||
-- | client request.
|
-- | client request.
|
||||||
getResponse :: forall e.
|
request :: forall e.
|
||||||
String ->
|
Int ->
|
||||||
Aff.Aff (http :: HTTP.HTTP | e) HTTPClient.Response
|
String ->
|
||||||
getResponse url = Aff.makeAff \_ success ->
|
StrMap.StrMap String ->
|
||||||
HTTPClient.requestFromURI url success >>= endRequest
|
String ->
|
||||||
|
String ->
|
||||||
|
Aff.Aff (http :: HTTP.HTTP | e) HTTPClient.Response
|
||||||
|
request port method headers path body = Aff.makeAff \_ success -> do
|
||||||
|
req <- HTTPClient.request options success
|
||||||
|
let stream = HTTPClient.requestAsStream req
|
||||||
|
_ <- Stream.writeString stream Encoding.UTF8 body noop
|
||||||
|
Stream.end stream noop
|
||||||
|
noop
|
||||||
|
where
|
||||||
|
noop = pure unit
|
||||||
|
options =
|
||||||
|
HTTPClient.method `Options.assoc` method <>
|
||||||
|
HTTPClient.hostname `Options.assoc` "localhost" <>
|
||||||
|
HTTPClient.port `Options.assoc` port <>
|
||||||
|
HTTPClient.path `Options.assoc` path <>
|
||||||
|
HTTPClient.headers `Options.assoc` HTTPClient.RequestHeaders headers
|
||||||
|
|
||||||
-- | Given an ST String buffer and a new string, concatenate that new string
|
-- | Given an ST String buffer and a new string, concatenate that new string
|
||||||
-- | onto the ST buffer.
|
-- | onto the ST buffer.
|
||||||
@ -71,8 +82,22 @@ toString response = Aff.makeAff \_ success -> do
|
|||||||
|
|
||||||
-- | Run an HTTP GET with the given url and return an Aff that contains the
|
-- | Run an HTTP GET with the given url and return an Aff that contains the
|
||||||
-- | string with the response body.
|
-- | string with the response body.
|
||||||
get :: forall e. String -> Aff.Aff (HTTPRequestEffects e) String
|
get :: forall e.
|
||||||
get url = getResponse url >>= toString
|
Int ->
|
||||||
|
StrMap.StrMap String ->
|
||||||
|
String ->
|
||||||
|
Aff.Aff (HTTPRequestEffects e) String
|
||||||
|
get port headers path = request port "GET" headers path "" >>= toString
|
||||||
|
|
||||||
|
-- | Run an HTTP POST with the given url and body and return an Aff that
|
||||||
|
-- | contains the string with the response body.
|
||||||
|
post :: forall e.
|
||||||
|
Int ->
|
||||||
|
StrMap.StrMap String ->
|
||||||
|
String ->
|
||||||
|
String ->
|
||||||
|
Aff.Aff (HTTPRequestEffects e) String
|
||||||
|
post port headers path body = request port "POST" headers path body >>= toString
|
||||||
|
|
||||||
-- | Convert a request to an Aff containing the string with the given header
|
-- | Convert a request to an Aff containing the string with the given header
|
||||||
-- | value.
|
-- | value.
|
||||||
@ -85,10 +110,13 @@ extractHeader header = unmaybe <<< lookup <<< HTTPClient.responseHeaders
|
|||||||
-- | Run an HTTP GET with the given url and return an Aff that contains the
|
-- | Run an HTTP GET with the given url and return an Aff that contains the
|
||||||
-- | string with the header value for the given header.
|
-- | string with the header value for the given header.
|
||||||
getHeader :: forall e.
|
getHeader :: forall e.
|
||||||
|
Int ->
|
||||||
|
StrMap.StrMap String ->
|
||||||
String ->
|
String ->
|
||||||
String ->
|
String ->
|
||||||
Aff.Aff (HTTPRequestEffects e) String
|
Aff.Aff (HTTPRequestEffects e) String
|
||||||
getHeader url header = extractHeader header <$> getResponse url
|
getHeader port headers path header =
|
||||||
|
extractHeader header <$> request port "GET" headers path ""
|
||||||
|
|
||||||
-- | An effect encapsulating creating a mock request object
|
-- | An effect encapsulating creating a mock request object
|
||||||
foreign import data MOCK_REQUEST :: Eff.Effect
|
foreign import data MOCK_REQUEST :: Eff.Effect
|
||||||
|
Loading…
Reference in New Issue
Block a user