mirror of https://github.com/vapor/docs.git
543 lines
22 KiB
HTML
543 lines
22 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="">
|
|
<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="active">
|
|
<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="responserepresentable">ResponseRepresentable</h1>
|
|
<p>Traditionally HTTP servers take a <code>Request</code> and return a <code>Response</code>. Vapor is no different, but we can take advantage of Swift's powerful protocols to be a bit more flexible to the user facing API.</p>
|
|
<p>Let's start with the definition of <code>ResponseRepresentable</code></p>
|
|
<pre><code class="language-swift">public protocol ResponseRepresentable {
|
|
func makeResponse() throws -> Response
|
|
}</code></pre>
|
|
<p>By conforming to this protocol, we can more flexibly return things that conform instead of creating the response manually each time. Vapor provides some of these by default. Including (but not limited to):</p>
|
|
<h3 id="string">String</h3>
|
|
<p>Because string conforms to <code>ResponseRepresentable</code>, we can return it directly in a Vapor route handler.</p>
|
|
<pre><code class="language-swift">drop.get("hello") { request in
|
|
return "Hello, World!"
|
|
}</code></pre>
|
|
<h3 id="json">JSON</h3>
|
|
<p><code>JSON</code> can be returned directly instead of recreating a response each time.</p>
|
|
<pre><code class="language-swift">drop.get("hello") { request in
|
|
return try JSON(node: [
|
|
"hello": "world",
|
|
"some-numbers": [
|
|
1,
|
|
2,
|
|
3
|
|
]
|
|
]
|
|
)
|
|
}</code></pre>
|
|
<h3 id="response">Response</h3>
|
|
<p>Of course, we can also return Responses for anything not covered:</p>
|
|
<pre><code class="language-swift">drop.get("hello") { request in
|
|
return Response(status: .ok, headers: ["Content-Type": "text/plain"], body: "Hello, World!")
|
|
}</code></pre>
|
|
<h2 id="conforming">Conforming</h2>
|
|
<p>All we need to do to return our own objects is conform them to <code>ResponseRepresentable</code>. Let's look at an example type, a simple blog post model:</p>
|
|
<pre><code class="language-swift">import Foundation
|
|
|
|
struct BlogPost {
|
|
let id: String
|
|
let content: String
|
|
let createdAt: NSDate
|
|
}</code></pre>
|
|
<p>And now, let's conform it to response representable.</p>
|
|
<pre><code class="language-swift">import HTTP
|
|
import Foundation
|
|
|
|
extension BlogPost: ResponseRepresentable {
|
|
func makeResponse() throws -> Response {
|
|
let json = try JSON(node:
|
|
[
|
|
"id": id,
|
|
"content": content,
|
|
"created-at": createdAt.timeIntervalSince1970
|
|
]
|
|
)
|
|
return try json.makeResponse()
|
|
}
|
|
}</code></pre>
|
|
<blockquote>
|
|
<p>Don't forget to import HTTP.</p>
|
|
</blockquote>
|
|
<p>Now that we've modeled our BlogPost, we can return it directly in route handlers.</p>
|
|
<pre><code class="language-swift">drop.post("post") { req in
|
|
guard let content = request.data["content"] else { throw Error.missingContent }
|
|
let post = Post(content: content)
|
|
try post.save(to: database)
|
|
return post
|
|
}</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>
|