mirror of https://github.com/vapor/docs.git
594 lines
26 KiB
HTML
594 lines
26 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
|
|
<title>Vapor Documentation</title>
|
|
|
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Code+Pro">
|
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Quicksand:400,700,300">
|
|
<link rel="stylesheet" href="/1.5/styles/vapor-code.css">
|
|
<link rel="stylesheet" href="/1.5/styles/main.css">
|
|
</head>
|
|
<body>
|
|
|
|
<header>
|
|
<a class="logo" href="/1.5/">
|
|
<img src="/1.5/images/droplet.svg" alt="Vapor">
|
|
<h1>Vapor <em>Docs</em></h1>
|
|
</a>
|
|
<ul>
|
|
<li>
|
|
<a href="http://vapor.codes">Home</a>
|
|
</li>
|
|
<li>
|
|
<a href="http://example.vapor.codes">Example</a>
|
|
</li>
|
|
<li>
|
|
<a href="https://github.com/vapor/vapor">GitHub</a>
|
|
</li>
|
|
<li>
|
|
<a href="https://twitter.com/@codevapor">Twitter</a>
|
|
</li>
|
|
<li>
|
|
<a href="http://vapor.team">Slack</a>
|
|
</li>
|
|
</ul>
|
|
</header>
|
|
|
|
|
|
|
|
<nav>
|
|
<a href="#" class="toggle show">☰</a>
|
|
<a href="#" class="toggle close">×</a>
|
|
|
|
<div class="scroll">
|
|
<section>
|
|
<h3>Getting Started</h3>
|
|
<ul>
|
|
<li class="">
|
|
<a href="/1.5/getting-started/install-swift-3-macos.html">
|
|
Install Swift 3: macOS
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/getting-started/install-swift-3-ubuntu.html">
|
|
Install Swift 3: Ubuntu
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/getting-started/install-toolbox.html">
|
|
Install Toolbox
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/getting-started/hello-world.html">
|
|
Hello, World
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/getting-started/manual.html">
|
|
Manual
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/getting-started/xcode.html">
|
|
Xcode
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</section>
|
|
<section>
|
|
<h3>Guide</h3>
|
|
<ul>
|
|
<li class="">
|
|
<a href="/1.5/guide/droplet.html">
|
|
Droplet
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/guide/folder-structure.html">
|
|
Folder Structure
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/guide/json.html">
|
|
JSON
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/guide/config.html">
|
|
Config
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/guide/views.html">
|
|
Views
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/guide/leaf.html">
|
|
Leaf
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/guide/controllers.html">
|
|
Controllers
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/guide/middleware.html">
|
|
Middleware
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/guide/validation.html">
|
|
Validation
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/guide/provider.html">
|
|
Provider
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/guide/sessions.html">
|
|
Sessions
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/guide/hash.html">
|
|
Hash
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/guide/commands.html">
|
|
Commands
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</section>
|
|
<section>
|
|
<h3>Routing</h3>
|
|
<ul>
|
|
<li class="">
|
|
<a href="/1.5/routing/basic.html">
|
|
Basic
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/routing/parameters.html">
|
|
Route Parameters
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/routing/query-parameters.html">
|
|
Query Parameters
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/routing/group.html">
|
|
Group
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/routing/collection.html">
|
|
Collection
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</section>
|
|
<section>
|
|
<h3>Fluent</h3>
|
|
<ul>
|
|
<li class="">
|
|
<a href="/1.5/fluent/driver.html">
|
|
Driver
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/fluent/model.html">
|
|
Model
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/fluent/query.html">
|
|
Query
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/fluent/relation.html">
|
|
Relation
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</section>
|
|
<section>
|
|
<h3>Auth</h3>
|
|
<ul>
|
|
<li class="">
|
|
<a href="/1.5/auth/user.html">
|
|
User
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/auth/middleware.html">
|
|
Middleware
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/auth/request.html">
|
|
Request
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/auth/protect.html">
|
|
Protect
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</section>
|
|
<section>
|
|
<h3>HTTP</h3>
|
|
<ul>
|
|
<li class="active">
|
|
<a href="/1.5/http/request.html">
|
|
Request
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/http/response.html">
|
|
Response
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/http/body.html">
|
|
Body
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/http/response-representable.html">
|
|
ResponseRepresentable
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/http/responder.html">
|
|
Responder
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/http/client.html">
|
|
Client
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/http/server.html">
|
|
Server
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/http/cors.html">
|
|
CORS
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</section>
|
|
<section>
|
|
<h3>WebSockets</h3>
|
|
<ul>
|
|
<li class="">
|
|
<a href="/1.5/websockets/droplet.html">
|
|
Droplet
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/websockets/custom.html">
|
|
Custom
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</section>
|
|
<section>
|
|
<h3>Testing</h3>
|
|
<ul>
|
|
<li class="">
|
|
<a href="/1.5/testing/modules.html">
|
|
Modules
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/testing/basic.html">
|
|
Basic
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</section>
|
|
<section>
|
|
<h3>Deploy</h3>
|
|
<ul>
|
|
<li class="">
|
|
<a href="/1.5/deploy/nginx.html">
|
|
Nginx
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/deploy/supervisor.html">
|
|
Supervisor
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</section>
|
|
<section>
|
|
<h3>Version (1.5)</h3>
|
|
<ul>
|
|
<li class="">
|
|
<a href="/1.5/switch/1_5.html">
|
|
1.5
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/switch/2_0.html">
|
|
2.0
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</section>
|
|
</div>
|
|
</nav>
|
|
|
|
<main>
|
|
<a href="https://github.com/vapor/documentation/blob/master/CONTRIBUTING.md" class="edit">✎ Edit on GitHub</a>
|
|
<blockquote>
|
|
<p>Module: <code>import HTTP</code></p>
|
|
</blockquote>
|
|
<h1 id="request">Request</h1>
|
|
<p>The most common part of the <code>HTTP</code> library we'll be interacting with is the <code>Request</code> type. Here's a look at some of the most commonly used attributes in this type.</p>
|
|
<pre><code class="language-swift">public var method: Method
|
|
public var uri: URI
|
|
public var parameters: Node
|
|
public var headers: [HeaderKey: String]
|
|
public var body: Body
|
|
public var data: Content</code></pre>
|
|
<h3 id="method">Method</h3>
|
|
<p>The HTTP <code>Method</code> associated with the <code>Request</code>, ie: <code>GET</code>, <code>POST</code>, <code>PUT</code>, <code>PATCH</code>, <code>DELETE</code>.</p>
|
|
<h3 id="uri">URI</h3>
|
|
<p>The associated <code>URI</code> of the request. We will use this to access attributes about the <code>uri</code> the request was sent to.</p>
|
|
<p>For example, given the following uri: <code>http://vapor.codes/example?query=hi#fragments-too</code></p>
|
|
<pre><code class="language-swift">let scheme = request.uri.scheme // http
|
|
let host = request.uri.host // vapor.codes
|
|
|
|
let path = request.uri.path // /example
|
|
let query = request.uri.query // query=hi
|
|
let fragment = request.uri.fragment // fragments-too</code></pre>
|
|
<h3 id="route-parameters">Route Parameters</h3>
|
|
<p>The url parameters associated with the request. For example, if we have a path registered as <code>hello/:name/age/:age</code>, we would be able to access those in our request, like so:</p>
|
|
<pre><code class="language-swift">let name = request.parameters["name"] // String?
|
|
let age = request.parameters["age"]?.int // Int?</code></pre>
|
|
<p>Or, to automatically throw on <code>nil</code> or invalid variable, you can also <code>extract</code></p>
|
|
<pre><code class="language-swift">let name = try request.parameters.extract("name") as String
|
|
let age = try request.parameters.extract("age") as Int</code></pre>
|
|
<p>These extract functions can cast to any <code>NodeInitializable</code> type, including your own custom types. Make sure to check out <a href="https://github.com/vapor/node">Node</a> for more info.</p>
|
|
<blockquote>
|
|
<p>Note: Vapor also provides type safe routing in the routing section of our docs.</p>
|
|
</blockquote>
|
|
<h3 id="headers">Headers</h3>
|
|
<p>These are the headers associated with the request. If you are preparing an outgoing request, this can be used to add your own keys.</p>
|
|
<pre><code class="language-swift">let contentType = request.headers["Content-Type"] </code></pre>
|
|
<p>Or for outgoing requests:</p>
|
|
<pre><code class="language-swift">let request = Request ...
|
|
request.headers["Content-Type"] = "application/json"
|
|
request.headers["Authorization"] = ... my auth token</code></pre>
|
|
<h4 id="extending-headers">Extending Headers</h4>
|
|
<p>We generally seek to improve code bases by removing stringly typed code where possible. We can add variables to the headers using generic extensions.</p>
|
|
<pre><code class="language-swift">extension HTTP.KeyAccessible where Key == HeaderKey, Value == String {
|
|
var customKey: String? {
|
|
get {
|
|
return self["Custom-Key"]
|
|
}
|
|
set {
|
|
self["Custom-Key"] = newValue
|
|
}
|
|
}
|
|
}</code></pre>
|
|
<p>With this pattern implemented, our string <code>"Custom-Key"</code> is contained in one section of our code. We can now access like this:</p>
|
|
<pre><code class="language-swift">let customKey = request.headers.customKey
|
|
|
|
// or
|
|
|
|
let request = ...
|
|
request.headers.customKey = "my custom value"</code></pre>
|
|
<h3 id="body">Body</h3>
|
|
<p>This is the body associated with the request and represents the general data payload. You can view more about body in the associated <a href="./body.html">docs</a></p>
|
|
<p>For incoming requests, we'll often pull out the associated bytes like so:</p>
|
|
<pre><code class="language-swift">let rawBytes = request.body.bytes</code></pre>
|
|
<h2 id="content">Content</h2>
|
|
<p>Generally when we're sending or receiving requests, we're using them as a way to transport content. For this, Vapor provides a convenient <code>data</code> variable associated with the request that prioritizes content in a consistent way.</p>
|
|
<p>For example, say I receive a request to <code>http://vapor.codes?hello=world</code>.</p>
|
|
<pre><code class="language-swift">let world = request.data["hello"]?.string</code></pre>
|
|
<p>This same code will work if I receive a JSON request, for example:</p>
|
|
<pre><code class="language-json">{
|
|
"hello": "world"
|
|
}</code></pre>
|
|
<p>Will still be accessible through data.</p>
|
|
<pre><code class="language-swift">let world = request.data["hello"]?.string</code></pre>
|
|
<blockquote>
|
|
<p>Note: Force unwrap should never be used.</p>
|
|
</blockquote>
|
|
<p>This also applies to multi-part requests and can even be extended to new types such as XML or YAML through middleware.</p>
|
|
<p>If you'd prefer to access given types more explicitly, that's totally fine. The <code>data</code> variable is purely opt-in convenience for those who want it.</p>
|
|
<h2 id="json">JSON</h2>
|
|
<p>To access JSON directly on a given request, use the following:</p>
|
|
<pre><code class="language-swift">let json = request.json["hello"]</code></pre>
|
|
<h2 id="query-parameters">Query Parameters</h2>
|
|
<p>The same applies to query convenience:</p>
|
|
<pre><code class="language-swift">let query = request.query?["hello"] // String?
|
|
let name = request.query?["name"]?.string // String?
|
|
let age = request.query?["age"]?.int // Int?
|
|
let rating = request.query?["rating"]?.double // Double?</code></pre>
|
|
<h2 id="key-paths">Key Paths</h2>
|
|
<p>Key paths work on most Vapor types that can have nested key value objects. Here's a couple examples of how to access given the following json:</p>
|
|
<pre><code class="language-json">{
|
|
"metadata": "some metadata",
|
|
"artists" : {
|
|
"href": "http://someurl.com",
|
|
"items": [
|
|
{
|
|
"name": "Van Gogh",
|
|
},
|
|
{
|
|
"name": "Mozart"
|
|
}
|
|
]
|
|
}
|
|
}</code></pre>
|
|
<p>We could access the data in the following ways:</p>
|
|
<h3 id="metadata">Metadata</h3>
|
|
<p>Access top level values</p>
|
|
<pre><code class="language-swift">let type = request.data["metadata"].string // "some metadata"</code></pre>
|
|
<h3 id="items">Items</h3>
|
|
<p>Access nested values</p>
|
|
<pre><code class="language-swift">let items = request.data["artists", "items"] // [["name": "Van Gogh"], ["name": "Mozart"]]</code></pre>
|
|
<h3 id="mixing-arrays-and-objects">Mixing Arrays and Objects</h3>
|
|
<p>Get first artists</p>
|
|
<pre><code class="language-swift">let first = request.data["artists", "items", 0] // ["name": "Van Gogh"]</code></pre>
|
|
<h3 id="array-item">Array Item</h3>
|
|
<p>Get key from array item</p>
|
|
<pre><code class="language-swift">let firstName = request.data["artists", "items", 0, "name"] // "Van Gogh"</code></pre>
|
|
<h3 id="array-comprehension">Array Comprehension</h3>
|
|
<p>We can also smartly map an array of keys, for example, to just get the names of all of the artists, we could use the following</p>
|
|
<pre><code class="language-swift">let names = request.data["artists", "items", "name"] // ["Van Gogh", "Mozart"]</code></pre>
|
|
</main>
|
|
|
|
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
|
|
<script src="/1.5/scripts/highlight.pack.js"></script>
|
|
|
|
<script>
|
|
hljs.registerLanguage("leaf", function (hljs) {
|
|
/* Author: Hale Chan <halechan@qq.com> */
|
|
return {
|
|
c: [
|
|
{
|
|
cN: 'function',
|
|
b: '#+',
|
|
e: '[)] ',
|
|
rB: true,
|
|
eE: false,
|
|
c : [
|
|
{
|
|
b: '[(]',
|
|
e: '[)]',
|
|
eE: true,
|
|
c: [
|
|
{
|
|
cN: 'string',
|
|
b: '"',
|
|
e: '"'
|
|
},
|
|
{
|
|
cN: 'title',
|
|
b: '[A-Za-z_][A-Za-z_0-9]*'
|
|
}
|
|
]
|
|
},
|
|
{
|
|
cN: 'keyword',
|
|
b: '#+([A-Za-z$_][0-9A-Za-z$_]*)?',
|
|
eP: true
|
|
},
|
|
]
|
|
}
|
|
]
|
|
};
|
|
});
|
|
</script>
|
|
|
|
<script>
|
|
$(function() {
|
|
// Syntax highlighting
|
|
hljs.initHighlightingOnLoad();
|
|
|
|
if (navigator.userAgent.indexOf('Safari') != -1 && navigator.userAgent.indexOf('Chrome') == -1) {
|
|
$('body').addClass('safari');
|
|
}
|
|
|
|
$('h1, h2, h3, h4, h5, h6').each(function(key, item) {
|
|
var $item = $(item);
|
|
var id = $item.attr('id');
|
|
if (id) {
|
|
var link = $('<a>');
|
|
link.attr('href', '#' + id);
|
|
$item.wrap(link);
|
|
}
|
|
})
|
|
|
|
$('a.toggle').on('click', function(e){
|
|
e.preventDefault();
|
|
console.log('hi');
|
|
var body = $('body');
|
|
if (body.hasClass('toggled')) {
|
|
body.removeClass('toggled');
|
|
} else {
|
|
body.addClass('toggled');
|
|
}
|
|
})
|
|
|
|
var lastScroll = 0;
|
|
var isUp = false;
|
|
var win = $(window);
|
|
|
|
win.on('scroll', function(){
|
|
var scrollTop = win.scrollTop();
|
|
var scrollBottom = win.scrollTop() + win.height();
|
|
var docHeight = $(document).height();
|
|
|
|
if ( scrollTop < 0 || scrollBottom >= docHeight ){
|
|
return;
|
|
}
|
|
|
|
if (scrollTop > (lastScroll + 0) && scrollTop >= 0) {
|
|
if (!isUp) {
|
|
$('a.toggle.show').addClass('hide')
|
|
}
|
|
isUp = true;
|
|
lastScroll = scrollTop;
|
|
} else if (scrollTop < (lastScroll - 0)) {
|
|
if (isUp) {
|
|
$('a.toggle.show').removeClass('hide')
|
|
}
|
|
isUp = false;
|
|
lastScroll = scrollTop;
|
|
}
|
|
});
|
|
|
|
// scroll to the active nav item
|
|
$("nav .scroll").animate({
|
|
scrollTop: $("nav .active").offset().top - 157
|
|
}, 0);
|
|
|
|
// var lastScrollTop = 0;
|
|
// $(window).scroll(function(event){
|
|
// var st = $(this).scrollTop();
|
|
// if (st > lastScrollTop){
|
|
// $('a.toggle.show').addClass('hide')
|
|
// } else {
|
|
// $('a.toggle.show').removeClass('hide')
|
|
// }
|
|
// lastScrollTop = st;
|
|
// });
|
|
});
|
|
</script>
|
|
|
|
<script>
|
|
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
|
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
|
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
|
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
|
|
|
|
ga('create', 'UA-76177358-4', 'auto');
|
|
ga('send', 'pageview');
|
|
</script>
|
|
|
|
</body>
|
|
</html>
|