### ----------------------------------------------------
### -- P6W
### -- Licenses: Artistic-2.0
### -- Authors: Sterling Hanenkamp <hanenkamp@cpan.org>
### -- File: README.md
### ----------------------------------------------------
### -- Chunk 2 of 2
 one of these supported protocols by sending a `WAPIx-Upgrade` header back to the server with the named protocol. The application MAY send any other headers related to the Upgrade and MAY send a message payload if the upgrade allows it. These SHOULD override any server supplied values or headers.

The server MUST negotiate the new protocol and enable any environment variables required for interacting through that protocol. After the handshake or upgrade negoatiation is complete, the server MUST make a new call to the application with a new environment to process the remainder of the network request with the origin.

### 3.8.0 HTTP/2 Protocol Upgrade

The workings of HTTP/2 are similar enough to HTTP/1.0 and HTTP/1.1 that use of a protocol upgrade may not be necessary in most or all use-cases. However, servers MAY choose to delegate this to the application using the protocol upgrade extension.

Servers that support this protocol upgrade MUST place the name "h2c" and/or "h2" into the `wapix.net-protocol.upgrade` set, for support of HTTP/2 over cleartext connections and HTTP/2 over TLS, respectively.

The application MUST NOT request an upgrade using the `WAPIx-Upgrade` header for "h2c" unless the `wapi.url-scheme` is "http". Similarly, the application MUST NOT request an upgrade for "h2" unless the `wapi.url-scheme` is "https". The application server SHOULD enforce this requirement for security reasons.

The application MUST NOT tap the `wapi.input` stream when performing this upgrade. The application SHOULD NOT return a message payload aside from an empty [Supply](http://doc.perl6.org/type/Supply).

### 3.8.1 WebSocket Protocol Upgrade

Servers that support the WebSocket protocol upgrade MUST place the name "ws" into the `wapix.net-protocol.upgrade` set.

The application MUST NOT tap the `wapi.input` stream when performing this upgrade. The application SHOULD NOT return a message payload aside from an empty [Supply](http://doc.perl6.org/type/Supply).

3.9 Transfer Encoding
---------------------

This extension is only for HTTP/1.1 protocol connections. When the server supports this extension, it MUST provide a `wapix.http11.transfer-encoding` variable containing a `Set` naming the transfer encodings the server supports as strings. This SHOULD be set in the configuration environment.

When the application returns a header named `WAPIx-Transfer-Encoding` with the name of one of the supported transfer encoding strings, the server MUST apply that transfer encoding to the message payload. If the connection is not HTTP/1.1, the server SHOULD ignore this header.

### 3.9.0 Chunked Encoding

When the server supports and the application requests "chunked" encoding. The application server SHOULD treat each emitted [Str](http://doc.perl6.org/type/Str) or [Blob](http://doc.perl6.org/type/Blob) as a chunk to be encoded according to [RFC7230](https://tools.ietf.org/html/draft-ietf-httpbis-p1-messaging). It MUST adhere to requirements of RFC7230 when sending the response payload to the origin.

### 3.9.1 Other Encodings

All other encodings should be handled as required by the relevant rules for HTTP/1.1.

### 3.10 HTTP/2 Push Promises

When the `SERVER_PROTOCOL` is "HTTP/2", servers SHOULD support the HTTP/2 push promises extension. However, applications SHOULD check to make sure that the `wapix.h2.push-promise` variable is set to a defined value before using this extension.

This extension is implemented by providing a variable named `wapix.h2.push-promise`. When provided, this MUST be a [Supplier](http://doc.perl6.org/type/Supplier).

When the application wishes to invoke a server push, it MUST emit a message describing the request the server is pushing. The application server will receive this request and make a new, separate call to the application to fulfill that request.

Push-promise messages are sent as an [Array](http://doc.perl6.org/type/Array) of [Pair](http://doc.perl6.org/type/Pair)s. This is a set of headers to send with the PUSH_PROMISE frame, including HTTP/2 pseudo-headers like ":path" and ":authority".

Upon receiving a message to `wapix.h2.push-promise`, the server SHOULD schedule a followup call to the application to fulfill the push-promise as if the push-promise were an incoming request from the client. (The push-promise could be canceled by the client, so the call to the application might not actually happen.)

4 Application Protocol Implementation
=====================================

One goal of RakuWAPI application servers is to allow the application to focus on building web applications without having to implement the mundane details of web protocols. In times past, this was simply a matter of implementing HTTP/1.x or some kind of front-end to HTTP/1.x (such as CGI or FastCGI). While HTTP/1.x is still relevant to the web today, new protocols have also become important to modern web applications, such as HTTP/2 and WebSocket.

These protocols may have different interfaces that do not lend themselves to the request-response pattern specifed by PSGI. Therefore, we provide a means by which servers and applications may implement these alternate protocols, which each may have different requirements. These protocols are called application protocols to differentiate them from network protocols. For example, rather than providing a protocol for HTTP, we provide the "request-response" protocol. The underlying network protocol may be HTTP/1.0, HTTP/1.1, HTTP/2 or it may be something else that operates according to a similar pattern.

The application and application server MUST communicate according to the application protocol used for the current application call. For many applications, just implementing the basic request-response protocol is enough. However, to allow for more complete applications, RakuWAPI provides additional tools to help application and application server to communicate through a variety of situations. This is handled primarily via the `wapi.protocol`, `wapi.protocol.support`, and `wapi.protocol.enabled` values in the environment.

The application SHOULD check the value in `wapi.protocol`. If the application needs to make a decision based upon the network protocol, the application SHOULD check the `SERVER_PROTOCOL`.

The application SHOULD check `wapi.protocol.support` to discover which protocols are supported by the application server. An application that is not able to support all supported protocols SHOULD modify `wapi.protocol.enabled` to only include protocols supported by the application as early as possible.

The application server MUST provide the `wapi.protocol.support` and `wapi.protocol.enabled` values as part of the configuration environment. The application server MUST NOT use any protocol that is not a member of the `wapi.protocol.enabled` set.

This specification defines the following protocols:

  * **request-response** for request-response protocols, including HTTP

  * **framed-socket** for framed-socket protocols, such as WebSocket

  * **psgi** for legacy PSGI applications

  * **socket** for raw, plain socket protocols, which send and receive data with no expectation of special server handling

It is recommended that an application server that implements all of these protocols only enable the request-response protocol within `wapi.protocol.enabled` by default. This allows simple RakuWAPI applications to safely operate without having to perform any special configuration.

4.0 Request-Response Protocol
-----------------------------

The "request-response" protocol SHOULD be used for any HTTP-style client-server web protocol, this include HTTP/1.x and HTTP/2 connections over plain text and TLS or SSL.

### 4.0.0 Response

Here is an example application that implements the "request-response" protocol:

```perl6
    sub app(%env) {
        start {
            200,
            [ Content-Type => 'text/plain' ],
            supply {
                emit "Hello World"
            },
        }
    }
```

The runtime routine for the application MUST return a [Promise](http://doc.perl6.org/type/Promise). This Promise MUST be kept with a [Capture](http://doc.perl6.org/type/Capture) (or something that becomes one on return) and MAY be broken. The Capture MUST contain 3 positional elements, which are the status code, the list of headers, and the response payload.

  * The status code MUST be an [Int](http://doc.perl6.org/type/Int) or an object that coerces to an Int. It MUST be a valid status code for the [SERVER_PROTOCOL](http://doc.perl6.org/type/SERVER_PROTOCOL).

  * The headers MUST be a [List](http://doc.perl6.org/type/List) of [Pair](http://doc.perl6.org/type/Pair)s or an object that when coerced into a List becomes a List of Pairs. These pairs name the headers to return with the response. Header names MAY be repeated.

  * The message payload MUST be a *sane* [Supply](http://doc.perl6.org/type/Supply) or an object that coerces into a *sane* Supply, such as a [List](http://doc.perl6.org/type/List).

Here is a more interesting example application of this interface:

```perl6
    sub app(%env) {
        start {
            my $n = %env<QUERY_STRING>.Int;
            200,
            [ Content-Type => 'text/plain' ],
            supply {
                my $acc = 1.FatRat;
                for 1..$n -> $v {
                    emit $acc *= $v;
                    emit "\n";
                }
            },
        }
    }
```

The example application above will print out all the values of factorial from 1 to N where N is given in the query string. The header may be returned immediately and the lines of the body may be returned as the values of factorial are calculated by the application server.

And here is an example demonstrating a couple ways in which coercion can be used by an application to simplify the result:

```perl6
    sub app(%env) {
        my enum HttpStatus (OK => 200, NotFound => 404, ServerError => 500);
        start {
            OK, [ Content-Type => 'text/plain' ], [ 'Hello World' ]
        }
    }
```

In this example, the status is returned using an enumeration which coerces to an appropriate integer value. The payload is returned as a list, which is automatically coerced into a Supply.

Applications SHOULD return a Promise as soon as possible. It is recommended that applications wrap all operations within a `start` block to make this automatic.

Application servers SHOULD NOT assume that the returned [Promise](http://doc.perl6.org/type/Promise) will be kept. It SHOULD assume that the Promise has been vowed and MUST NOT try to keep or break the Promise from the application.

### 4.0.1 Response Payload

The response payload, in the result of the application's promise, must be a *sane* [Supply](http://doc.perl6.org/type/Supply). This supply MUST emit nothing for requests whose response must be empty.

For any other request, the application MAY emit zero or more messages in the returned payload Supply. The messages SHOULD be handled as follows:

  * [Blob](http://doc.perl6.org/type/Blob). Any Blob emitted by the application SHOULD be treated as binary data to be passed through to the origin as-is.

  * [List](http://doc.perl6.org/type/List) of [Pair](http://doc.perl6.org/type/Pair)s. Some response payloads may contain trailing headers. Any List of Pairs emitted should be treated as trailing headers.

  * [Associative](http://doc.perl6.org/type/Associative). Any Associative object emitted should be treated as a message to communicate between layers of the application, middleware, and server. These should be ignored and passed on by middleware to the next layer unless consumed by the current middleware. Any message that reaches the application server but is not consumed by the application server MAY result in a warning being reported, but SHOULD otherwise be ignored. These objects MUST NOT be transmitted to the origin.

  * [Mu](http://doc.perl6.org/type/Mu). Any other Mu SHOULD be stringified with the `Str` method and encoded by the application server. If an object given cannot be stringified, the server SHOULD report a warning.

### 4.0.2 Encoding

The application server SHOULD handle encoding of strings or stringified objects emitted to it. When performing encoding, the application server SHOULD honor the `charset` set within the `Content-Type` header, if given. If it does not honor the `charset` or no `charset` is set by the application, it MUST encode any strings in the response payload according to the encoding named in `wapi.body.encoding`.

### 4.0.3 Request-Response Lifecycle

The application server performs the following during a single request-response interaction:

  * Receive a request from an origin and begin parsing the request according to the network protocol.

  * Construct a runtime environment and combine it with the configuration environment. The `wapi.input` part of the environment should continue reading data from the origin as it arrives until the request has been completely read.

  * Call the application runtime routine with the constructed environment and await a value from the returned [Promise](http://doc.perl6.org/type/Promise).

  * Return the start of the response using the HTTP status code and headers provided, formatted according to the protocol requirements.

  * Tap the supply part of the response and return data to the origin, formatted in ways appropriate for the environment settings and the network protocol in place.

The server processes requests from an origin, passes the processed request information to the application by calling the application, waits for the application's response, and then returns the response to the origin. In the simplest example this means handling an HTTP roundtrip. Yet, it may also mean implementing a related protocol like CGI or FastCGI or SCGI or something else entirely.

In the modern web, an application may want to implement a variety of complex HTTP interactions. These use-cases are not described by the typical HTTP request-response roundtrip with which most web developers are familiar. For example, an interactive Accept-Continue response or a data stream to or from the origin or an upgrade request to switch protocols. As such, application servers SHOULD make a best effort to be implemented in such a way as to make this variety applications possible.

The application server SHOULD pass control to the application as soon as the headers have been received and the environment can be constructed. The application server MAY continue processing the request payload while the application server begins its work. The server SHOULD NOT emit the request payload to `wapi.input` yet.

Once the application has returned the its [Promise](http://doc.perl6.org/type/Promise) to respond, the server SHOULD wait until the promise is kept. Once kept, the server SHOULD tap the response payload as soon as possible. After tapping the Supply, the application server SHOULD keep the [Promise](http://doc.perl6.org/type/Promise) in `wapi.ready` (the application server SHOULD NOT break this Promise). Once that promise has been kept, only then SHOULD the server start emitting the contents of the request payload, if any, to `wapi.input`.

The server SHOULD return the application response headers back to the origin as soon as they are received. After which, the server SHOULD return each chunk emitted by the response body from the application as soon as possible.

This particular order of operations during the application call will ensure that the application has the greatest opportunity to perform well and be able to execute a variety of novel HTTP interactions.

### 4.0.4 HTTP/1.1 Keep Alive

When an application server supports HTTP/1.1 with keep-alive, each request sent on the connection MUST be handled as a separate call to the application.

### 4.0.4 HTTP/2 Handling

When a server supports HTTP/2 it SHOULD implement the HTTP/2 Push Promise Extension defined in section 3.10. An application server MAY want to consider implementing HTTP/2 protocol upgrades using the extension described in section 3.8 or MAY perform such upgrades automatically instead.

The application MUST be called once for each request or push-promise made on an HTTP/2 stream.

4.1 Framed-Socket Protocol
--------------------------

The "framed-socket" protocol is appropriate for WebSocket-style peer-to-peer TCP connections. The following sections assume a WebSocket connection, but might be adaptable for use with other framed message exchanges, such as message queues or chat servers.

### 4.1.0 Response

Any application server implementing WebSocket MUST adhere to all the requirements described above with the following modifications when calling the application for a WebSocket:

  * The `REQUEST_METHOD` MUST be set to the HTTP method used when the WebSocket connection was negotiated, i.e., usually "GET". Similarly, `SCRIPT_NAME`, `PATH_INFO`, `REQUEST_URI`, `QUERY_STRING`, `SERVER_NAME`, `SERVER_PORT`, `CONTENT_TYPE`, and `HTTP_*` variables in the environment MUST be set to the values from the original upgrade request sent from the origin.

  * The `SERVER_PROTOCOL` MUST be set to "WebSocket/13" or a similar string representing the revision of the WebSocket network protocol which in use.

  * The `CONTENT_LENGTH` SHOULD be set to an undefined [Int](http://doc.perl6.org/type/Int).

  * The `wapi.url-scheme` MUST be set to "ws" for plain text WebSocket connections or "wss" for encrypted WebSocket connections.

  * The `wapi.protocol` MUST be set to "framed-socket".

  * The server MUST decode frames received from the client and emit each of them to `wapi.input`. The frames MUST NOT be buffered or concatenated.

  * The server's supplied `wapi.input` [Supply](http://doc.perl6.org/type/Supply) must be *sane*. The server SHOULD signal `done` through the Supply when either the client or server closes the WebSocket connection normally and `quit` on abnormal termination of the connection.

  * The server MUST encode frames emitted by the application in the message payload as data frames sent to the client. The frames MUST be separated out as emitted by the application without any buffering or concatenation.

The application MUST return a [Promise](http://doc.perl6.org/type/Promise) that is kept with just a [Supply](http://doc.perl6.org/type/Supply) (i.e., not a 3-element Capture as is used with the request-response protocol). The application MAY break this Promise. The application will emit frames to send back to the origin using the promised Supply.

### 4.1.1 Response Payload

Applications MUST return a *sane* [Supply](http://doc.perl6.org/type/Supply) that emits an object for every frame it wishes to return to the origin. The application MAY emit zero or more messages to this supply. The application MAY emit `done` to signal that the connection is to be terminated with the client.

The messages MUST be framed and returned to the origin by the application server as follows, based on message type:

  * [Blob](http://doc.perl6.org/type/Blob). Any Blob emitted by the application SHOULD be treated as binary data, framed exactly as is, and returned to the client.

  * [Associative](http://doc.perl6.org/type/Associative). Any Associative object emitted should be treated as a message to communicate between layers of the application, middleware, and server. These should be ignored and passed on by middleware to the next layer unless consumed by the current middleware. Any message that reaches the application server but is not consumed by the application server MAY result in a warning being reported, but SHOULD otherwise be ignored. These objects MUST NOT be transmitted to the origin.

  * [Mu](http://doc.perl6.org/type/Mu). Any other Mu SHOULD be stringified, if possible, and encoded by the application server. If an object given cannot be stringified, the server SHOULD report a warning.

### 4.1.2 Encoding

The application server SHOULD handle encoding of strings or stringified objects emitted to it. The server MUST encode any strings in the message payload according to the encoding named in `wapi.body.encoding`.

4.2 PSGI Protocol
-----------------

To handle legacy applications, this specification defines the "psgi" protocol. If `wapi.protocol.enabled` has both "psgi" and "request-response" enabled, the "request-response" protocol SHOULD be preferred.

### 4.2.0 Response

The application SHOULD return a 3-element [Capture](http://doc.perl6.org/type/Capture) directly. The first element being the numeric status code, the second being an array of pairs naming the headers to return in the response, and finally an array of values representing the response payload.

### 4.2.1 Payload

The payload SHOULD be delivered as an array of strings, never as a supply.

### 4.2.2 Encoding

String encoding is not defined by this document.

4.3 Socket Protocol
-------------------

The "socket" protocol can be provided by an application server wishing to allow the application to basically take over the socket connection with the origin. This allows the application to implement an arbitrary protocol. It does so, however, in a way that is aimed toward providing better portability than using the socket extension.

The socket provided sends and receives data directly to and from the application without any framing, buffering, or modification. 

The "socket" protocol SHOULD only be used when it is enabled in `wapi.protocol.enabled` and no other protocol enabled there can fulfill the current application call.

4.3.0 Response
--------------

Here's an example application that implements the "socket" protocol to create a naïve HTTP server:

```perl6
    sub app(%env) {
        start {
            supply {
                whenever %env<wapi.input> -> $msg {
                    my $req = parse-http-request($msg);

                    if $req.method eq 'GET' {
                        emit "200 OK HTTP/1.0\r\n";
                        emit "\r\n";
                        emit "Custom HTTP Server";
                    }
                }
            }
        }
    }
```

The socket protocol behaves very much like "framed-socket", but with fewer specified details in the environment. Some of the mandatory environment are not mandatory for the socket protocol.

The following parts of the environment SHOULD be provided as undefined values:

  * REQUEST_METHOD

  * SCRIPT_NAME

  * PATH_INFO

  * REQUEST_URI

  * QUERY_STRING

  * SERVER_NAME

  * SERVER_PORT

  * CONTENT_TYPE

  * HTTP_*

  * wapi.url-scheme

  * wapi.ready

  * wapi.body.encoding

  * SERVER_PROTOCOL

The `wapi.protocol` must be set to "socket".

The application server SHOULD provide data sent by the origin to the application through the `wapi.input` supply as it arrives. It MUST still be a *sane* supply.

The application server MAY tunnel the connection through another socket, stream, file handle, or what-not. That is, the application MAY NOT assume the communication is being performed over any particular medium. The application server SHOULD transmit the data to the origin as faithfully as possible, keeping the intent of the application as much as possible.

The application server SHOULD forward on data emitted by the application in the returned payload supply as it arrives. The application server SHOULD send no other data to the origin over that socket once the application is handed control, unless related to how the data is being tunneled or handled by the server. The application server SHOULD close the connection with the origin when the application server sends the "done" message to the supply. Similarly, the application server SHOULD send "done" the `wapi.input` supply when the connection is closed by the client or server.

### 4.3.1 Response Payload

Applications MUST return a *sane* [Supply](http://doc.perl6.org/type/Supply) which emits a string of bytes for every message to be sent. The messages returned on this stream MUST be [Blob](http://doc.perl6.org/type/Blob) objects. 

### 4.3.2 Encoding

The application server SHOULD reject any object other than a [Blob](http://doc.perl6.org/type/Blob) sent as part of the message payload. The application server is not expected to perform any encoding or stringification of messages.

Changes
=======

0.9.Draft
---------

  * The error stream is now defined to be a `Supplierish` object, defined in Section 1.1.

  * Section 2.2.0.0 has been changed to forbid runtime routines from having a `Callable` return type.

  * Section 2.1.2 was rewritten to disallow what was previously allowed: the modification of the input stream.

  * Eliminated ambiguity regarding typing of environment in the middleware section.

  * Added a section for type constraints and made better use of subset types to streamline and simplify some of the documentation.

  * Cleaned up some old language left over from previous versions of the specification.

  * Eliminated some ambiguities in the type required for undefined environment values. The undefined environment values MUST match the given type constraint and be set to type objects of that type if they are not defined.

  * Changed the abbreviation from P6WAPI to RakuWAPI.

  * Changed all `p6w.*` environment prefixes to `wapi.*`

  * Changed all `p6wx.*` environment prefixes to `wapix.*`

  * Changed all `P6Wx-*` header names to `WAPIx-*` header names

  * Renamed all example `*.p6w` files to `*.wapi`

0.8.Draft
---------

  * Changed the abbreviation from P6W to P6WAPI.

0.7.Draft
---------

  * Renamed the standard from Perl 6 Standard Gateway Interface (P6SGI) to the Web API for Perl 6 (P6W).

  * Some grammar fixes, typo fixes, and general verbiage cleanup and simplification.

  * Renaming `p6sgi.*` to `p6w.*` and `p6sgix.*` to `p6wx.*`.

  * The errors stream is now a `Supplier` rather than a `Supply` because of recent changes to the Supply interface in Perl 6. Made other supply-related syntax changes because of design changes to S17.

  * Eliminating the requirement that things emitted in the response payload be [Cool](http://doc.perl6.org/type/Cool) if they are to be stringified and encoded. Any stringifiable [Mu](http://doc.perl6.org/type/Mu) is permitted.

  * Adding `p6w.protocol`, `p6w.protocol.support`, and `p6w.protocol.enabled` to handle server-to-application notification of the required response protocol.

  * Breaking sections 2.0.4, 2.1.4, and 2.2.4 up to discuss the difference between the HTTP and WebSocket protocol response requirements.

  * Moving 2.0.5, 2.1.5, and 2.2.5 under 2.*.4 because of the protocol changes made in 2.*.4.

  * Changed `p6wx.protocol.upgrade` from an [Array](http://doc.perl6.org/type/Array) to a [Set](http://doc.perl6.org/type/Set) of supported protocol names.

  * Split the environment and the application into two parts: configuration and runtime.

  * Added Section 4 to describe protocol-specific features of the specification. Section 4.0 is for HTTP, 4.1 is for WebSocket, 4.2 is for PSGI, and 4.3 is for Socket.

0.6.Draft
---------

  * Added Protocol-specific details and modifications to the standard HTTP/1.x environment.

  * Adding the Protocol Upgrade extension and started details for HTTP/2 and WebSocket upgrade handling.

  * Adding the Transfer Encoding extension because leaving this to the application or unspecified can lead to tricky scenarios.

0.5.Draft
---------

  * Adding `p6sgi.ready` and added the Application Lifecycle section to describe the ideal lifecycle of an application.

  * Changed `p6sgi.input` and `p6sgi.errors` to Supply objects.

  * Porting extensions from PSGI and moving the existing extensions into the extension section.

  * Adding some notes about middleware encoding.

  * Renamed `p6sgi.encoding` to `p6sgi.body.encoding`.

  * Renamed `p6sgix.response.sent` to `p6sgix.body.done`.

  * Added `p6sgix.header.done` as a new P6SGI extension.

0.4.Draft
---------

  * Cutting back on some more verbose or unnecessary statements in the standard, trying to stick with just what is important and nothing more.

  * The application response has been completely restructured in a form that is both easy on applications and easy on middleware, mainly taking advantage of the fact that a List easily coerces into a Supply.

  * Eliminating the P6SGI compilation unit again as it is no longer necessary.

  * Change the Supply to emit Cool and Blob rather than just Str and Blob.

0.3.Draft
---------

  * Splitting the standard formally into layers: Application, Server, and Middleware.

  * Bringing back the legacy standards and bringing back the variety of standard response forms.

  * Middleware is given a higher priority in this revision and more explanation.

  * Adding the P6SGI compilation unit to provide basic tools that allow middleware and possibly servers to easily process all standard response forms.

  * Section numbering has been added.

  * Added the Changes section.

  * Use `p6sgi.` prefixes in the environment rather than `psgi.`

0.2.Draft
---------

This second revision eliminates the legacy standard and requires that all P6SGI responses be returned as a [Promise](http://doc.perl6.org/type/Promise). The goal is to try and gain some uniformity in the responses the server must deal with.

0.1.Draft
---------

This is the first published version. It was heavily influenced by PSGI and included interfaces based on the standard, deferred, and streaming responses of PSGI. Instead of callbacks, however, it used [Promise](http://doc.perl6.org/type/Promise) to handle deferred responses and [Channel](http://doc.perl6.org/type/Channel) to handle streaming. It mentioned middleware in passing.



