Shield determines the domain of the request by looking at the Host
header, or if the header is not present, the domain
of the URI.
Shield creates a RequestProcessor
actor for the request with the current configuration of the domain determined in step
one. This includes the current routing table, middleware, listeners, and the proxy actors for each upstream service.
This means each request receives their own actor, allowing Shield to take advantage of Akka’s scaling and reliability mechanisms. Any unexpected error is isolated to the one request, and will not affect any other requests in flight.
The Request Processor prepares the request for processing by making several alterations.
X-Forwarded-For
header is updated with the current connection’s IP.Client-Address
header is added using the address determined by the X-Forwarded-For
header
and the shield.trust-proxies
setting.shield.trust-x-forwarded-proto
config option is set to true, the URI is updated with the correct protocol.ignoreExtensions
setting for the domain contains the extension of the request, the URI is updated to remove
the extension.The Request Processor runs the request through the domain’s Routing Table to determine which upstream services are capable of handling it.
404 Not Found
responseOPTION
requests if no upstream implements one.HEAD
requests if no upstream implements one.405 Method Not Allowed
response.Content-Type
header)
415 Unsupported Media Type
response.Accept
header)
Accept
header, the router filters possible upstreams to those that do not
specify what they can produce406 Not Acceptable
header.There are a few endpoints that Shield implements locally that will return a response. The path can be changed via config, but they will take precedence over any upstream that declares the same endpoint.
If the Routing Table returned a response, that response is immediately forwarded to the client. Otherwise, the Request Processor continues on to the next step.
Based off the destination endpoint selected by the routing table, the Request Process removes any disabled middleware. For each active middleware, the Request Processor sends the current request and waits for the middleware to reply with either a response to send back or a request to send onwards. Each request middleware has the option to register a Response Middleware for intercepting a response.
If the middleware does not respond within the allotted time, the Request Processor advances on to the next middleware, or on to the next stage if no middleware remain.
The Request Processor takes the latest request from the middleware and forwards it on to the Host Proxy. If there are multiple hosts that can satisfy the request, the Request Processor will apply a weighted round-robin load balancing strategy to select one.
At this point the Host Proxy will prepare the request to be forwarded by updating the X-Forwraded-For
header and setting
the Accept-Encoding: gzip
and Connection: Keep-Alive
headers, and then forward it on using the given transport mechanism
for the selected upstream.
The Host Proxy will also apply Circuit Breakers at both
the host level (50 failures, 10 second timeouts, resets after 10 seconds) and the host/endpoint level (25 failures, 10
second timeouts, resets after 10 seconds). These breakers will trip if the upstream endpoint takes too long or responds
with a 5XX Server Error. If the circuit breakers are open, Shield will immediately reply with a 503 Service Unavailable
response. If the request takes too long, Shield will reply with a 504 Gateway Timeout
response.
Once the Request Processor has received a response, whether from a middleware or from the Host Proxy, it will iterate through the Response Middleware that were registered during the “Request Middleware” stage. These middleware have the chance to take some action and reply with a new response to forward.
If the middleware does not respond within the allotted time, the Request Processor advances on to the next middleware, or on to the next stage if no middleware remain.
The Request Processor prepares the response to be sent to the client by adding the Via: 1.1 Shield
header and gzipping
the response if appropriate,
or unzipping the response if necessary.
Once ready, the response is sent to the client.
The Request Processor wraps up by gathering metrics about the various stages and forwards the metrics, the original request, and the final response on to all registered listeners. These listeners usually do logging to some other location, but may also take other actions that don’t need to block the forwarding of the response to the client.
Once done with this stage, the Request Process terminates itself.