Skip to content

Commit

Permalink
updated documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
gciuloaica committed Jan 21, 2022
1 parent c4249bc commit 73782af
Showing 1 changed file with 91 additions and 51 deletions.
142 changes: 91 additions & 51 deletions docs/website/docs/dsl/headers/index.md
Original file line number Diff line number Diff line change
@@ -1,50 +1,19 @@
# Headers API
# Headers

Headers API provides a ton of powerful operators that can be used to add, remove and modify headers.
Same Headers API could be used on both client, server and middleware.
ZIO-Http provide support for all HTTP (as defined in [RFC2616](https://datatracker.ietf.org/doc/html/rfc2616) ) headers and the library user's may define and use custom headers too.

`zhttp.http.Headers` - represents an immutable collection of headers i.e. essentially a `Chunk[(String, String)]`.
## Server side

`zhttp.http.HeaderNames` - commonly used header names.
### Attaching Headers to `Response`
In the server side implementation, `zio-http` is adding a collection of pre-defined headers to any response, according to http specification, but on top of them, user's of the library
may add other headers, including custom headers.

`zhttp.http.HeaderValues` - commonly used header values
There are multiple ways to attach headers to a response:
- using `Response.addHeaders` API
- through `Response` constructors
- using `Middlewares`

## Client API

The following example shows how you can add headers on the client request and how to check presence of header in client response.
```scala
import zhttp.http.{HeaderNames, HeaderValues, Headers}
import zhttp.service.{ChannelFactory, Client, EventLoopGroup}
import zio.{App, ExitCode, URIO, console}

object SimpleClientJson extends App {
val env = ChannelFactory.auto ++ EventLoopGroup.auto()
val url = "http://sports.api.decathlon.com/groups/water-aerobics"
// Construct headers
val headers = Headers.host("sports.api.decathlon.com").withAccept(HeaderValues.applicationJson)

val program = for {
// Pass headers to request
res <- Client.request(url, headers)
// List all response headers
_ <- console.putStrLn(res.headers.toList.mkString("\n"))
data <-
// Check if response contains a specified header with a specified value.
if (res.hasHeader(HeaderNames.contentType, HeaderValues.applicationJson))
res.getBodyAsString
else
res.getBodyAsString
_ <- console.putStrLn { data }
} yield ()

override def run(args: List[String]): URIO[zio.ZEnv, ExitCode] = program.exitCode.provideCustomLayer(env)

}
```

## Server API

The following example shows how to use Headers API on the server side.
Example below shows how the Headers could be added to a response by using `Response` constructors and how a custom header is added to `Response` through `addHeader` API call:

```scala
import zhttp.http._
Expand Down Expand Up @@ -74,29 +43,100 @@ object SimpleResponseDispatcher extends App {
if (acceptsStreaming)
Response(
status = Status.OK,
// Setting response header
headers = Headers.contentLength(message.length.toLong),
// Setting response header
headers = Headers.contentLength(message.length.toLong), // adding CONTENT-LENGTH header
data = HttpData.fromStream(ZStream.fromChunk(message)), // Encoding content using a ZStream
)
else Response(status = Status.ACCEPTED, data = HttpData.fromChunk(message))
else {
// Adding a custom header to Response
Response(status = Status.ACCEPTED, data = HttpData.fromChunk(message)).addHeader("X-MY-HEADER", "test")
}
}
}

```

## Middleware API
The following example shows how Headers could be added to `Response` in the `Middleware` implementation:

Middleware Service allows access of both Request and Response headers. It provides:
```scala

`zhttp.http.Middleware.addHeader` - to add a custom header in response (for example, in case of basic authentication when you have to provide the `WWW_AUTHENTICATE` header in case the authentication fail.)
/**
* Creates an authentication middleware that only allows authenticated requests to be passed on to the app.
*/
final def customAuth(
verify: Headers => Boolean,
responseHeaders: Headers = Headers.empty,
): HttpMiddleware[Any, Nothing] =
Middleware.ifThenElse[Request](req => verify(req.getHeaders))(
_ => Middleware.identity,
_ => Middleware.fromHttp(Http.status(Status.FORBIDDEN).addHeaders(responseHeaders)),
)

`zhttp.http.Middleware.addHeaders` - to add one or more headers in response.
```

Example:
More examples:
- [BasicAuth](https://github.com/dream11/zio-http/blob/main/example/src/main/scala/BasicAuth.scala)
- [Authentication](https://github.com/dream11/zio-http/blob/main/example/src/main/scala/Authentication.scala)

## More examples
### Reading Headers from `Request`

Server side implementation provides API that allows to read `Request` headers. The example above shows how also how the request headers could be read.
In the example, the `ACCEPT` request header is read/checked to see if the `octet-streaming` response is acceptable for the client.

TBD: example

## Client Side

### Adding headers to `Request`

ZIO-http provides a simple way to add headers to a client `Request`. Fo example, in most of the cases a client request should provide the `Host` header.
The sample below shows how a header could be added into a client request:

```scala
import zhttp.http.{HeaderNames, HeaderValues, Headers}
import zhttp.service.{ChannelFactory, Client, EventLoopGroup}
import zio.{App, ExitCode, URIO, console}

object SimpleClientJson extends App {
val env = ChannelFactory.auto ++ EventLoopGroup.auto()
val url = "http://sports.api.decathlon.com/groups/water-aerobics"
// Construct headers
val headers = Headers.host("sports.api.decathlon.com").withAccept(HeaderValues.applicationJson)

val program = for {
// Pass headers to request
res <- Client.request(url, headers)
// List all response headers
_ <- console.putStrLn(res.headers.toList.mkString("\n"))
data <-
// Check if response contains a specified header with a specified value.
if (res.hasHeader(HeaderNames.contentType, HeaderValues.applicationJson))
res.getBodyAsString
else
res.getBodyAsString
_ <- console.putStrLn { data }
} yield ()

override def run(args: List[String]): URIO[zio.ZEnv, ExitCode] = program.exitCode.provideCustomLayer(env)

}
```

### Reading headers from `Response`

TBD


## Headers DSL

Headers DSL provides a ton of powerful operators that can be used to add, remove and modify headers.
Same Headers API could be used on both client, server and middleware.

`zhttp.http.Headers` - represents an immutable collection of headers i.e. essentially a `Chunk[(String, String)]`.

`zhttp.http.HeaderNames` - commonly used header names.

`zhttp.http.HeaderValues` - commonly used header values

- Constructors:

Expand Down

0 comments on commit 73782af

Please sign in to comment.