Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Configuring middleware in the component #3937

Open
wants to merge 16 commits into
base: v1.13
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
type: docs
title: "Middleware components"
linkTitle: "Middleware components"
description: "Guidance on how to work with middleware components"
weight: 200
---

Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
---
type: docs
title: "How to: Author middleware components"
linkTitle: "Middleware components"
weight: 200
description: "Learn how to develop middleware components"
aliases:
- /developing-applications/middleware/middleware-overview/
- /concepts/middleware-concept/
title: "How to: Implement middleware components"
linkTitle: "How to: Implement middleware components"
weight: 100
description: "Learn how to author and implement middleware components"
---

Dapr allows custom processing pipelines to be defined by chaining a series of middleware components. In this guide, you'll learn how to create a middleware component. To learn how to configure an existing middleware component, see [Configure middleware components]({{< ref middleware.md >}})
Dapr allows custom processing pipelines to be defined by chaining a series of middleware components. In this guide, you'll learn how to create a middleware component. To learn how to use a middleware component, see [the guide for middleware component configurations and pipelines]({{< ref middleware.md >}}).

## Writing a custom HTTP middleware

Expand Down
100 changes: 79 additions & 21 deletions daprdocs/content/en/operations/components/middleware.md
Original file line number Diff line number Diff line change
@@ -1,34 +1,96 @@
---
type: docs
title: "Configure middleware components"
linkTitle: "Configure middleware"
title: "Middleware components"
linkTitle: "Middleware"
weight: 2000
description: "Customize processing pipelines by adding middleware components"
description: "Customize processing pipelines using middleware components"
---

Dapr allows custom processing pipelines to be defined by chaining a series of middleware components. There are two places that you can use a middleware pipeline:
With Dapr, you can define custom processing middleware pipelines. In this guide, you learn about:

1. Building block APIs - HTTP middleware components are executed when invoking any Dapr HTTP APIs.
2. Service-to-Service invocation - HTTP middleware components are applied to service-to-service invocation calls.
- The two types of middleware pipelines.
- The two methods you can use to configure middleware.

## Configure API middleware pipelines
## Middleware pipelines

When launched, a Dapr sidecar constructs a middleware processing pipeline for incoming HTTP calls. By default, the pipeline consists of the [tracing]({{< ref tracing-overview.md >}}) and CORS middlewares. Additional middlewares, configured by a Dapr [Configuration]({{< ref configuration-concept.md >}}), can be added to the pipeline in the order they are defined. The pipeline applies to all Dapr API endpoints, including state, pub/sub, service invocation, bindings, secrets, configuration, distributed lock, etc.
Dapr offers two middleware pipeline types: `httpPipeline` and `appHttpPipeline`.

A request goes through all the defined middleware components before it's routed to user code, and then goes through the defined middleware, in reverse order, before it's returned to the client, as shown in the following diagram.
### `httpPipeline`

This pipeline applies to all Dapr API endpoints, including state, pub/sub, service invocation, bindings, secrets, configuration, distributed lock, etc. In this pipeline, a request:

1. Goes through all the defined middleware components before it's routed to user code.
1. Goes through the defined middleware, in reverse order, before it's returned to the client.

<img src="/images/middleware.png" width="800" alt="Diagram showing the flow of a request and a response through the middlewares, as described in the paragraph above" />

### `appHttpPipeline`

You can also use any middleware component when making service-to-service invocation calls. For example, to add token validation in a zero-trust environment, to transform a request for a specific app endpoint, or to apply OAuth policies.

Service-to-service invocation middleware components apply to all **outgoing** calls from a Dapr sidecar to the receiving application (service), as shown in the diagram below.

<img src="/images/app-middleware.png" width="800" alt="Diagram showing the flow of a service invocation request. Requests from the callee Dapr sidecar to the callee application go through the app middleware pipeline as described in the paragraph above." />

## Configure middleware

Dapr offers two ways for you to configure middleware:

- **Recommended:** Using the middleware component, just like any other [component]({{< ref components-concept.md >}}), with a YAML file placed into the application resources folder.
- Using a [configuration file]({{< ref configuration-schema.md >}}).

### Using middleware components

> Configuring middleware pipelines using the middleware component **is the recommended method**.

In your middleware component, you can set the pipeline type and priority metadata options, both of which are required for the component to be enabled in a pipeline.

Use `pipelineType` to set either `httpPipeline` or `appHttpPipeline` as the pipeline type.

The `priority` metadata option sets the order in which middleware components should be arranged and executed. Components with lower priorities are executed first, and priorities don't necessarily need to be sequential.

The following example defines a custom pipeline that uses a [RouterChecker middleware]({{< ref middleware-routerchecker.md >}}). In this case, all requests are authorized to follow the regex rule `^[A-Za-z0-9/._-]+$` before they are forwarded to user code. The `priority` field determines the order in which requests are executed once all handler components are collected.

```yml
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: routerchecker1
spec:
type: middleware.http.routerchecker
version: v1
metadata:
- name: rule
value: "^[A-Za-z0-9/._-]+$"
- name: pipelineType
value: appHttpPipeline
- name: priority
value: 1
```

### Using middleware components with configuration

Setting middleware pipelines using [a Dapr configuration file]({{< ref configuration-schema.md >}}) is **no longer recommended**.

#### API middleware pipelines

When launched, a Dapr sidecar constructs a middleware processing pipeline for incoming HTTP calls. By default, the pipeline consists of the [tracing]({{< ref tracing-overview.md >}}) and CORS middlewares. Additional middlewares, configured by a Dapr [Configuration]({{< ref configuration-concept.md >}}), can be added to the pipeline in the order they are defined.

HTTP middleware components are executed when invoking Dapr HTTP APIs using the `httpPipeline` configuration.

The following configuration example defines a custom pipeline that uses an [OAuth 2.0 middleware]({{< ref middleware-oauth2.md >}}) and an [uppercase middleware component]({{< ref middleware-uppercase.md >}}). In this case, all requests are authorized through the OAuth 2.0 protocol, and transformed to uppercase text, before they are forwarded to user code.

{{% alert title="Note" color="primary" %}}
Make sure to set different priority for different middleware components, otherwise Dapr might set it randomly.
{{% /alert %}}

```yaml
apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
name: pipeline
namespace: default
metadata:
name: routerchecker1
spec:
httpPipeline:
handlers:
Expand All @@ -38,19 +100,17 @@ spec:
type: middleware.http.uppercase
```

As with other components, middleware components can be found in the [supported Middleware reference]({{< ref supported-middleware >}}) and in the [`dapr/components-contrib` repo](https://github.com/dapr/components-contrib/tree/master/middleware/http).

{{< button page="supported-middleware" text="See all middleware components">}}
As with other components, supported middleware components can be found in the [supported Middleware reference guide]({{< ref supported-middleware >}}) and in the [`dapr/components-contrib` repo](https://github.com/dapr/components-contrib/tree/master/middleware/http).

## Configure app middleware pipelines
#### App middleware pipelines

You can also use any middleware component when making service-to-service invocation calls. For example, to add token validation in a zero-trust environment, to transform a request for a specific app endpoint, or to apply OAuth policies.

Service-to-service invocation middleware components apply to all **outgoing** calls from a Dapr sidecar to the receiving application (service), as shown in the diagram below.
Any middleware component that can be used as HTTP middleware can also be applied to service-to-service invocation calls as a middleware component using the `appHttpPipeline` configuration.

<img src="/images/app-middleware.png" width="800" alt="Diagram showing the flow of a service invocation request. Requests from the callee Dapr sidecar to the callee application go through the app middleware pipeline as described in the paragraph above." />
The example below adds the `uppercase` middleware component for all outgoing calls from the Dapr sidecar (target of service invocation) to the application that this configuration is applied to.

Any middleware component that can be used as HTTP middleware can also be applied to service-to-service invocation calls as a middleware component using the `appHttpPipeline` configuration. The example below adds the `uppercase` middleware component for all outgoing calls from the Dapr sidecar (target of service invocation) to the application that this configuration is applied to.
{{% alert title="Note" color="primary" %}}
Make sure to set different priority for different middleware components, otherwise Dapr might set it randomly.
{{% /alert %}}

```yaml
apiVersion: dapr.io/v1alpha1
Expand All @@ -68,6 +128,4 @@ spec:
## Related links

- [Learn how to author middleware components]({{< ref develop-middleware.md >}})
- [Component schema]({{< ref component-schema.md >}})
- [Configuration overview]({{< ref configuration-overview.md >}})
- [API middleware sample](https://github.com/dapr/samples/tree/master/middleware-oauth-google)
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,24 @@ spec:
value: "<your token audience; i.e. the application's client ID>"
- name: issuer
value: "<your token issuer, e.g. 'https://accounts.google.com'>"
- name: pipelineType
hhunter-ms marked this conversation as resolved.
Show resolved Hide resolved
value: "httpPipeline"

# Optional values
- name: priority
value: "1"
- name: jwksURL
value: "<JWKS URL, e.g. 'https://accounts.google.com/.well-known/openid-configuration'>"
```

## Spec metadata fields

| Field | Required | Details | Example |
|-------|:--------:|---------|---------|
| Field | Required? | Details | Example |
|-------|-----------|---------|---------|
| `audience` | Y | The audience expected in the tokens. Usually, this corresponds to the client ID of your application that is created as part of a credential hosted by a OpenID Connect platform. |
| `issuer` | Y | The issuer authority, which is the value expected in the issuer claim in the tokens. | `"https://accounts.google.com"`
| `pipelineType` | Y | For configuring middleware pipelines. One of the two types of middleware pipeline so you can configure your middleware for either sidecar-to-sidecar communication (`appHttpPipeline`) or sidecar-to-app communication (`httpPipeline`). | `"httpPipeline"`, `"appHttpPipeline"`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This description is wrong for the pipelines. Use one similar to the descriptions here https://docs.dapr.io/operations/components/middleware/

Suggested change
| `pipelineType` | Y | For configuring middleware pipelines. One of the two types of middleware pipeline so you can configure your middleware for either sidecar-to-sidecar communication (`appHttpPipeline`) or sidecar-to-app communication (`httpPipeline`). | `"httpPipeline"`, `"appHttpPipeline"`
| `pipelineType` | Y | For configuring middleware pipelines. One of the two types of middleware pipeline so you can configure your middleware for either sidecar-to-sidecar communication (`appHttpPipeline`) or sidecar-to-app communication (`httpPipeline`). | `"httpPipeline"`, `"appHttpPipeline"`

| `priority` | N | For configuring middleware pipeline ordering. The order in which [middleware components]({{< ref middleware.md >}}) are executed. Integer from -MaxInt32 to +MaxInt32. | `"1"`
| `jwksURL` | N | Address of the JWKS (JWK Set containing the public keys for verifying tokens). If empty, will try to fetch the URL set in the OpenID Configuration document `<issuer>/.well-known/openid-configuration`. | `"https://accounts.google.com/.well-known/openid-configuration"`

Common values for `issuer` include:
Expand All @@ -46,21 +52,14 @@ Common values for `issuer` include:
- Google: `https://accounts.google.com`
- Salesforce (Force.com): `https://login.salesforce.com`

## Dapr configuration
## Configure

To be applied, the middleware must be referenced in [configuration]({{< ref configuration-concept.md >}}). See [middleware pipelines]({{< ref "middleware.md">}}).
hhunter-ms marked this conversation as resolved.
Show resolved Hide resolved
You can configure middleware using the following methods:

```yaml
apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
name: appconfig
spec:
httpPipeline:
handlers:
- name: bearer-token
type: middleware.http.bearer
```
- **Recommended:** Using [the middleware component]({{< ref "middleware.md#using-middleware-components" >}}), just like any other [component]({{< ref components-concept.md >}}), with a YAML file placed into the application resources folder.
- Using a [configuration file]({{< ref "middleware.md#using-middleware-components-with-configuration" >}}).

See [how to apply middleware pipeline configurations]({{< ref "middleware.md" >}}).

## Related links

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ spec:
value: "authorization"
- name: forceHTTPS
value: "false"
- name: pipelineType
value: "httpPipeline"
- name: priority
value: "2"
```

{{% alert title="Warning" color="warning" %}}
Expand All @@ -44,32 +48,25 @@ The above example uses secrets as plain strings. It is recommended to use a secr

## Spec metadata fields

| Field | Details | Example |
|-------|---------|---------|
| clientId | The client ID of your application that is created as part of a credential hosted by a OAuth-enabled platform
| clientSecret | The client secret of your application that is created as part of a credential hosted by a OAuth-enabled platform
| scopes | A list of space-delimited, case-sensitive strings of [scopes](https://tools.ietf.org/html/rfc6749#section-3.3) which are typically used for authorization in the application | `"https://www.googleapis.com/auth/userinfo.email"`
| authURL | The endpoint of the OAuth2 authorization server | `"https://accounts.google.com/o/oauth2/v2/auth"`
| tokenURL | The endpoint is used by the client to obtain an access token by presenting its authorization grant or refresh token | `"https://accounts.google.com/o/oauth2/token"`
| redirectURL | The URL of your web application that the authorization server should redirect to once the user has authenticated | `"https://myapp.com"`
| authHeaderName | The authorization header name to forward to your application | `"authorization"`
| forceHTTPS | If true, enforces the use of TLS/SSL | `"true"`,`"false"` |
| Field | Required? | Details | Example |
|-------|-----------|---------|---------|
| `clientId` | | The client ID of your application that is created as part of a credential hosted by a OAuth-enabled platform
| `clientSecret` | | The client secret of your application that is created as part of a credential hosted by a OAuth-enabled platform
| `scopes` | | A list of space-delimited, case-sensitive strings of [scopes](https://tools.ietf.org/html/rfc6749#section-3.3) which are typically used for authorization in the application | `"https://www.googleapis.com/auth/userinfo.email"`
| `authURL` | | The endpoint of the OAuth2 authorization server | `"https://accounts.google.com/o/oauth2/v2/auth"`
| `tokenURL` | | The endpoint is used by the client to obtain an access token by presenting its authorization grant or refresh token | `"https://accounts.google.com/o/oauth2/token"`
| `redirectURL` | | The URL of your web application that the authorization server should redirect to once the user has authenticated | `"https://myapp.com"`
| `authHeaderName` | | The authorization header name to forward to your application | `"authorization"`
| `forceHTTPS` | | If true, enforces the use of TLS/SSL | `"true"`,`"false"` |
| `pipelineType` | Y | For configuring middleware pipelines. One of the two types of middleware pipeline so you can configure your middleware for either sidecar-to-sidecar communication (`appHttpPipeline`) or sidecar-to-app communication (`httpPipeline`). | `"httpPipeline"`, `"appHttpPipeline"`
| `priority` | N | For configuring middleware pipeline ordering. The order in which [middleware components]({{< ref middleware.md >}}) are executed. Integer from -MaxInt32 to +MaxInt32. | `"1"`, `"2"`

## Dapr configuration
## Configure

To be applied, the middleware must be referenced in [configuration]({{< ref configuration-concept.md >}}). See [middleware pipelines]({{< ref "middleware.md#customize-processing-pipeline">}}).
hhunter-ms marked this conversation as resolved.
Show resolved Hide resolved
You can configure middleware using the following methods:

```yaml
apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
name: appconfig
spec:
httpPipeline:
handlers:
- name: oauth2
type: middleware.http.oauth2
```
- **Recommended:** Using [the middleware component]({{< ref "middleware.md#using-middleware-components" >}}), just like any other [component]({{< ref components-concept.md >}}), with a YAML file placed into the application resources folder.
- Using a [configuration file]({{< ref "middleware.md#using-middleware-components-with-configuration" >}}).

## Related links

Expand Down
Loading
Loading