Skip to content

Commit

Permalink
update workflow to test haskell servant ping
Browse files Browse the repository at this point in the history
  • Loading branch information
wing328 committed Jul 7, 2024
1 parent 067442f commit 015072e
Show file tree
Hide file tree
Showing 11 changed files with 488 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/samples-haskell.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ on:
paths:
- samples/server/petstore/haskell-yesod/**
- samples/server/petstore/haskell-servant/**
- samples/server/others/haskell-servant-ping/**
- samples/client/petstore/haskell-http-client/**
pull_request:
paths:
- samples/server/petstore/haskell-yesod/**
- samples/server/petstore/haskell-servant/**
- samples/server/others/haskell-servant-ping/**
- samples/client/petstore/haskell-http-client/**
jobs:
build:
Expand All @@ -22,6 +24,7 @@ jobs:
# servers
- samples/server/petstore/haskell-yesod/
- samples/server/petstore/haskell-servant/
- samples/server/others/haskell-servant-ping/
- samples/client/petstore/haskell-http-client/
steps:
- uses: actions/checkout@v4
Expand Down
4 changes: 4 additions & 0 deletions bin/configs/haskell-servant-ping.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
generatorName: haskell
outputDir: samples/server/others/haskell-servant-ping
inputSpec: modules/openapi-generator/src/test/resources/3_0/ping.yaml
templateDir: modules/openapi-generator/src/main/resources/haskell-servant
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# OpenAPI Generator Ignore
# Generated by openapi-generator https://github.com/openapitools/openapi-generator

# Use this file to prevent files from being overwritten by the generator.
# The patterns follow closely to .gitignore or .dockerignore.

# As an example, the C# client generator defines ApiClient.cs.
# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
#ApiClient.cs

# You can match any string of characters against a directory, file or extension with a single asterisk (*):
#foo/*/qux
# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux

# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
#foo/**/qux
# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux

# You can also negate patterns with an exclamation (!).
# For example, you can ignore all files in a docs folder with the file extension .md:
#docs/*.md
# Then explicitly reverse the ignore rule for a single file:
#!docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.openapi-generator-ignore
README.md
Setup.hs
lib/PingTest/API.hs
lib/PingTest/Types.hs
ping-test.cabal
stack.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
7.8.0-SNAPSHOT
128 changes: 128 additions & 0 deletions samples/server/others/haskell-servant-ping/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
# Auto-Generated OpenAPI Bindings to `PingTest`

The library in `lib` provides auto-generated-from-OpenAPI bindings to the PingTest API.

## Installation

Installation follows the standard approach to installing Stack-based projects.

1. Install the [Haskell `stack` tool](http://docs.haskellstack.org/en/stable/README).
2. Run `stack install` to install this package.

Otherwise, if you already have a Stack project, you can include this package under the `packages` key in your `stack.yaml`:
```yaml
packages:
- location:
git: https://github.com/yourGitOrg/yourGitRepo
commit: somecommit
```
## Main Interface
The main interface to this library is in the `PingTest.API` module, which exports the PingTestBackend type. The PingTestBackend
type can be used to create and define servers and clients for the API.

## Creating a Client

A client can be created via the `createPingTestClient` function, which will generate a function for every endpoint of the API.
Then these functions can be invoked with `runPingTestClientWithManager` or more conveniently with `callPingTestClient`
(depending if you want an `Either` back or you want to catch) to access the API endpoint they refer to, if the API is served
at the `url` you specified.

For example, if `localhost:8080` is serving the PingTest API, you can write:

```haskell
{-# LANGUAGE RecordWildCards #-}
import PingTest.API as API
import Network.HTTP.Client (newManager)
import Network.HTTP.Client.TLS (tlsManagerSettings)
import Servant.Client (ClientEnv, mkClientEnv, parseBaseUrl)
main :: IO ()
main = do
-- Configure the BaseUrl for the client
url <- parseBaseUrl "http://localhost:8080/"
-- You probably want to reuse the Manager across calls, for performance reasons
manager <- newManager tlsManagerSettings
-- Create the client (all endpoint functions will be available)
let PingTestBackend{..} = API.createPingTestClient
-- Any PingTest API call can go here, e.g. here we call `getSomeEndpoint`
API.callPingTest (mkClientEnv manager url) getSomeEndpoint
```

## Creating a Server

In order to create a server, you must use the `runPingTestMiddlewareServer` function. However, you unlike the client, in which case you *got* a `PingTestBackend`
from the library, you must instead *provide* a `PingTestBackend`. For example, if you have defined handler functions for all the
functions in `PingTest.Handlers`, you can write:

```haskell
{-# LANGUAGE RecordWildCards #-}

import PingTest.API
-- required dependency: wai
import Network.Wai (Middleware)
-- required dependency: wai-extra
import Network.Wai.Middleware.RequestLogger (logStdout)

-- A module you wrote yourself, containing all handlers needed for the PingTestBackend type.
import PingTest.Handlers

-- If you would like to not use any middlewares you could use runPingTestServer instead

-- Combined middlewares
requestMiddlewares :: Middleware
requestMiddlewares = logStdout

-- Run a PingTest server on localhost:8080
main :: IO ()
main = do
let server = PingTestBackend{..}
config = Config "http://localhost:8080/"
runPingTestMiddlewareServer config requestMiddlewares server
```

## Authentication

Currently basic, bearer and API key authentication is supported. The API key must be provided
in the request header.

For clients authentication the function `clientAuth` is generated automatically. For basic
authentication the argument is of type `BasicAuthData` provided by `Servant.API.BasicAuth`.
For bearer and API key authentication the argument is the key/token and is of type `Text`.
Protected endpoints on the client will receive an extra argument. The value returned by
`clientAuth keyTokenOrBasic` can then be used to make authenticated requests.

For the server you are free to choose a custom data type. After you specified an instance of
`AuthServerData` it is automatically added as a first argument to protected endpoints:

```
newtype Account = Account {unAccount :: Text}
type instance AuthServerData Protected = Account
```

Additionally, you have to provide value for the `PingTestAuth` type provided by the
`PingTest.API` module:

```
auth :: PingTestAuth
auth =
PingTestAuth
{ lookupUser = lookupAccount,
authError = \request -> err401 {errBody = "Missing header"}
}
```

`lookupAccount` is a user defined function used to verify the key, token or basic auth data.
`authError` takes a `Request` and returns a `ServerError`. The value is used by the server
functions:

```
runPingTestMiddlewareServer config requestMiddlewares auth server
```
2 changes: 2 additions & 0 deletions samples/server/others/haskell-servant-ping/Setup.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import Distribution.Simple
main = defaultMain
Loading

0 comments on commit 015072e

Please sign in to comment.