-
Notifications
You must be signed in to change notification settings - Fork 133
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1114 from efossier/http4s-docs
[WIP] Add Http4s documentation to microsite
- Loading branch information
Showing
14 changed files
with
406 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
61 changes: 61 additions & 0 deletions
61
modules/microsite/docs/scala/http4s/generating-a-server.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
--- | ||
layout: docs | ||
title: "Generating a Server - http4s - scala - guardrail" | ||
--- | ||
|
||
Generating a Server | ||
=================== | ||
|
||
guardrail-generated servers come in two parts: a `Resource` and a `Handler`. The `Resource` contains all the routing logic, accepting a `Handler` as an argument to the `route` function in order to provide an HTTP service in whichever supported HTTP framework you're hosting your service in. | ||
|
||
The following is an example from the [http4s](https://github.com/http4s/http4s) server generator: | ||
|
||
```scala mdoc:passthrough | ||
import com.twilio.guardrail.generators.Scala.Http4s | ||
import com.twilio.guardrail.docs._ | ||
DocsHelpers.renderScalaSnippet(Http4s, GeneratingAServer)(""" | ||
|// The `Handler` trait is fully abstracted from the underlying http framework. As a result, with the exception of some | ||
|// structural alterations (`F[_]` instead of `Future[_]` as the return type) the same handlers can be used with | ||
|// different `Resource` implementations from different framework generators. This permits greater compatibility between | ||
|// different frameworks without changing your business logic. | ||
""".stripMargin, | ||
"" | ||
) | ||
``` | ||
|
||
As all parameters are provided as arguments to the function stubs in the trait, there's no concern of forgetting to extract a query string parameter, introducing a typo in a form parameter name, or forgetting to close the bytestream for the streaming HTTP Request. | ||
|
||
The routes and resources generated by guardrail can be hooked up into your HTTP4s server like so: | ||
|
||
```scala | ||
val usersApi = new UsersApi() // Class which implements the generated UsersHandler from guardrail | ||
val usersService = new UsersResource[IO]().routes(usersApi) | ||
val httpApp = Router("/" -> usersService).orNotFound | ||
|
||
// Same basic server setup as in the http4s quickstart | ||
BlazeServerBuilder[IO] | ||
.bindHttp(5000, "localhost") | ||
.withHttpApp(httpApp) | ||
.resource | ||
.use(_ => IO.never) | ||
.as(ExitCode.Success) | ||
``` | ||
|
||
Separation of business logic | ||
---------------------------- | ||
|
||
Providing an implementation of a function with a well-defined set of inputs and outputs is natural for any developer. By reducing the scope of the interface a developer writes against, implementations are more clear and concise. | ||
|
||
Furthermore, by providing business logic as an implementation of an abstract class, unit tests can test the routing layer and business logic independently, by design. | ||
|
||
API structure slip is impossible | ||
-------------------------------- | ||
|
||
As parameters are explicitly provided as arguments to functions in `Handler`s, any alteration to parameters constitute a new function interface that must be implemented. As a result, if providing an implementation for an externally managed specification, the compiler informs when a previously written function is no longer sufficient. | ||
|
||
By representing different response codes and structures as members of a sealed trait, it's impossible to return a structure that violates the specification, even for less frequently used response codes. | ||
|
||
Finally, describing an endpoint in your specification without providing an implementation for it is a compiler error. This prevents reduction of functionality due to refactors, human error, or miscommunication with other teams. | ||
|
||
<span style="float: left">[Prev: Sample API specification](sample-api-specification)</span> | ||
<span style="float: right">[Next: Generating clients](generating-clients)</span> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
--- | ||
layout: docs | ||
title: "Generating Clients - http4s - scala - guardrail" | ||
--- | ||
|
||
Generating clients | ||
================== | ||
|
||
As we've seen in [Generating a Server](generating-a-server), guardrail-generated servers establish a mapping between our business logic and a cordoned off subset of HTTP. This permits us to focus on our business logic, without getting overloaded with the complexities of managing such a large protocol. The same is true with guardrail generated HTTP Clients: from a consumer's standpoint, HTTP calls should look like regular function calls, accepting domain-specific arguments and producing domain-specific results. | ||
|
||
By generating minimal clients that only have enough business knowledge to map domain types to and from HTTP, opportunities for logical errors are effectively removed. While this does not eliminate logical errors entirely, establishing a firm boundary between the underlying protocol and hand-written code drastically reduces the scope of possible bugs. | ||
|
||
The following is an example from the [http4s](https://github.com/http4s/http4s) client generator: | ||
|
||
```scala mdoc:passthrough | ||
import com.twilio.guardrail.generators.Scala.Http4s | ||
import com.twilio.guardrail.docs._ | ||
DocsHelpers.renderScalaSnippet(Http4s, GeneratingClients)( | ||
"""|// Two constructors are provided, one accepting the `httpClient` and `Async` | ||
|// implicitly, the other accepting an explicit `httpClient`, but still | ||
|// accepting the `Async` implicitly | ||
""".stripMargin, | ||
"" | ||
) | ||
``` | ||
|
||
Separation of protocol-concerns from API-level concerns | ||
------------------------------------------------------- | ||
|
||
As guardrail clients are built on top of any Http4s client type, client configuration is done the same way as you are | ||
already familiar with when using Http4s. | ||
|
||
Check out the docs for [Http4s Clients](https://http4s.org/v0.20/client/). | ||
|
||
<span style="float: left">[Prev: Generating a Server](generating-a-server)</span> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,22 @@ | ||
--- | ||
layout: docs | ||
title: "guardrail[http4s <- scala]" | ||
title: "http4s - scala - guardrail" | ||
--- | ||
|
||
These docs are under construction! | ||
Table of Contents | ||
================= | ||
|
||
In the meantime, please refer to the [akka-http](../akka-http) docs for broad context and getting started. | ||
|
||
Note that the `framework` for http4s is `"http4s"`, so using that in your SBT, Gradle, or Maven plugin configuration should get you started. | ||
1. [What is guardrail](what-is-guardrail.md) | ||
1. [Single Point of Truth](what-is-guardrail.md#single-point-of-truth) | ||
1. [Unexpected API changes are compiler errors](what-is-guardrail.md#unexpected-api-changes-are-compiler-errors) | ||
1. [Fewer binary dependencies](what-is-guardrail.md#fewer-binary-dependencies) | ||
1. [Installation](installation) | ||
1. [Sample API specification](sample-api-specification) | ||
1. [Generating a Server](generating-a-server) | ||
1. [Separation of business logic](generating-a-server#separation-of-business-logic) | ||
1. [API structure slip is impossible](generating-a-server#api-structure-slip-is-impossible) | ||
1. [Generating test-only (real) server mocks for unit tests](generating-a-server#generating-test-only-real-server-mocks-for-unit-tests) | ||
1. [A note about scalatest integration](generating-a-server#a-note-about-scalatest-integration) | ||
1. [Generating clients](generating-clients) | ||
1. [Separation of protocol-concerns from API-level concerns](generating-clients#separation-of-protocol-concerns-from-api-level-concerns) | ||
1. [guardrail Extensions](guardrail-extensions) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
--- | ||
layout: docs | ||
title: "Installation - http4s - scala - guardrail" | ||
--- | ||
|
||
Installation | ||
============ | ||
|
||
guardrail is available as a modular core, with both [sbt](https://github.com/twilio/sbt-guardrail) and [Maven](https://github.com/twilio/guardrail-maven-plugin) integration. The core can also be run as a stand-alone [CLI](https://github.com/twilio/guardrail/blob/978a92db3dd46812aa19f05050995f864cbb5bb3/build.sbt#L33-L48) application, with full support for all features. | ||
|
||
To generate servers or clients using the `http4s` framework, set `http4s` as the framework in the generation configuration in either sbt or maven. | ||
|
||
If compiling with Scala < 2.13.x, you'll need to enable `-Ypartial-unification`: | ||
|
||
```scala | ||
scalacOptions += "-Ypartial-unification" | ||
``` | ||
|
||
If compiling with Scala < 2.12.x, you'll additionally need the `-Xexperimental` flag: | ||
|
||
```scala | ||
scalacOptions += "-Xexperimental" | ||
``` | ||
|
||
Additionally, you will need to manually include dependencies in your project for the following packages: | ||
- `http4s`, dsl, server, and client dependencies | ||
- `http4s-circe` for JSON decoding and encoding support | ||
- `circe-generic` for JSON decoding and encoding support | ||
- `cats-effect` for http4s integration | ||
- `cats-core` for http4s integration | ||
|
||
Versions of these libraries should be picked by checking out the [Compatibility Matrix](https://github.com/guardrail-dev/guardrail/blob/master/COMPATIBILITY.md). | ||
|
||
<span style="float: left">[Prev: What is guardrail?](what-is-guardrail)</span> | ||
<span style="float: right">[Next: Sample API specification](sample-api-specification)</span> |
Oops, something went wrong.