Skip to content

Commit 280c35e

Browse files
committed
Docs improvement
1 parent 85afaf9 commit 280c35e

File tree

1 file changed

+62
-35
lines changed

1 file changed

+62
-35
lines changed

Rho.md

+62-35
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,64 @@
11
# Documenting Http4s web services with rho
2-
Rho is a library for documenting Http4s web apis.
32

4-
Note: To get the generated swagger.json, you need to visit: `{https|http}://host:port/{base path if any}/swagger.json`
3+
Rho is a library for documenting [http4s](https://http4s.org/) web APIs.
4+
5+
Note: To get the generated swagger.json, you need to visit: `{https|http}://host:port/{base service path if any}/swagger.json`
56

67
Sample:
8+
79
```scala
810
val api = new RhoService[IO] {
9-
"Description of api endpoint" **
10-
GET / "somePath" / pathVar[Int]("someInt", "parameter description") +? paramD[String]("name", "parameter description") |>> { (someInt: Int, name: String) => {
11-
Ok("result")
12-
}
11+
GET / "somePath" / pathVar[Int]("someInt", "parameter description") +? paramD[String]("name", "parameter description") |>> {
12+
(someInt: Int, name: String) => Ok("result")
1313
}
1414
}
1515
```
1616

17-
So we start by creating a new RhoService which will be converted to an HttpService later. This RhoService will contain our api endpoints. Every api endpoint starts (optionally) with a description for that endpoint and then the implementation. We describe the HTTP method (GET/POST/DELETE etc) and then an implementation for the url endpoint.
17+
So we start by creating a new RhoService which will be converted to an HttpService later. This RhoService will contain our api endpoints. Every api endpoint starts (optionally, for Swagger) with a description for that endpoint and then the implementation. We describe the HTTP method (GET/POST/DELETE etc) and then an implementation for the url endpoint.
1818

1919
You can specify and capture path or query parameters in your path. You specify a name and description (optional) for the variables. The available types that you can capture are:
2020
- all primitive types
21-
- java.util.Date (yyyy-MM-dd)
22-
- java.util.UUID
23-
- java.time.Instant (yyyy-MM-ddThh:mm:ssZ)
21+
- `java.util.Date` (yyyy-MM-dd)
22+
- `java.util.UUID`
23+
- `java.time.Instant` (yyyy-MM-ddThh:mm:ssZ)
2424

2525
Checkout these methods:
2626
- `pathVar` functions for capturing path variables
2727
- `param` functions for capturing query parameters
2828
- `capture` functions for capturing headers
2929

30+
Think of `|>>` as a function that "registers" new route matcher and associated action in RhoService.
31+
Route matcher is at lefthand-side (represented as `TypedBuilder`) and action at righthand-side is a function returning HTTP response.
32+
The arguments for action appear exactly as they do in the URL spec (route matcher).
33+
So in the sample above, `someInt` is first then `name` and so on. Optionally it can accept whole `org.http4s.Request` as first argument.
3034

31-
Think of `|>>` as a function from url specification to an implementation which returns a Response. The arguments for `|>>` appear exactly as they do in the url spec. So in the sample above, `someInt` is first then `name` and so on.
35+
Apart from plain URL parameters and path, you can insert header captures and body decoders for your requests, an example:
3236

33-
You can insert header captures and body decoders for your requests, an example:
3437
```scala
38+
object Auth extends org.http4s.rho.AuthedContext[IO, AuthInfo]
39+
3540
val api = new RhoService[IO] {
36-
"Description of api endpoint" **
37-
POST / "somePath" / pathVar[Int]("someInt", "parameter description") >>> auth ^ jsonOf[T] |>> { (someInt: Int, au: AuthInfo, body: T) => {
38-
Ok("result")
39-
}
41+
import org.http4s.rho.swagger.syntax.io._
42+
43+
"Description of api endpoint" ** // Description is optional and specific to Swagger
44+
POST / "somePath" / pathVar[Int]("someInt", "parameter description") >>> Auth.auth() ^ jsonOf[IO, T] |>> {
45+
(someInt: Int, au: AuthInfo, body: T) => Ok("result")
4046
}
4147
}
4248
```
43-
`auth` captures the authentication information. We are specifying that the body is a json object for some T.
49+
50+
`Auth.auth()` captures the authentication information.
51+
In order to provide authentication information:
52+
1. `AuthedContext` should be transformed into `HttpService`
53+
2. `AuthMiddleware[IO, AuthInfo]` must wrap above service
54+
55+
```scala
56+
val authInfoMiddleware: org.http4s.server.AuthMiddleware[IO, AuthInfo] = ??? // Standard http4s AuthMiddleware
57+
val authApi = Auth.toService(api.toService()) // 1
58+
val service: org.http4s.HttpService[IO] = authInfoMiddleware.apply(authApi) // 2
59+
```
60+
61+
Also, in example above, we are specifying that the body is a json object for some `T`.
4462
Anything that has a `EntityDecoder` can be specified as a body decoder. In the example above `jsonOf` is an `EntityDecoder` provided by `circe`. Included decoders in Rho are:
4563
- binary
4664
- binaryChunk
@@ -59,6 +77,8 @@ case class MyClass(name: String, description: String, someBool: Boolean, tags: L
5977
//or
6078
case class MyClass(name: String, description: String, someBool: Boolean, tags: List[String], someObj: JsonObject)
6179

80+
import org.http4s.rho.swagger.models._
81+
6282
val myClassModel: Set[Model] = Set(
6383
ModelImpl(
6484
id = "MyClass",
@@ -101,24 +121,31 @@ val myClassModel: Set[Model] = Set(
101121
)
102122
)
103123

104-
// register this model
105-
SwaggerSupport[IO].createRhoMiddleware(
106-
swaggerFormats = DefaultSwaggerFormats
107-
.withSerializers(typeOf[MyClass], myClassModel)
108-
.withSerializers(...),
109-
apiInfo = Info(
110-
title = "My API",
111-
version = "1.0.0",
112-
description = Some("functional because who hates sleep?")
113-
),
114-
basePath = "/v1".some,
115-
schemes = List(Scheme.HTTPS),
116-
security = List(SecurityRequirement("bearer", List())),
117-
securityDefinitions = Map(
118-
"bearer" -> ApiKeyAuthDefinition("Authorization", In.HEADER)
119-
))
124+
import org.http4s.rho.RhoMiddleware
125+
import org.http4s.rho.swagger.syntax.{io => ioSwagger}
126+
127+
// Create a middleware that will transform RhoService into HttpService with attached Swagger definition
128+
val swaggerMiddleware: RhoMiddleware[IO] = ioSwagger.createRhoMiddleware(
129+
swaggerFormats = DefaultSwaggerFormats
130+
.withSerializers(typeOf[MyClass], myClassModel)
131+
.withSerializers(...),
132+
apiInfo = Info(
133+
title = "My API",
134+
version = "1.0.0",
135+
description = Some("functional because who hates sleep?")
136+
),
137+
basePath = "/v1".some,
138+
schemes = List(Scheme.HTTPS),
139+
security = List(SecurityRequirement("bearer", List())),
140+
securityDefinitions = Map(
141+
"bearer" -> ApiKeyAuthDefinition("Authorization", In.HEADER)
142+
))
143+
144+
// Create http4s HttpService
145+
val httpService = api.toService(swaggerMiddleware)
120146
```
121-
Tha example above also shows how to provide basic api info and base path and security specification.
122-
By declaring security here we get option to add api key/token in the swagger ui.
147+
148+
The example above also shows how to provide basic api info and base path and security specification.
149+
By declaring security here we get option to add api key/token in the Swagger UI.
123150

124151
To get the generated swagger.json for this example, you would visit: `https://host:port/v1/swagger.json`

0 commit comments

Comments
 (0)