2023-11-17 13:02:23 +03:00
|
|
|
# 🦓🦒Okapi
|
2022-03-31 05:35:32 +03:00
|
|
|
|
2023-11-17 13:02:23 +03:00
|
|
|
Okapi is a data-driven micro framework for implementing HTTP servers.
|
2022-03-31 05:35:32 +03:00
|
|
|
|
2023-11-17 13:02:23 +03:00
|
|
|
- Ergonomic DSLs for routing and parsing requests
|
|
|
|
- Integrate Okapi with ANY monad stack or effect system
|
|
|
|
- Automatically generate clients and OpenAPI specifications (coming soon)
|
|
|
|
- Programatically generate your API's structure
|
2022-03-31 05:35:32 +03:00
|
|
|
|
2023-11-17 13:02:23 +03:00
|
|
|
## Hello World Example
|
2022-07-27 06:42:57 +03:00
|
|
|
|
2023-11-17 13:02:23 +03:00
|
|
|
```haskell
|
|
|
|
helloWorld =
|
|
|
|
responder @200 @'[] @Text.Text @Text.Text
|
|
|
|
. method HTTP.GET id
|
|
|
|
$ \greet _req -> return $ greet noHeaders "Hello World!"
|
|
|
|
|
|
|
|
main =
|
|
|
|
Warp.run 8000
|
|
|
|
. withDefault helloWorld
|
|
|
|
$ \_ resp -> resp $ Wai.responseLBS HTTP.status404 [] "Not Found..."
|
|
|
|
```
|
|
|
|
|
|
|
|
## Calculator Example
|
2022-03-31 05:35:32 +03:00
|
|
|
|
|
|
|
```haskell
|
2023-11-17 13:02:23 +03:00
|
|
|
data Operator
|
|
|
|
= Add
|
|
|
|
| Sub
|
|
|
|
| Mul
|
|
|
|
| Div
|
|
|
|
| Sq
|
|
|
|
| Neg
|
|
|
|
deriving (Show)
|
2022-03-31 05:35:32 +03:00
|
|
|
|
2023-11-17 13:02:23 +03:00
|
|
|
instance Web.FromHttpApiData Operator where
|
|
|
|
parseUrlPiece "add" = Right Add
|
|
|
|
parseUrlPiece "sub" = Right Sub
|
|
|
|
parseUrlPiece "minus" = Right Sub
|
|
|
|
parseUrlPiece "mul" = Right Mul
|
|
|
|
parseUrlPiece "div" = Right Div
|
|
|
|
parseUrlPiece "neg" = Right Neg
|
|
|
|
parseUrlPiece "sq" = Right Sq
|
|
|
|
parseUrlPiece "square" = Right Sq
|
|
|
|
parseUrlPiece _ = Left "Can't parse operator..."
|
2022-03-31 05:35:32 +03:00
|
|
|
|
2023-11-17 13:02:23 +03:00
|
|
|
shared =
|
|
|
|
lit "calc"
|
|
|
|
. param @Operator
|
|
|
|
. param @Int
|
2022-03-31 05:35:32 +03:00
|
|
|
|
2023-11-17 13:02:23 +03:00
|
|
|
unary =
|
|
|
|
responder @200 @'[] @Text.Text @Int
|
|
|
|
. responder @500 @'[] @Text.Text @Text.Text
|
|
|
|
. method HTTP.GET id
|
2022-03-31 05:35:32 +03:00
|
|
|
|
2023-11-17 13:02:23 +03:00
|
|
|
unaryHandler operator x ok wrongArgs _req =
|
|
|
|
return $ case operator of
|
|
|
|
Sq -> ok noHeaders (x * x)
|
|
|
|
Neg -> ok noHeaders (x * (-1))
|
|
|
|
_ -> wrongArgs noHeaders $ Text.pack (show operator) <> " needs two arguments."
|
2022-07-27 06:44:45 +03:00
|
|
|
|
2023-11-17 13:02:23 +03:00
|
|
|
binary =
|
|
|
|
param @Int
|
|
|
|
. responder @200 @'[] @Text.Text @Int
|
|
|
|
. responder @500 @'[] @Text.Text @Text.Text
|
|
|
|
. responder @403 @'[] @Text.Text @Text.Text
|
|
|
|
. method HTTP.GET id
|
2022-07-27 06:44:45 +03:00
|
|
|
|
2023-11-17 13:02:23 +03:00
|
|
|
binaryHandler operator x y ok wrongArgs divByZeroErr _req =
|
|
|
|
return $ case operator of
|
|
|
|
Add -> ok noHeaders (x + y)
|
|
|
|
Sub -> ok noHeaders (x - y)
|
|
|
|
Mul -> ok noHeaders (x * y)
|
|
|
|
Div ->
|
|
|
|
if y == 0
|
|
|
|
then divByZeroErr noHeaders "You can't divide by 0."
|
|
|
|
else ok noHeaders (div x y)
|
|
|
|
_ -> wrongArgs noHeaders $ Text.pack (show operator) <> " needs one argument."
|
2022-03-31 05:35:32 +03:00
|
|
|
|
2023-11-17 13:02:23 +03:00
|
|
|
calc = shared $ choice
|
|
|
|
[ unary unaryHandler
|
|
|
|
, binary binaryHandler
|
|
|
|
]
|
2022-03-31 05:35:32 +03:00
|
|
|
|
2023-11-17 13:02:23 +03:00
|
|
|
main =
|
|
|
|
Warp.run 8003
|
|
|
|
. withDefault calc
|
|
|
|
$ \_ resp -> resp $ Wai.responseLBS HTTP.status404 [] "Not Found..."
|
|
|
|
```
|