mirror of
https://github.com/monadicsystems/okapi.git
synced 2024-11-23 09:54:24 +03:00
Add more documentation
This commit is contained in:
parent
130fb42b83
commit
c1096e386e
125
docs/index.md
125
docs/index.md
@ -403,7 +403,7 @@ apiSpec = genOpenAPISpec myServer
|
||||
|
||||
In the future, you should be able to automatically generate API clients as well.
|
||||
|
||||
### Not Using A Plan
|
||||
#### Not Using A Plan
|
||||
|
||||
You can also create Servers with out first creating Plans. If you want to do this, you can just use the `buildWith` function directly.
|
||||
|
||||
@ -439,8 +439,131 @@ myServer = Server
|
||||
|
||||
## Matchpoint
|
||||
|
||||
A *Matchpoint* is a *pattern* that matches on `Request` values.
|
||||
|
||||
```haskell
|
||||
pattern Matchpoint :: Request -> Matchpoint
|
||||
```
|
||||
|
||||
You can use the Matchpoint pattern synonym to create your own pattern synonyms that match specific Requests.
|
||||
|
||||
```haskell
|
||||
newtype UserID = UserID Int
|
||||
deriving ({- various typeclasses -})
|
||||
|
||||
pattern GetUserByID :: UserID -> Request
|
||||
pattern GetUserByID userID <- Matchpoint
|
||||
GET
|
||||
["users", PathParam @UserID userID]
|
||||
_
|
||||
_
|
||||
_
|
||||
```
|
||||
|
||||
The `GetUserByID` pattern defined above would match against any Request of the form `GET /users/{userID : UserID}`. The Handler on the RHS of this pattern in a case statement will then be able to use the `userID` parameter in it's function body if the Request matches sucessfully. If not, the next Matchpoint in your case statement is checked, just like regular patterns that we use all the time.
|
||||
|
||||
`PathParam` is a pattern synonym that you can use with in your Matchpoints to match against path parameters of any type that is an instance of both `ToHttpApiData` and `FromHttpApiData`. This is required since `PathParam` is a *bidirectional pattern synonym*. This property of `PathParam` makes it useful for generating URLs.
|
||||
|
||||
If our matching logic is more complicated, pattern synonyms alone may not be enough. For more complicated routes, we can use Okapi's DSL inside our Matchpoints by using `-XViewPatterns`. As an example, let's reimplement the first Endpoint on this page as a Matchpoint. Here's the Endpoint version first:
|
||||
|
||||
```haskell
|
||||
-- | Define Endpoints using an Applicative eDSL
|
||||
myEndpoint = Endpoint
|
||||
GET
|
||||
do
|
||||
Path.static "index"
|
||||
magicNumber <- Path.param @Int
|
||||
pure magicNumber
|
||||
do
|
||||
x <- Query.param @Int "x"
|
||||
y <- Query.option 10 $ Query.param @Int "y"
|
||||
pure (x, y)
|
||||
do
|
||||
foo <- Body.json @Value
|
||||
pure foo
|
||||
do pure ()
|
||||
do
|
||||
itsOk <- Responder.json @Int status200 do
|
||||
addSecretNumber <- AddHeader.using @Int "X-SECRET"
|
||||
pure addSecretNumber
|
||||
pure itsOk
|
||||
```
|
||||
|
||||
Here's the equivalent Matchpoint version:
|
||||
|
||||
```haskell
|
||||
pattern MyMatchpoint magicNumber pair foo = Matchpoint
|
||||
GET
|
||||
(Path.eval $ Path.static "index" *> Path.param @Int -> Ok magicNumber)
|
||||
(Query.eval xyQuery -> Ok pair)
|
||||
(Body.eval $ Body.json @Value -> Ok foo)
|
||||
__
|
||||
|
||||
xyQuery = do
|
||||
x <- Query.param @Int "x"
|
||||
y <- Query.option 10 $ Query.param @Int "y"
|
||||
pure (x, y)
|
||||
```
|
||||
|
||||
We can simplify `MyMatchpoint` further by using more pattern synonyms:
|
||||
|
||||
```haskell
|
||||
pattern MyMatchpoint magicNumber pair foo <- Matchpoint
|
||||
GET
|
||||
(Path.eval $ Path.static "index" *> Path.param @Int -> Ok magicNumber)
|
||||
(XYQuery pair)
|
||||
(Body.eval $ Body.json @Value -> Ok foo)
|
||||
__
|
||||
|
||||
pattern XYQuery pair <- (Query.eval xyQuery -> Ok pair)
|
||||
|
||||
xyQuery = do
|
||||
x <- Query.param @Int "x"
|
||||
y <- Query.option 10 $ Query.param @Int "y"
|
||||
pure (x, y)
|
||||
```
|
||||
|
||||
Custom patterns like `XYQuery` in the example above come in handy when we need to use the same pattern inside multiple Matchpoints.
|
||||
|
||||
You would use the Matchpoint we defined above like so (using `-XLambdaCase`):
|
||||
|
||||
```haskell
|
||||
type Server m = Request -> m Response
|
||||
|
||||
myServer :: Server IO
|
||||
myServer = \case
|
||||
MyMatchpoint n (x, y) foo -> do
|
||||
...
|
||||
_ -> do
|
||||
...
|
||||
|
||||
instantiate :: Monad m => (m ~> IO) -> Server m -> Application
|
||||
instantiate transformer server = ...
|
||||
|
||||
api :: Application
|
||||
api = instantiate id myServer
|
||||
```
|
||||
|
||||
You'll notice the Server type for Matchpoints is much simpler than the Server type for Endpoints.
|
||||
|
||||
### Matchpoints vs. Endpoints
|
||||
|
||||
We recommend using Endpoints. Matchpoints are great if you're not worried about safety and just want to get something up and running quickly. Here are some downsides to using Matchpoints to implement your Server:
|
||||
|
||||
1. Can't do any static analysis. This means you can't generate OpenAPI specifications for Servers that use Matchpoints or perform any optimizations. You can perform static analysis on the Scripts that you use in your Matchpoints, if any.
|
||||
|
||||
2. All handlers in a Matchpoint Server must operate within the same context. For Endpoints, this is not the case.
|
||||
|
||||
3. Endpoints are more modular. You can achieve some level of moduarity with your Matchpoints by using nested `-XPatternSynonyms` though.
|
||||
|
||||
4. Matchpoint Servers have no knowledge of what Responses you will return to the Client. Endpoint Servers know every possible Response you may return from your Handlers, besides ones caused by `IO` errors (the goal is for Endpoints to know about these as well).
|
||||
|
||||
In short, if you don't care about safety, use Matchpoints.
|
||||
|
||||
## Servant <> Okapi
|
||||
|
||||
Coming Soon
|
||||
|
||||
<!-- ## TLDR
|
||||
|
||||
or even
|
||||
|
@ -401,7 +401,7 @@ class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb16-1"><a
|
||||
<span id="cb16-8"><a href="#cb16-8" aria-hidden="true" tabindex="-1"></a>apiSpec <span class="ot">=</span> genOpenAPISpec myServer</span></code></pre></div>
|
||||
<p>In the future, you should be able to automatically generate API
|
||||
clients as well.</p>
|
||||
<h3>Not Using A Plan</h3>
|
||||
<h4>Not Using A Plan</h4>
|
||||
<p>You can also create Servers with out first creating Plans. If you
|
||||
want to do this, you can just use the <code>buildWith</code> function
|
||||
directly.</p>
|
||||
@ -432,7 +432,137 @@ class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb18-1"><a
|
||||
<span id="cb18-11"><a href="#cb18-11" aria-hidden="true" tabindex="-1"></a> <span class="op">...</span></span>
|
||||
<span id="cb18-12"><a href="#cb18-12" aria-hidden="true" tabindex="-1"></a> ]</span></code></pre></div>
|
||||
<h2 id="matchpoint">Matchpoint</h2>
|
||||
<p>A <em>Matchpoint</em> is a <em>pattern</em> that matches on
|
||||
<code>Request</code> values.</p>
|
||||
<div class="sourceCode" id="cb19"><pre
|
||||
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a><span class="kw">pattern</span> <span class="dt">Matchpoint</span><span class="ot"> ::</span> <span class="dt">Request</span> <span class="ot">-></span> <span class="dt">Matchpoint</span></span></code></pre></div>
|
||||
<p>You can use the Matchpoint pattern synonym to create your own pattern
|
||||
synonyms that match specific Requests.</p>
|
||||
<div class="sourceCode" id="cb20"><pre
|
||||
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a><span class="kw">newtype</span> <span class="dt">UserID</span> <span class="ot">=</span> <span class="dt">UserID</span> <span class="dt">Int</span></span>
|
||||
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a> <span class="kw">deriving</span> (<span class="co">{- various typeclasses -}</span>)</span>
|
||||
<span id="cb20-3"><a href="#cb20-3" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb20-4"><a href="#cb20-4" aria-hidden="true" tabindex="-1"></a><span class="kw">pattern</span> <span class="dt">GetUserByID</span><span class="ot"> ::</span> <span class="dt">UserID</span> <span class="ot">-></span> <span class="dt">Request</span></span>
|
||||
<span id="cb20-5"><a href="#cb20-5" aria-hidden="true" tabindex="-1"></a><span class="kw">pattern</span> <span class="dt">GetUserByID</span> userID <span class="ot"><-</span> <span class="dt">Matchpoint</span></span>
|
||||
<span id="cb20-6"><a href="#cb20-6" aria-hidden="true" tabindex="-1"></a> <span class="dt">GET</span></span>
|
||||
<span id="cb20-7"><a href="#cb20-7" aria-hidden="true" tabindex="-1"></a> [<span class="st">"users"</span>, <span class="dt">PathParam</span> <span class="op">@</span><span class="dt">UserID</span> userID]</span>
|
||||
<span id="cb20-8"><a href="#cb20-8" aria-hidden="true" tabindex="-1"></a> _</span>
|
||||
<span id="cb20-9"><a href="#cb20-9" aria-hidden="true" tabindex="-1"></a> _</span>
|
||||
<span id="cb20-10"><a href="#cb20-10" aria-hidden="true" tabindex="-1"></a> _</span></code></pre></div>
|
||||
<p>The <code>GetUserByID</code> pattern defined above would match
|
||||
against any Request of the form
|
||||
<code>GET /users/{userID : UserID}</code>. The Handler on the RHS of
|
||||
this pattern in a case statement will then be able to use the
|
||||
<code>userID</code> parameter in it's function body if the Request
|
||||
matches sucessfully. If not, the next Matchpoint in your case statement
|
||||
is checked, just like regular patterns that we use all the time.</p>
|
||||
<p><code>PathParam</code> is a pattern synonym that you can use with in
|
||||
your Matchpoints to match against path parameters of any type that is an
|
||||
instance of both <code>ToHttpApiData</code> and
|
||||
<code>FromHttpApiData</code>. This is required since
|
||||
<code>PathParam</code> is a <em>bidirectional pattern synonym</em>. This
|
||||
property of <code>PathParam</code> makes it useful for generating
|
||||
URLs.</p>
|
||||
<p>If our matching logic is more complicated, pattern synonyms alone may
|
||||
not be enough. For more complicated routes, we can use Okapi's DSL
|
||||
inside our Matchpoints by using <code>-XViewPatterns</code>. As an
|
||||
example, let's reimplement the first Endpoint on this page as a
|
||||
Matchpoint. Here's the Endpoint version first:</p>
|
||||
<div class="sourceCode" id="cb21"><pre
|
||||
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- | Define Endpoints using an Applicative eDSL</span></span>
|
||||
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a>myEndpoint <span class="ot">=</span> <span class="dt">Endpoint</span></span>
|
||||
<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a> <span class="dt">GET</span></span>
|
||||
<span id="cb21-4"><a href="#cb21-4" aria-hidden="true" tabindex="-1"></a> <span class="kw">do</span></span>
|
||||
<span id="cb21-5"><a href="#cb21-5" aria-hidden="true" tabindex="-1"></a> Path.static <span class="st">"index"</span></span>
|
||||
<span id="cb21-6"><a href="#cb21-6" aria-hidden="true" tabindex="-1"></a> magicNumber <span class="ot"><-</span> Path.param <span class="op">@</span><span class="dt">Int</span></span>
|
||||
<span id="cb21-7"><a href="#cb21-7" aria-hidden="true" tabindex="-1"></a> <span class="fu">pure</span> magicNumber</span>
|
||||
<span id="cb21-8"><a href="#cb21-8" aria-hidden="true" tabindex="-1"></a> <span class="kw">do</span></span>
|
||||
<span id="cb21-9"><a href="#cb21-9" aria-hidden="true" tabindex="-1"></a> x <span class="ot"><-</span> Query.param <span class="op">@</span><span class="dt">Int</span> <span class="st">"x"</span></span>
|
||||
<span id="cb21-10"><a href="#cb21-10" aria-hidden="true" tabindex="-1"></a> y <span class="ot"><-</span> Query.option <span class="dv">10</span> <span class="op">$</span> Query.param <span class="op">@</span><span class="dt">Int</span> <span class="st">"y"</span></span>
|
||||
<span id="cb21-11"><a href="#cb21-11" aria-hidden="true" tabindex="-1"></a> <span class="fu">pure</span> (x, y)</span>
|
||||
<span id="cb21-12"><a href="#cb21-12" aria-hidden="true" tabindex="-1"></a> <span class="kw">do</span></span>
|
||||
<span id="cb21-13"><a href="#cb21-13" aria-hidden="true" tabindex="-1"></a> foo <span class="ot"><-</span> Body.json <span class="op">@</span><span class="dt">Value</span></span>
|
||||
<span id="cb21-14"><a href="#cb21-14" aria-hidden="true" tabindex="-1"></a> <span class="fu">pure</span> foo</span>
|
||||
<span id="cb21-15"><a href="#cb21-15" aria-hidden="true" tabindex="-1"></a> <span class="kw">do</span> <span class="fu">pure</span> ()</span>
|
||||
<span id="cb21-16"><a href="#cb21-16" aria-hidden="true" tabindex="-1"></a> <span class="kw">do</span></span>
|
||||
<span id="cb21-17"><a href="#cb21-17" aria-hidden="true" tabindex="-1"></a> itsOk <span class="ot"><-</span> Responder.json <span class="op">@</span><span class="dt">Int</span> status200 <span class="kw">do</span></span>
|
||||
<span id="cb21-18"><a href="#cb21-18" aria-hidden="true" tabindex="-1"></a> addSecretNumber <span class="ot"><-</span> AddHeader.using <span class="op">@</span><span class="dt">Int</span> <span class="st">"X-SECRET"</span></span>
|
||||
<span id="cb21-19"><a href="#cb21-19" aria-hidden="true" tabindex="-1"></a> <span class="fu">pure</span> addSecretNumber</span>
|
||||
<span id="cb21-20"><a href="#cb21-20" aria-hidden="true" tabindex="-1"></a> <span class="fu">pure</span> itsOk</span></code></pre></div>
|
||||
<p>Here's the equivalent Matchpoint version:</p>
|
||||
<div class="sourceCode" id="cb22"><pre
|
||||
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a><span class="kw">pattern</span> <span class="dt">MyMatchpoint</span> magicNumber pair foo <span class="ot">=</span> <span class="dt">Matchpoint</span></span>
|
||||
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a> <span class="dt">GET</span></span>
|
||||
<span id="cb22-3"><a href="#cb22-3" aria-hidden="true" tabindex="-1"></a> (Path.eval <span class="op">$</span> Path.static <span class="st">"index"</span> <span class="op">*></span> Path.param <span class="op">@</span><span class="dt">Int</span> <span class="ot">-></span> <span class="dt">Ok</span> magicNumber)</span>
|
||||
<span id="cb22-4"><a href="#cb22-4" aria-hidden="true" tabindex="-1"></a> (Query.eval xyQuery <span class="ot">-></span> <span class="dt">Ok</span> pair)</span>
|
||||
<span id="cb22-5"><a href="#cb22-5" aria-hidden="true" tabindex="-1"></a> (Body.eval <span class="op">$</span> Body.json <span class="op">@</span><span class="dt">Value</span> <span class="ot">-></span> <span class="dt">Ok</span> foo)</span>
|
||||
<span id="cb22-6"><a href="#cb22-6" aria-hidden="true" tabindex="-1"></a> __</span>
|
||||
<span id="cb22-7"><a href="#cb22-7" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb22-8"><a href="#cb22-8" aria-hidden="true" tabindex="-1"></a>xyQuery <span class="ot">=</span> <span class="kw">do</span></span>
|
||||
<span id="cb22-9"><a href="#cb22-9" aria-hidden="true" tabindex="-1"></a> x <span class="ot"><-</span> Query.param <span class="op">@</span><span class="dt">Int</span> <span class="st">"x"</span></span>
|
||||
<span id="cb22-10"><a href="#cb22-10" aria-hidden="true" tabindex="-1"></a> y <span class="ot"><-</span> Query.option <span class="dv">10</span> <span class="op">$</span> Query.param <span class="op">@</span><span class="dt">Int</span> <span class="st">"y"</span></span>
|
||||
<span id="cb22-11"><a href="#cb22-11" aria-hidden="true" tabindex="-1"></a> <span class="fu">pure</span> (x, y)</span></code></pre></div>
|
||||
<p>We can simplify <code>MyMatchpoint</code> further by using more
|
||||
pattern synonyms:</p>
|
||||
<div class="sourceCode" id="cb23"><pre
|
||||
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a><span class="kw">pattern</span> <span class="dt">MyMatchpoint</span> magicNumber pair foo <span class="ot"><-</span> <span class="dt">Matchpoint</span></span>
|
||||
<span id="cb23-2"><a href="#cb23-2" aria-hidden="true" tabindex="-1"></a> <span class="dt">GET</span></span>
|
||||
<span id="cb23-3"><a href="#cb23-3" aria-hidden="true" tabindex="-1"></a> (Path.eval <span class="op">$</span> Path.static <span class="st">"index"</span> <span class="op">*></span> Path.param <span class="op">@</span><span class="dt">Int</span> <span class="ot">-></span> <span class="dt">Ok</span> magicNumber)</span>
|
||||
<span id="cb23-4"><a href="#cb23-4" aria-hidden="true" tabindex="-1"></a> (<span class="dt">XYQuery</span> pair)</span>
|
||||
<span id="cb23-5"><a href="#cb23-5" aria-hidden="true" tabindex="-1"></a> (Body.eval <span class="op">$</span> Body.json <span class="op">@</span><span class="dt">Value</span> <span class="ot">-></span> <span class="dt">Ok</span> foo)</span>
|
||||
<span id="cb23-6"><a href="#cb23-6" aria-hidden="true" tabindex="-1"></a> __</span>
|
||||
<span id="cb23-7"><a href="#cb23-7" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb23-8"><a href="#cb23-8" aria-hidden="true" tabindex="-1"></a><span class="kw">pattern</span> <span class="dt">XYQuery</span> pair <span class="ot"><-</span> (Query.eval xyQuery <span class="ot">-></span> <span class="dt">Ok</span> pair)</span>
|
||||
<span id="cb23-9"><a href="#cb23-9" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb23-10"><a href="#cb23-10" aria-hidden="true" tabindex="-1"></a>xyQuery <span class="ot">=</span> <span class="kw">do</span></span>
|
||||
<span id="cb23-11"><a href="#cb23-11" aria-hidden="true" tabindex="-1"></a> x <span class="ot"><-</span> Query.param <span class="op">@</span><span class="dt">Int</span> <span class="st">"x"</span></span>
|
||||
<span id="cb23-12"><a href="#cb23-12" aria-hidden="true" tabindex="-1"></a> y <span class="ot"><-</span> Query.option <span class="dv">10</span> <span class="op">$</span> Query.param <span class="op">@</span><span class="dt">Int</span> <span class="st">"y"</span></span>
|
||||
<span id="cb23-13"><a href="#cb23-13" aria-hidden="true" tabindex="-1"></a> <span class="fu">pure</span> (x, y)</span></code></pre></div>
|
||||
<p>Custom patterns like <code>XYQuery</code> in the example above come
|
||||
in handy when we need to use the same pattern inside multiple
|
||||
Matchpoints.</p>
|
||||
<p>You would use the Matchpoint we defined above like so (using
|
||||
<code>-XLambdaCase</code>):</p>
|
||||
<div class="sourceCode" id="cb24"><pre
|
||||
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> <span class="dt">Server</span> m <span class="ot">=</span> <span class="dt">Request</span> <span class="ot">-></span> m <span class="dt">Response</span></span>
|
||||
<span id="cb24-2"><a href="#cb24-2" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb24-3"><a href="#cb24-3" aria-hidden="true" tabindex="-1"></a><span class="ot">myServer ::</span> <span class="dt">Server</span> <span class="dt">IO</span></span>
|
||||
<span id="cb24-4"><a href="#cb24-4" aria-hidden="true" tabindex="-1"></a>myServer <span class="ot">=</span> \<span class="kw">case</span></span>
|
||||
<span id="cb24-5"><a href="#cb24-5" aria-hidden="true" tabindex="-1"></a> <span class="dt">MyMatchpoint</span> n (x, y) foo <span class="ot">-></span> <span class="kw">do</span></span>
|
||||
<span id="cb24-6"><a href="#cb24-6" aria-hidden="true" tabindex="-1"></a> <span class="op">...</span></span>
|
||||
<span id="cb24-7"><a href="#cb24-7" aria-hidden="true" tabindex="-1"></a> _ <span class="ot">-></span> <span class="kw">do</span></span>
|
||||
<span id="cb24-8"><a href="#cb24-8" aria-hidden="true" tabindex="-1"></a> <span class="op">...</span></span>
|
||||
<span id="cb24-9"><a href="#cb24-9" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb24-10"><a href="#cb24-10" aria-hidden="true" tabindex="-1"></a><span class="ot">instantiate ::</span> <span class="dt">Monad</span> m <span class="ot">=></span> (m <span class="op">~></span> <span class="dt">IO</span>) <span class="ot">-></span> <span class="dt">Server</span> m <span class="ot">-></span> <span class="dt">Application</span></span>
|
||||
<span id="cb24-11"><a href="#cb24-11" aria-hidden="true" tabindex="-1"></a>instantiate transformer server <span class="ot">=</span> <span class="op">...</span></span>
|
||||
<span id="cb24-12"><a href="#cb24-12" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb24-13"><a href="#cb24-13" aria-hidden="true" tabindex="-1"></a><span class="ot">api ::</span> <span class="dt">Application</span></span>
|
||||
<span id="cb24-14"><a href="#cb24-14" aria-hidden="true" tabindex="-1"></a>api <span class="ot">=</span> instantiate <span class="fu">id</span> myServer</span></code></pre></div>
|
||||
<p>You'll notice the Server type for Matchpoints is much simpler than
|
||||
the Server type for Endpoints.</p>
|
||||
<h3>Matchpoints vs. Endpoints</h3>
|
||||
<p>We recommend using Endpoints. Matchpoints are great if you're not
|
||||
worried about safety and just want to get something up and running
|
||||
quickly. Here are some downsides to using Matchpoints to implement your
|
||||
Server:</p>
|
||||
<ol type="1">
|
||||
<li><p>Can't do any static analysis. This means you can't generate
|
||||
OpenAPI specifications for Servers that use Matchpoints or perform any
|
||||
optimizations. You can perform static analysis on the Scripts that you
|
||||
use in your Matchpoints, if any.</p></li>
|
||||
<li><p>All handlers in a Matchpoint Server must operate within the same
|
||||
context. For Endpoints, this is not the case.</p></li>
|
||||
<li><p>Endpoints are more modular. You can achieve some level of
|
||||
moduarity with your Matchpoints by using nested
|
||||
<code>-XPatternSynonyms</code> though.</p></li>
|
||||
<li><p>Matchpoint Servers have no knowledge of what Responses you will
|
||||
return to the Client. Endpoint Servers know every possible Response you
|
||||
may return from your Handlers, besides ones caused by <code>IO</code>
|
||||
errors (the goal is for Endpoints to know about these as well).</p></li>
|
||||
</ol>
|
||||
<p>In short, if you don't care about safety, use Matchpoints.</p>
|
||||
<h2 id="servant<>okapi">Servant <> Okapi</h2>
|
||||
<p>Coming Soon</p>
|
||||
<!-- ## TLDR
|
||||
|
||||
or even
|
||||
|
Loading…
Reference in New Issue
Block a user