vapor-docs/build/2.0/http/middleware/index.html

2013 lines
58 KiB
HTML

<!DOCTYPE html>
<html class="no-js">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="shortcut icon" href="../../assets/images/favicon.png">
<meta name="generator" content="mkdocs-0.16.2, mkdocs-material-1.1.1">
<title>Middleware - Vapor Docs</title>
<script src="../../assets/javascripts/modernizr-56ade86843.js"></script>
<link rel="stylesheet" href="../../assets/stylesheets/application-e5b48ab351.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto Slab:300,400,400i,700|Source+Code+Pro">
<style>body,input{font-family:"Roboto Slab","Helvetica Neue",Helvetica,Arial,sans-serif}code,kbd,pre{font-family:"Source Code Pro","Courier New",Courier,monospace}</style>
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
<link rel="stylesheet" href="../../stylesheets/extra.css">
</head>
<body>
<svg class="md-svg">
<defs>
<svg xmlns="http://www.w3.org/2000/svg" width="416" height="448" viewBox="0 0 416 448" id="github"><path fill="currentColor" d="M160 304q0 10-3.125 20.5t-10.75 19T128 352t-18.125-8.5-10.75-19T96 304t3.125-20.5 10.75-19T128 256t18.125 8.5 10.75 19T160 304zm160 0q0 10-3.125 20.5t-10.75 19T288 352t-18.125-8.5-10.75-19T256 304t3.125-20.5 10.75-19T288 256t18.125 8.5 10.75 19T320 304zm40 0q0-30-17.25-51T296 232q-10.25 0-48.75 5.25Q229.5 240 208 240t-39.25-2.75Q130.75 232 120 232q-29.5 0-46.75 21T56 304q0 22 8 38.375t20.25 25.75 30.5 15 35 7.375 37.25 1.75h42q20.5 0 37.25-1.75t35-7.375 30.5-15 20.25-25.75T360 304zm56-44q0 51.75-15.25 82.75-9.5 19.25-26.375 33.25t-35.25 21.5-42.5 11.875-42.875 5.5T212 416q-19.5 0-35.5-.75t-36.875-3.125-38.125-7.5-34.25-12.875T37 371.5t-21.5-28.75Q0 312 0 260q0-59.25 34-99-6.75-20.5-6.75-42.5 0-29 12.75-54.5 27 0 47.5 9.875t47.25 30.875Q171.5 96 212 96q37 0 70 8 26.25-20.5 46.75-30.25T376 64q12.75 25.5 12.75 54.5 0 21.75-6.75 42 34 40 34 99.5z"/></svg>
</defs>
</svg>
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="drawer">
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="search">
<label class="md-overlay" data-md-component="overlay" for="drawer"></label>
<header class="md-header">
<nav class="md-header-nav md-grid">
<div class="md-flex">
<div class="md-flex__cell md-flex__cell--shrink">
<a href="../.." title="Vapor Docs" class="md-logo md-header-nav__button">
<img src="../../images/droplet-white.svg" width="24" height="24">
</a>
</div>
<div class="md-flex__cell md-flex__cell--shrink">
<label class="md-icon md-icon--menu md-header-nav__button" for="drawer"></label>
</div>
<div class="md-flex__cell md-flex__cell--stretch">
<span class="md-flex__ellipsis md-header-nav__title">
<span class="md-header-nav__parent">
HTTP
</span>
Middleware
</span>
</div>
<div class="md-flex__cell md-flex__cell--shrink">
<label class="md-icon md-icon--search md-header-nav__button" for="search"></label>
<div class="md-search" data-md-component="search">
<div class="md-search__overlay"></div>
<div class="md-search__inner">
<form class="md-search__form" name="search">
<input type="text" class="md-search__input" name="query" placeholder="Search" accesskey="s" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="query">
<label class="md-icon md-search__icon" for="search"></label>
</form>
<div class="md-search__output">
<div class="md-search__scrollwrap" data-md-scrollfix>
<div class="md-search-result" data-md-component="result"></div>
</div>
</div>
</div>
</div>
</div>
<div class="md-flex__cell md-flex__cell--shrink">
<div class="md-header-nav__source">
<a href="https://github.com/vapor/documentation" title="Go to repository" class="md-source" data-md-source="github">
<div class="md-source__icon">
<svg viewBox="0 0 24 24" width="24" height="24">
<use xlink:href="#github" width="24" height="24"></use>
</svg>
</div>
<div class="md-source__repository">
GitHub
</div>
</a>
</div>
</div>
</div>
</nav>
</header>
<div class="md-container">
<main class="md-main">
<div class="md-main__inner md-grid" data-md-component="container">
<div class="md-sidebar md-sidebar--primary" data-md-component="navigation">
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--primary" data-md-level="0">
<label class="md-nav__title md-nav__title--site" for="drawer">
<i class="md-logo md-nav__button">
<img src="../../images/droplet-white.svg">
</i>
Vapor Docs
</label>
<div class="md-nav__source">
<a href="https://github.com/vapor/documentation" title="Go to repository" class="md-source" data-md-source="github">
<div class="md-source__icon">
<svg viewBox="0 0 24 24" width="24" height="24">
<use xlink:href="#github" width="24" height="24"></use>
</svg>
</div>
<div class="md-source__repository">
GitHub
</div>
</a>
</div>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../.." title="Overview" class="md-nav__link">
Overview
</a>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-2" type="checkbox" id="nav-2">
<label class="md-nav__link" for="nav-2">
Getting started
</label>
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
<label class="md-nav__title" for="nav-2">
Getting started
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../getting-started/install-on-macos/" title="Install: macOS" class="md-nav__link">
Install: macOS
</a>
</li>
<li class="md-nav__item">
<a href="../../getting-started/install-on-ubuntu/" title="Install: Ubuntu" class="md-nav__link">
Install: Ubuntu
</a>
</li>
<li class="md-nav__item">
<a href="../../getting-started/toolbox/" title="Toolbox" class="md-nav__link">
Toolbox
</a>
</li>
<li class="md-nav__item">
<a href="../../getting-started/hello-world/" title="Hello, World" class="md-nav__link">
Hello, World
</a>
</li>
<li class="md-nav__item">
<a href="../../getting-started/manual/" title="Manual" class="md-nav__link">
Manual
</a>
</li>
<li class="md-nav__item">
<a href="../../getting-started/xcode/" title="Xcode" class="md-nav__link">
Xcode
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-3" type="checkbox" id="nav-3">
<label class="md-nav__link" for="nav-3">
Vapor
</label>
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
<label class="md-nav__title" for="nav-3">
Vapor
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../vapor/folder-structure/" title="Folder Structure" class="md-nav__link">
Folder Structure
</a>
</li>
<li class="md-nav__item">
<a href="../../vapor/droplet/" title="Droplet" class="md-nav__link">
Droplet
</a>
</li>
<li class="md-nav__item">
<a href="../../vapor/views/" title="Views" class="md-nav__link">
Views
</a>
</li>
<li class="md-nav__item">
<a href="../../vapor/controllers/" title="Controllers" class="md-nav__link">
Controllers
</a>
</li>
<li class="md-nav__item">
<a href="../../vapor/provider/" title="Provider" class="md-nav__link">
Provider
</a>
</li>
<li class="md-nav__item">
<a href="../../vapor/hash/" title="Hash" class="md-nav__link">
Hash
</a>
</li>
<li class="md-nav__item">
<a href="../../vapor/log/" title="Log" class="md-nav__link">
Log
</a>
</li>
<li class="md-nav__item">
<a href="../../vapor/commands/" title="Commands" class="md-nav__link">
Commands
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-4" type="checkbox" id="nav-4">
<label class="md-nav__link" for="nav-4">
Settings
</label>
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
<label class="md-nav__title" for="nav-4">
Settings
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../settings/config/" title="Config" class="md-nav__link">
Config
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-5" type="checkbox" id="nav-5">
<label class="md-nav__link" for="nav-5">
JSON
</label>
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
<label class="md-nav__title" for="nav-5">
JSON
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../json/package/" title="Package" class="md-nav__link">
Package
</a>
</li>
<li class="md-nav__item">
<a href="../../json/overview/" title="Overview" class="md-nav__link">
Overview
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-6" type="checkbox" id="nav-6">
<label class="md-nav__link" for="nav-6">
Routing
</label>
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
<label class="md-nav__title" for="nav-6">
Routing
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../routing/package/" title="Package" class="md-nav__link">
Package
</a>
</li>
<li class="md-nav__item">
<a href="../../routing/overview/" title="Overview" class="md-nav__link">
Overview
</a>
</li>
<li class="md-nav__item">
<a href="../../routing/parameters/" title="Parameters" class="md-nav__link">
Parameters
</a>
</li>
<li class="md-nav__item">
<a href="../../routing/group/" title="Group" class="md-nav__link">
Group
</a>
</li>
<li class="md-nav__item">
<a href="../../routing/collection/" title="Collection" class="md-nav__link">
Collection
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-7" type="checkbox" id="nav-7">
<label class="md-nav__link" for="nav-7">
Fluent
</label>
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
<label class="md-nav__title" for="nav-7">
Fluent
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../fluent/package/" title="Package" class="md-nav__link">
Package
</a>
</li>
<li class="md-nav__item">
<a href="../../fluent/getting-started/" title="Getting Started" class="md-nav__link">
Getting Started
</a>
</li>
<li class="md-nav__item">
<a href="../../fluent/model/" title="Model" class="md-nav__link">
Model
</a>
</li>
<li class="md-nav__item">
<a href="../../fluent/database/" title="Database" class="md-nav__link">
Database
</a>
</li>
<li class="md-nav__item">
<a href="../../fluent/query/" title="Query" class="md-nav__link">
Query
</a>
</li>
<li class="md-nav__item">
<a href="../../fluent/relations/" title="Relations" class="md-nav__link">
Relations
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-8" type="checkbox" id="nav-8">
<label class="md-nav__link" for="nav-8">
Cache
</label>
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
<label class="md-nav__title" for="nav-8">
Cache
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../cache/package/" title="Package" class="md-nav__link">
Package
</a>
</li>
<li class="md-nav__item">
<a href="../../cache/overview/" title="Overview" class="md-nav__link">
Overview
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-9" type="checkbox" id="nav-9">
<label class="md-nav__link" for="nav-9">
MySQL
</label>
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
<label class="md-nav__title" for="nav-9">
MySQL
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../mysql/package/" title="Package" class="md-nav__link">
Package
</a>
</li>
<li class="md-nav__item">
<a href="../../mysql/provider/" title="Provider" class="md-nav__link">
Provider
</a>
</li>
<li class="md-nav__item">
<a href="../../mysql/driver/" title="Driver" class="md-nav__link">
Driver
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-10" type="checkbox" id="nav-10">
<label class="md-nav__link" for="nav-10">
Redis
</label>
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
<label class="md-nav__title" for="nav-10">
Redis
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../redis/package/" title="Package" class="md-nav__link">
Package
</a>
</li>
<li class="md-nav__item">
<a href="../../redis/provider/" title="Provider" class="md-nav__link">
Provider
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-11" type="checkbox" id="nav-11">
<label class="md-nav__link" for="nav-11">
Auth
</label>
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
<label class="md-nav__title" for="nav-11">
Auth
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../auth/package/" title="Package" class="md-nav__link">
Package
</a>
</li>
<li class="md-nav__item">
<a href="../../auth/provider/" title="Provider" class="md-nav__link">
Provider
</a>
</li>
<li class="md-nav__item">
<a href="../../auth/getting-started/" title="Getting Started" class="md-nav__link">
Getting Started
</a>
</li>
<li class="md-nav__item">
<a href="../../auth/helper/" title="Helper" class="md-nav__link">
Helper
</a>
</li>
<li class="md-nav__item">
<a href="../../auth/password/" title="Password" class="md-nav__link">
Password
</a>
</li>
<li class="md-nav__item">
<a href="../../auth/persist/" title="Persist" class="md-nav__link">
Persist
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-12" type="checkbox" id="nav-12">
<label class="md-nav__link" for="nav-12">
Sessions
</label>
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
<label class="md-nav__title" for="nav-12">
Sessions
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../sessions/sessions/" title="Sessions" class="md-nav__link">
Sessions
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--active md-nav__item--nested">
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-13" type="checkbox" id="nav-13" checked>
<label class="md-nav__link" for="nav-13">
HTTP
</label>
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
<label class="md-nav__title" for="nav-13">
HTTP
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../request/" title="Request" class="md-nav__link">
Request
</a>
</li>
<li class="md-nav__item">
<a href="../response/" title="Response" class="md-nav__link">
Response
</a>
</li>
<li class="md-nav__item md-nav__item--active">
<input class="md-toggle md-nav__toggle" data-md-toggle="toc" type="checkbox" id="toc">
<label class="md-nav__link md-nav__link--active" for="toc">
Middleware
</label>
<a href="./" title="Middleware" class="md-nav__link md-nav__link--active">
Middleware
</a>
<nav class="md-nav md-nav--secondary">
<label class="md-nav__title" for="toc">Table of contents</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="#version-middleware" title="Version Middleware" class="md-nav__link">
Version Middleware
</a>
<nav class="md-nav">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#breakdown" title="Breakdown" class="md-nav__link">
Breakdown
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#request" title="Request" class="md-nav__link">
Request
</a>
</li>
<li class="md-nav__item">
<a href="#errors" title="Errors" class="md-nav__link">
Errors
</a>
</li>
<li class="md-nav__item">
<a href="#route-groups" title="Route Groups" class="md-nav__link">
Route Groups
</a>
</li>
<li class="md-nav__item">
<a href="#configuration" title="Configuration" class="md-nav__link">
Configuration
</a>
</li>
<li class="md-nav__item">
<a href="#advanced" title="Advanced" class="md-nav__link">
Advanced
</a>
<nav class="md-nav">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#extensions" title="Extensions" class="md-nav__link">
Extensions
</a>
<nav class="md-nav">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#middleware_1" title="Middleware" class="md-nav__link">
Middleware
</a>
</li>
<li class="md-nav__item">
<a href="#response" title="Response" class="md-nav__link">
Response
</a>
</li>
<li class="md-nav__item">
<a href="#usage" title="Usage" class="md-nav__link">
Usage
</a>
</li>
<li class="md-nav__item">
<a href="#response-representable" title="Response Representable" class="md-nav__link">
Response Representable
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../body/" title="Body" class="md-nav__link">
Body
</a>
</li>
<li class="md-nav__item">
<a href="../response-representable/" title="ResponseRepresentable" class="md-nav__link">
ResponseRepresentable
</a>
</li>
<li class="md-nav__item">
<a href="../responder/" title="Responder" class="md-nav__link">
Responder
</a>
</li>
<li class="md-nav__item">
<a href="../client/" title="Client" class="md-nav__link">
Client
</a>
</li>
<li class="md-nav__item">
<a href="../server/" title="Server" class="md-nav__link">
Server
</a>
</li>
<li class="md-nav__item">
<a href="../cors/" title="CORS" class="md-nav__link">
CORS
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-14" type="checkbox" id="nav-14">
<label class="md-nav__link" for="nav-14">
Leaf
</label>
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
<label class="md-nav__title" for="nav-14">
Leaf
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../leaf/package/" title="Package" class="md-nav__link">
Package
</a>
</li>
<li class="md-nav__item">
<a href="../../leaf/provider/" title="Provider" class="md-nav__link">
Provider
</a>
</li>
<li class="md-nav__item">
<a href="../../leaf/leaf/" title="Overview" class="md-nav__link">
Overview
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../../validation/overview/" title="Validation" class="md-nav__link">
Validation
</a>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-16" type="checkbox" id="nav-16">
<label class="md-nav__link" for="nav-16">
Node
</label>
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
<label class="md-nav__title" for="nav-16">
Node
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../node/package/" title="Package" class="md-nav__link">
Package
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-17" type="checkbox" id="nav-17">
<label class="md-nav__link" for="nav-17">
Core
</label>
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
<label class="md-nav__title" for="nav-17">
Core
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../core/package/" title="Package" class="md-nav__link">
Package
</a>
</li>
<li class="md-nav__item">
<a href="../../core/overview/" title="Overview" class="md-nav__link">
Overview
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-18" type="checkbox" id="nav-18">
<label class="md-nav__link" for="nav-18">
Bits
</label>
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
<label class="md-nav__title" for="nav-18">
Bits
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../bits/package/" title="Package" class="md-nav__link">
Package
</a>
</li>
<li class="md-nav__item">
<a href="../../bits/overview/" title="Overview" class="md-nav__link">
Overview
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-19" type="checkbox" id="nav-19">
<label class="md-nav__link" for="nav-19">
Debugging
</label>
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
<label class="md-nav__title" for="nav-19">
Debugging
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../debugging/package/" title="Package" class="md-nav__link">
Package
</a>
</li>
<li class="md-nav__item">
<a href="../../debugging/overview/" title="Overview" class="md-nav__link">
Overview
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-20" type="checkbox" id="nav-20">
<label class="md-nav__link" for="nav-20">
Advanced
</label>
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
<label class="md-nav__title" for="nav-20">
Advanced
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../advanced/modules/" title="Modules" class="md-nav__link">
Modules
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-21" type="checkbox" id="nav-21">
<label class="md-nav__link" for="nav-21">
Version (2.0)
</label>
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
<label class="md-nav__title" for="nav-21">
Version (2.0)
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../switch/1_5/" title="1.5" class="md-nav__link">
1.5
</a>
</li>
<li class="md-nav__item">
<a href="../../switch/2_0/" title="2.0" class="md-nav__link">
2.0
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-sidebar md-sidebar--secondary" data-md-component="toc">
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--secondary">
<label class="md-nav__title" for="toc">Table of contents</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="#version-middleware" title="Version Middleware" class="md-nav__link">
Version Middleware
</a>
<nav class="md-nav">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#breakdown" title="Breakdown" class="md-nav__link">
Breakdown
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#request" title="Request" class="md-nav__link">
Request
</a>
</li>
<li class="md-nav__item">
<a href="#errors" title="Errors" class="md-nav__link">
Errors
</a>
</li>
<li class="md-nav__item">
<a href="#route-groups" title="Route Groups" class="md-nav__link">
Route Groups
</a>
</li>
<li class="md-nav__item">
<a href="#configuration" title="Configuration" class="md-nav__link">
Configuration
</a>
</li>
<li class="md-nav__item">
<a href="#advanced" title="Advanced" class="md-nav__link">
Advanced
</a>
<nav class="md-nav">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#extensions" title="Extensions" class="md-nav__link">
Extensions
</a>
<nav class="md-nav">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#middleware_1" title="Middleware" class="md-nav__link">
Middleware
</a>
</li>
<li class="md-nav__item">
<a href="#response" title="Response" class="md-nav__link">
Response
</a>
</li>
<li class="md-nav__item">
<a href="#usage" title="Usage" class="md-nav__link">
Usage
</a>
</li>
<li class="md-nav__item">
<a href="#response-representable" title="Response Representable" class="md-nav__link">
Response Representable
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-content">
<article class="md-content__inner md-typeset">
<a href="https://github.com/vapor/documentation/edit/master/2.0/docs/http/middleware.md" title="Edit this page" class="md-icon md-content__edit">edit</a>
<h1 id="middleware">Middleware<a class="headerlink" href="#middleware" title="Permanent link">&para;</a></h1>
<p>Middleware is an essential part of any modern web framework. It allows you to modify requests and responses as they pass between the client and your server.</p>
<p>You can imagine middleware as a chain of logic connecting your server to the client requesting your web app.</p>
<h2 id="version-middleware">Version Middleware<a class="headerlink" href="#version-middleware" title="Permanent link">&para;</a></h2>
<p>As an example, let's create a middleware that will add the version of our API to each response. The middleware would look something like this:</p>
<div class="codehilite"><pre><span></span><span class="kd">import</span> <span class="nc">HTTP</span>
<span class="kr">final</span> <span class="kd">class</span> <span class="nc">VersionMiddleware</span><span class="p">:</span> <span class="n">Middleware</span> <span class="p">{</span>
<span class="kd">func</span> <span class="nf">respond</span><span class="p">(</span><span class="n">to</span> <span class="n">request</span><span class="p">:</span> <span class="n">Request</span><span class="p">,</span> <span class="n">chainingTo</span> <span class="n">next</span><span class="p">:</span> <span class="n">Responder</span><span class="p">)</span> <span class="kr">throws</span> <span class="p">-&gt;</span> <span class="n">Response</span> <span class="p">{</span>
<span class="kd">let</span> <span class="nv">response</span> <span class="p">=</span> <span class="k">try</span> <span class="n">next</span><span class="p">.</span><span class="n">respond</span><span class="p">(</span><span class="n">to</span><span class="p">:</span> <span class="n">request</span><span class="p">)</span>
<span class="n">response</span><span class="p">.</span><span class="n">headers</span><span class="p">[</span><span class="s">&quot;Version&quot;</span><span class="p">]</span> <span class="p">=</span> <span class="s">&quot;API v1.0&quot;</span>
<span class="k">return</span> <span class="n">response</span>
<span class="p">}</span>
<span class="p">}</span>
</pre></div>
<p>We then supply this middleware to our <code>Droplet</code>.</p>
<div class="codehilite"><pre><span></span><span class="kd">let</span> <span class="nv">drop</span> <span class="p">=</span> <span class="n">Droplet</span><span class="p">()</span>
<span class="n">drop</span><span class="p">.</span><span class="n">middleware</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">VersionMiddleware</span><span class="p">())</span>
</pre></div>
<p>You can imagine our <code>VersionMiddleware</code> sitting in the middle of a chain that connects the client and our server. Every request and response that hits our server must go through this chain of middleware.</p>
<p><img alt="Middleware" src="https://cloud.githubusercontent.com/assets/1342803/17382676/0b51d6d6-59a0-11e6-9cbb-7585b9ab9803.png" /></p>
<h3 id="breakdown">Breakdown<a class="headerlink" href="#breakdown" title="Permanent link">&para;</a></h3>
<p>Let's break down the middleware line by line.</p>
<div class="codehilite"><pre><span></span><span class="kd">let</span> <span class="nv">response</span> <span class="p">=</span> <span class="k">try</span> <span class="n">next</span><span class="p">.</span><span class="n">respond</span><span class="p">(</span><span class="n">to</span><span class="p">:</span> <span class="n">request</span><span class="p">)</span>
</pre></div>
<p>Since the <code>VersionMiddleware</code> in this example is not interested in modifying the request, we immediately ask the next middleware in the chain to respond to the request. This goes all the way down the chain to the <code>Droplet</code> and comes back with the response that should be sent to the client.</p>
<div class="codehilite"><pre><span></span><span class="n">response</span><span class="p">.</span><span class="n">headers</span><span class="p">[</span><span class="s">&quot;Version&quot;</span><span class="p">]</span> <span class="p">=</span> <span class="s">&quot;API v1.0&quot;</span>
</pre></div>
<p>We then <em>modify</em> the response to contain a Version header.</p>
<div class="codehilite"><pre><span></span><span class="k">return</span> <span class="n">response</span>
</pre></div>
<p>The response is returned and will chain back up any remaining middleware and back to the client.</p>
<h2 id="request">Request<a class="headerlink" href="#request" title="Permanent link">&para;</a></h2>
<p>The middleware can also modify or interact with the request.</p>
<div class="codehilite"><pre><span></span><span class="kd">func</span> <span class="nf">respond</span><span class="p">(</span><span class="n">to</span> <span class="n">request</span><span class="p">:</span> <span class="n">Request</span><span class="p">,</span> <span class="n">chainingTo</span> <span class="n">next</span><span class="p">:</span> <span class="n">Responder</span><span class="p">)</span> <span class="kr">throws</span> <span class="p">-&gt;</span> <span class="n">Response</span> <span class="p">{</span>
<span class="k">guard</span> <span class="n">request</span><span class="p">.</span><span class="n">cookies</span><span class="p">[</span><span class="s">&quot;token&quot;</span><span class="p">]</span> <span class="p">==</span> <span class="s">&quot;secret&quot;</span> <span class="k">else</span> <span class="p">{</span>
<span class="k">throw</span> <span class="n">Abort</span><span class="p">(.</span><span class="n">badRequest</span><span class="p">)</span>
<span class="p">}</span>
<span class="k">return</span> <span class="k">try</span> <span class="n">next</span><span class="p">.</span><span class="n">respond</span><span class="p">(</span><span class="n">to</span><span class="p">:</span> <span class="n">request</span><span class="p">)</span>
<span class="p">}</span>
</pre></div>
<p>This middleware will require that the request has a cookie named <code>token</code> that equals <code>secret</code> or else the request will be aborted.</p>
<h2 id="errors">Errors<a class="headerlink" href="#errors" title="Permanent link">&para;</a></h2>
<p>Middleware is the perfect place to catch errors thrown from anywhere in your application. When you let the middleware catch errors, you can remove a lot of duplicated logic from your route closures. Take a look at the following example:</p>
<div class="codehilite"><pre><span></span><span class="kd">enum</span> <span class="nc">FooError</span><span class="p">:</span> <span class="n">Error</span> <span class="p">{</span>
<span class="k">case</span> <span class="n">fooServiceUnavailable</span>
<span class="p">}</span>
</pre></div>
<p>Say there is a custom error that either you defined or one of the APIs you are using <code>throws</code>. This error must be caught when thrown, or else it will end up as an internal server error (500) which may be unexpected to a user. The most obvious solution is to catch the error in the route closure.</p>
<div class="codehilite"><pre><span></span><span class="n">app</span><span class="p">.</span><span class="kr">get</span><span class="p">(</span><span class="s">&quot;foo&quot;</span><span class="p">)</span> <span class="p">{</span> <span class="n">request</span> <span class="k">in</span>
<span class="kd">let</span> <span class="nv">foo</span><span class="p">:</span> <span class="n">Foo</span>
<span class="k">do</span> <span class="p">{</span>
<span class="n">foo</span> <span class="p">=</span> <span class="k">try</span> <span class="n">getFooFromService</span><span class="p">()</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">{</span>
<span class="k">throw</span> <span class="n">Abort</span><span class="p">(.</span><span class="n">badRequest</span><span class="p">)</span>
<span class="p">}</span>
<span class="c1">// continue with Foo object</span>
<span class="p">}</span>
</pre></div>
<p>This solution works, but it would get repetitive if multiple routes need to handle the error. Luckily, this error could be caught in a middleware instead.</p>
<div class="codehilite"><pre><span></span><span class="kr">final</span> <span class="kd">class</span> <span class="nc">FooErrorMiddleware</span><span class="p">:</span> <span class="n">Middleware</span> <span class="p">{</span>
<span class="kd">func</span> <span class="nf">respond</span><span class="p">(</span><span class="n">to</span> <span class="n">request</span><span class="p">:</span> <span class="n">Request</span><span class="p">,</span> <span class="n">chainingTo</span> <span class="n">next</span><span class="p">:</span> <span class="n">Responder</span><span class="p">)</span> <span class="kr">throws</span> <span class="p">-&gt;</span> <span class="n">Response</span> <span class="p">{</span>
<span class="k">do</span> <span class="p">{</span>
<span class="k">return</span> <span class="k">try</span> <span class="n">next</span><span class="p">.</span><span class="n">respond</span><span class="p">(</span><span class="n">to</span><span class="p">:</span> <span class="n">request</span><span class="p">)</span>
<span class="p">}</span> <span class="k">catch</span> <span class="n">FooError</span><span class="p">.</span><span class="n">fooServiceUnavailable</span> <span class="p">{</span>
<span class="k">throw</span> <span class="n">Abort</span><span class="p">(</span>
<span class="p">.</span><span class="n">badRequest</span><span class="p">,</span>
<span class="n">reason</span><span class="p">:</span> <span class="s">&quot;Sorry, we were unable to query the Foo service.&quot;</span>
<span class="p">)</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
</pre></div>
<p>We just need to append this middleware to the <code>Droplet</code>.</p>
<div class="codehilite"><pre><span></span><span class="n">drop</span><span class="p">.</span><span class="n">middleware</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">FooErrorMiddleware</span><span class="p">())</span>
</pre></div>
<p>Now our route closures look a lot better and we don't have to worry about code duplication.</p>
<div class="codehilite"><pre><span></span><span class="n">app</span><span class="p">.</span><span class="kr">get</span><span class="p">(</span><span class="s">&quot;foo&quot;</span><span class="p">)</span> <span class="p">{</span> <span class="n">request</span> <span class="k">in</span>
<span class="kd">let</span> <span class="nv">foo</span> <span class="p">=</span> <span class="k">try</span> <span class="n">getFooFromService</span><span class="p">()</span>
<span class="c1">// continue with Foo object</span>
<span class="p">}</span>
</pre></div>
<h2 id="route-groups">Route Groups<a class="headerlink" href="#route-groups" title="Permanent link">&para;</a></h2>
<p>For more granularity, Middleware can be applied to specific route groups.</p>
<div class="codehilite"><pre><span></span><span class="kd">let</span> <span class="nv">authed</span> <span class="p">=</span> <span class="n">drop</span><span class="p">.</span><span class="n">grouped</span><span class="p">(</span><span class="n">AuthMiddleware</span><span class="p">())</span>
<span class="n">authed</span><span class="p">.</span><span class="kr">get</span><span class="p">(</span><span class="s">&quot;secure&quot;</span><span class="p">)</span> <span class="p">{</span> <span class="n">req</span> <span class="k">in</span>
<span class="k">return</span> <span class="n">Secrets</span><span class="p">.</span><span class="n">all</span><span class="p">().</span><span class="n">makeJSON</span><span class="p">()</span>
<span class="p">}</span>
</pre></div>
<p>Anything added to the <code>authed</code> group must pass through <code>AuthMiddleware</code>. Because of this, we can assume all traffic to <code>/secure</code> has been authorized. Learn more in <a href="../../routing/group">Routing</a>.</p>
<h2 id="configuration">Configuration<a class="headerlink" href="#configuration" title="Permanent link">&para;</a></h2>
<p>Appending middleware to the <code>drop.middleware</code> array is the simplest way to add middleware--it will be used every time the application starts.</p>
<p>You can also use the <a href="../../settings/config/">configuration</a> files to enabled or disable middleware for more control. This is especially useful if you have middleware that should, for example, run only in production.</p>
<p>Appending configurable middleware looks like the following:</p>
<div class="codehilite"><pre><span></span><span class="kd">let</span> <span class="nv">drop</span> <span class="p">=</span> <span class="n">Droplet</span><span class="p">()</span>
<span class="n">drop</span><span class="p">.</span><span class="n">addConfigurable</span><span class="p">(</span><span class="n">middleware</span><span class="p">:</span> <span class="n">myMiddleware</span><span class="p">,</span> <span class="n">name</span><span class="p">:</span> <span class="s">&quot;my-middleware&quot;</span><span class="p">)</span>
</pre></div>
<p>Then, in the <code>Config/droplet.json</code> file, add <code>my-middleware</code> to the appropriate <code>middleware</code> array.</p>
<div class="codehilite"><pre><span></span><span class="p">{</span>
<span class="err">...</span>
<span class="nt">&quot;middleware&quot;</span><span class="p">:</span> <span class="p">{</span>
<span class="nt">&quot;server&quot;</span><span class="p">:</span> <span class="p">[</span>
<span class="err">...</span>
<span class="s2">&quot;my-middleware&quot;</span><span class="p">,</span>
<span class="err">...</span>
<span class="p">],</span>
<span class="nt">&quot;client&quot;</span><span class="p">:</span> <span class="p">[</span>
<span class="err">...</span>
<span class="p">]</span>
<span class="p">},</span>
<span class="err">...</span>
<span class="p">}</span>
</pre></div>
<p>If the name of the added middleware appears in the <code>server</code> array for the loaded configuration, it will be added to the server's middleware when the application boots.</p>
<p>Likewise, if the middleware appears in the <code>client</code> array for the loaded configuration, it will be added to the client's middleware.</p>
<p>One middleware can be appended to both the Client and the Server, and can be added multiple times. The ordering of middleware is respected.</p>
<h2 id="advanced">Advanced<a class="headerlink" href="#advanced" title="Permanent link">&para;</a></h2>
<h3 id="extensions">Extensions<a class="headerlink" href="#extensions" title="Permanent link">&para;</a></h3>
<p>Middleware pairs great with request/response extensions and storage. This example shows you how to dynamically return either HTML or JSON responses for a Model depending on the type of client.</p>
<h4 id="middleware_1">Middleware<a class="headerlink" href="#middleware_1" title="Permanent link">&para;</a></h4>
<div class="codehilite"><pre><span></span><span class="kr">final</span> <span class="kd">class</span> <span class="nc">PokemonMiddleware</span><span class="p">:</span> <span class="n">Middleware</span> <span class="p">{</span>
<span class="kd">let</span> <span class="nv">view</span><span class="p">:</span> <span class="n">ViewProtocol</span>
<span class="kd">init</span><span class="p">(</span><span class="kc">_</span> <span class="n">view</span><span class="p">:</span> <span class="n">ViewProtocol</span><span class="p">)</span> <span class="p">{</span>
<span class="kc">self</span><span class="p">.</span><span class="n">view</span> <span class="p">=</span> <span class="n">view</span>
<span class="p">}</span>
<span class="kd">func</span> <span class="nf">respond</span><span class="p">(</span><span class="n">to</span> <span class="n">request</span><span class="p">:</span> <span class="n">Request</span><span class="p">,</span> <span class="n">chainingTo</span> <span class="n">next</span><span class="p">:</span> <span class="n">Responder</span><span class="p">)</span> <span class="kr">throws</span> <span class="p">-&gt;</span> <span class="n">Response</span> <span class="p">{</span>
<span class="kd">let</span> <span class="nv">response</span> <span class="p">=</span> <span class="k">try</span> <span class="n">next</span><span class="p">.</span><span class="n">respond</span><span class="p">(</span><span class="n">to</span><span class="p">:</span> <span class="n">request</span><span class="p">)</span>
<span class="k">if</span> <span class="kd">let</span> <span class="nv">pokemon</span> <span class="p">=</span> <span class="n">response</span><span class="p">.</span><span class="n">pokemon</span> <span class="p">{</span>
<span class="k">if</span> <span class="n">request</span><span class="p">.</span><span class="n">accept</span><span class="p">.</span><span class="n">prefers</span><span class="p">(</span><span class="s">&quot;html&quot;</span><span class="p">)</span> <span class="p">{</span>
<span class="n">response</span><span class="p">.</span><span class="n">view</span> <span class="p">=</span> <span class="k">try</span> <span class="n">view</span><span class="p">.</span><span class="n">make</span><span class="p">(</span><span class="s">&quot;pokemon.mustache&quot;</span><span class="p">,</span> <span class="n">pokemon</span><span class="p">)</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="n">response</span><span class="p">.</span><span class="n">json</span> <span class="p">=</span> <span class="k">try</span> <span class="n">pokemon</span><span class="p">.</span><span class="n">makeJSON</span><span class="p">()</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">return</span> <span class="n">response</span>
<span class="p">}</span>
<span class="p">}</span>
</pre></div>
<h4 id="response">Response<a class="headerlink" href="#response" title="Permanent link">&para;</a></h4>
<p>And the extension to <code>Response</code>.</p>
<div class="codehilite"><pre><span></span><span class="kd">extension</span> <span class="nc">Response</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nv">pokemon</span><span class="p">:</span> <span class="n">Pokemon</span><span class="p">?</span> <span class="p">{</span>
<span class="kr">get</span> <span class="p">{</span> <span class="k">return</span> <span class="n">storage</span><span class="p">[</span><span class="s">&quot;pokemon&quot;</span><span class="p">]</span> <span class="k">as</span><span class="p">?</span> <span class="n">Pokemon</span> <span class="p">}</span>
<span class="kr">set</span> <span class="p">{</span> <span class="n">storage</span><span class="p">[</span><span class="s">&quot;pokemon&quot;</span><span class="p">]</span> <span class="p">=</span> <span class="n">newValue</span> <span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
</pre></div>
<p>In this example, we added a new property to response capable of holding a Pokémon object. If the middleware finds a response with one of these Pokémon objects, it will dynamically check whether the client prefers HTML. If the client is a browser like Safari and prefers HTML, it will return a Mustache view. If the client does not prefer HTML, it will return JSON.</p>
<h4 id="usage">Usage<a class="headerlink" href="#usage" title="Permanent link">&para;</a></h4>
<p>Your closures can now look something like this:</p>
<div class="codehilite"><pre><span></span><span class="kd">import</span> <span class="nc">Vapor</span>
<span class="kd">import</span> <span class="nc">HTTP</span>
<span class="kd">let</span> <span class="nv">drop</span> <span class="p">=</span> <span class="k">try</span> <span class="n">Droplet</span><span class="p">()</span>
<span class="kd">let</span> <span class="nv">pokemonMiddleware</span> <span class="p">=</span> <span class="n">PokemonMiddleware</span><span class="p">(</span><span class="n">drop</span><span class="p">.</span><span class="n">view</span><span class="p">)</span>
<span class="n">drop</span><span class="p">.</span><span class="n">middleware</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">pokemonMiddleware</span><span class="p">)</span>
<span class="n">drop</span><span class="p">.</span><span class="kr">get</span><span class="p">(</span><span class="s">&quot;pokemon&quot;</span><span class="p">,</span> <span class="n">Pokemon</span><span class="p">.</span><span class="kc">self</span><span class="p">)</span> <span class="p">{</span> <span class="n">request</span><span class="p">,</span> <span class="n">pokemon</span> <span class="k">in</span>
<span class="kd">let</span> <span class="nv">response</span> <span class="p">=</span> <span class="n">Response</span><span class="p">()</span>
<span class="n">response</span><span class="p">.</span><span class="n">pokemon</span> <span class="p">=</span> <span class="n">pokemon</span>
<span class="k">return</span> <span class="n">response</span>
<span class="p">}</span>
</pre></div>
<h4 id="response-representable">Response Representable<a class="headerlink" href="#response-representable" title="Permanent link">&para;</a></h4>
<p>If you want to go a step further, you can make <code>Pokemon</code> conform to <code>ResponseRepresentable</code>.</p>
<div class="codehilite"><pre><span></span><span class="kd">import</span> <span class="nc">HTTP</span>
<span class="kd">extension</span> <span class="nc">Pokemon</span><span class="p">:</span> <span class="n">ResponseRepresentable</span> <span class="p">{</span>
<span class="kd">func</span> <span class="nf">makeResponse</span><span class="p">()</span> <span class="kr">throws</span> <span class="p">-&gt;</span> <span class="n">Response</span> <span class="p">{</span>
<span class="kd">let</span> <span class="nv">response</span> <span class="p">=</span> <span class="n">Response</span><span class="p">()</span>
<span class="n">response</span><span class="p">.</span><span class="n">pokemon</span> <span class="p">=</span> <span class="kc">self</span>
<span class="k">return</span> <span class="n">response</span>
<span class="p">}</span>
<span class="p">}</span>
</pre></div>
<p>Now your route closures are greatly simplified.</p>
<div class="codehilite"><pre><span></span><span class="n">drop</span><span class="p">.</span><span class="kr">get</span><span class="p">(</span><span class="s">&quot;pokemon&quot;</span><span class="p">,</span> <span class="n">Pokemon</span><span class="p">.</span><span class="kc">self</span><span class="p">)</span> <span class="p">{</span> <span class="n">request</span><span class="p">,</span> <span class="n">pokemon</span> <span class="k">in</span>
<span class="k">return</span> <span class="n">pokemon</span>
<span class="p">}</span>
</pre></div>
<p>Middleware is incredibly powerful. Combined with extensions, it allows you to add functionality that feels native to the framework.</p>
</article>
</div>
</div>
</main>
<footer class="md-footer">
<div class="md-footer-nav">
<nav class="md-footer-nav__inner md-grid">
<a href="../response/" title="Response" class="md-flex md-footer-nav__link md-footer-nav__link--prev" rel="prev">
<div class="md-flex__cell md-flex__cell--shrink">
<i class="md-icon md-icon--arrow-back md-footer-nav__button"></i>
</div>
<div class="md-flex__cell md-flex__cell--stretch md-footer-nav__title">
<span class="md-flex__ellipsis">
<span class="md-footer-nav__direction">
Previous
</span>
Response
</span>
</div>
</a>
<a href="../body/" title="Body" class="md-flex md-footer-nav__link md-footer-nav__link--next" rel="next">
<div class="md-flex__cell md-flex__cell--stretch md-footer-nav__title">
<span class="md-flex__ellipsis">
<span class="md-footer-nav__direction">
Next
</span>
Body
</span>
</div>
<div class="md-flex__cell md-flex__cell--shrink">
<i class="md-icon md-icon--arrow-forward md-footer-nav__button"></i>
</div>
</a>
</nav>
</div>
<div class="md-footer-meta md-typeset">
<div class="md-footer-meta__inner md-grid">
<div class="md-footer-copyright">
<div class="md-footer-copyright__highlight">
Copyright &copy; 2017 Qutheory, LLC
</div>
powered by
<a href="http://www.mkdocs.org" title="MkDocs">MkDocs</a>
and
<a href="http://squidfunk.github.io/mkdocs-material/" title="Material for MkDocs">
Material for MkDocs</a>
</div>
<div class="md-footer-social">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<a href="https://twitter.com/@codevapor" class="md-footer-social__link fa fa-twitter"></a>
<a href="http://vapor.team/" class="md-footer-social__link fa fa-slack"></a>
</div>
</div>
</div>
</footer>
</div>
<script src="../../assets/javascripts/application-f6cd941c96.js"></script>
<script>app.initialize({url:{base:"../.."}})</script>
<script>!function(e,t,n,a,o,c,i){e.GoogleAnalyticsObject=o,e[o]=e[o]||function(){(e[o].q=e[o].q||[]).push(arguments)},e[o].l=1*new Date,c=t.createElement(n),i=t.getElementsByTagName(n)[0],c.async=1,c.src=a,i.parentNode.insertBefore(c,i)}(window,document,"script","https://www.google-analytics.com/analytics.js","ga"),ga("create","UA-76177358-4","auto"),ga("set","anonymizeIp",!0),ga("send","pageview");var links=document.getElementsByTagName("a");Array.prototype.map.call(links,function(e){e.host!=document.location.host&&e.addEventListener("click",function(){var t=e.getAttribute("data-md-action")||"follow";ga("send","event","outbound",t,e.href)})}),document.forms.search.query.addEventListener("blur",function(){if(this.value){var e=document.location.pathname;ga("send","pageview",e+"?q="+this.value)}})</script>
</body>
</html>