mirror of https://github.com/vapor/docs.git
commit
491551d250
|
|
@ -2,9 +2,6 @@
|
|||
|
||||
The bits package is included in Vapor by default and provides a convenient API for working with bytes.
|
||||
|
||||
!!! note
|
||||
Use `import Bits` to use this package.
|
||||
|
||||
## Typealias
|
||||
|
||||
The bits package provides two type-aliases for bytes.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,3 @@
|
|||
!!! warning
|
||||
This section may contain outdated information.
|
||||
|
||||
# Config
|
||||
|
||||
An application's configuration settings. Cloud applications generally require complex configurations that can adjust based on their environment. Vapor intends to provide a flexible configuration interaction that can be customized for a given user.
|
||||
|
|
@ -12,47 +9,45 @@ For Vapor applications, configuration files are expected to be nested under a to
|
|||
```bash
|
||||
./
|
||||
├── Config/
|
||||
│ ├── servers.json
|
||||
│ ├── server.json
|
||||
```
|
||||
|
||||
And an example of how this might look:
|
||||
|
||||
```JSON
|
||||
{
|
||||
"http": {
|
||||
"host": "0.0.0.0",
|
||||
"port": 8080
|
||||
}
|
||||
"port": 8080,
|
||||
"securityLayer": "none"
|
||||
}
|
||||
```
|
||||
|
||||
What that's saying, is that our application should start a single server named 'http' serving port `8080` on host `0.0.0.0`. This represents the following url: `http://localhost:8080`.
|
||||
What that's saying, is that our application should start a server on port `8080` and host `0.0.0.0`. This represents the following url: `http://localhost:8080`.
|
||||
|
||||
### Custom Keys
|
||||
|
||||
Let's add a custom key to the `servers.json` file:
|
||||
Let's add a custom key to the `server.json` file:
|
||||
|
||||
```JSON
|
||||
{
|
||||
"http": {
|
||||
"host": "0.0.0.0",
|
||||
"port": 8080,
|
||||
"securityLayer": "none",
|
||||
"custom-key": "custom value"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This can be accessed from your application's config using the following.
|
||||
|
||||
```swift
|
||||
let customValue = drop.config["servers", "http", "custom-key"]?.string ?? "default"
|
||||
let customValue = drop.config["server", "custom-key"]?.string ?? "default"
|
||||
```
|
||||
|
||||
That's it, feel free to add and utilize keys as necessary to make your application configuration easier.
|
||||
|
||||
## Config Syntax
|
||||
|
||||
You can access your config directory with the following syntax. `app.config[<#file-name#>, <#path#>, <#to#>, <#file#>]`. For example, let's hypothesize that in addition to the `servers.json` file we mentioned earlier, there is also a `keys.json` that looks like this:
|
||||
You can access your config directory with the following syntax. `app.config[fileName, path, to, key]`. For example, let's hypothesize that in addition to the `server.json` file we mentioned earlier, there is also a `keys.json` that looks like this:
|
||||
|
||||
```JSON
|
||||
{
|
||||
|
|
@ -110,7 +105,7 @@ Config files will be accessed in the following priority.
|
|||
3. Config/name-of-environment/
|
||||
4. Config/
|
||||
|
||||
What this means is that if a user calls `app.config["servers", "host"]`, the key will be searched in the CLI first, then the `secrets/` directory, then the top level default configs.
|
||||
What this means is that if a user calls `app.config["server", "host"]`, the key will be searched in the CLI first, then the `secrets/` directory, then the top level default configs.
|
||||
|
||||
> `secrets/` directory should very likely be added to the gitignore.
|
||||
|
||||
|
|
@ -118,59 +113,39 @@ What this means is that if a user calls `app.config["servers", "host"]`, the key
|
|||
|
||||
Let's start with the following JSON files.
|
||||
|
||||
#### `servers.json`
|
||||
#### `server.json`
|
||||
|
||||
```JSON
|
||||
{
|
||||
"http": {
|
||||
"host": "0.0.0.0",
|
||||
"port": 9000
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### `production/servers.json`
|
||||
#### `production/server.json`
|
||||
|
||||
```JSON
|
||||
{
|
||||
"http": {
|
||||
"host": "127.0.0.1",
|
||||
"port": "$PORT"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> The `"$NAME"` syntax is available for all values to access environment variables.
|
||||
|
||||
Please notice that `servers.json`, and `production/servers.json` both declare the same keys: `host`, and `port`. In our application, we'll call:
|
||||
Please notice that `server.json`, and `production/server.json` both declare the same keys: `host`, and `port`. In our application, we'll call:
|
||||
|
||||
```swift
|
||||
// will load 0.0.0.0 or 127.0.0.1 based on above config
|
||||
let host = drop.config["servers", "http", "host"]?.string ?? "0.0.0.0"
|
||||
let host = drop.config["server" "host"]?.string ?? "0.0.0.0"
|
||||
// will load 9000, or environment variable port.
|
||||
let port = drop.config["servers", "http", "port"]?.int ?? 9000
|
||||
let port = drop.config["server", "port"]?.int ?? 9000
|
||||
```
|
||||
|
||||
## COMMAND LINE
|
||||
|
||||
In addition to json files nested within the `Config/` directory, we can also use the command line to pass arguments into our config. By default, these values will be set as the "cli" file, but more complex options are also available.
|
||||
|
||||
#### 1. `--KEY=VALUE`
|
||||
|
||||
Arguments set through the command line can be accessed through config's cli file. For example, the following CLI command:
|
||||
|
||||
```bash
|
||||
--mongo-password=$MONGO_PASSWORD
|
||||
```
|
||||
|
||||
would be accessible within your application by using the following:
|
||||
|
||||
```swift
|
||||
let mongoPassword = drop.config["cli", "mongo-password"]?.string
|
||||
```
|
||||
|
||||
#### 2. `--CONFIG:FILE-NAME.KEY=CUSTOM-VALUE`
|
||||
|
||||
If you want command line arguments set to a file besides "cli", you can use this more advanced specification. For example, the following CLI command:
|
||||
|
||||
```bash
|
||||
|
|
@ -2,9 +2,6 @@
|
|||
|
||||
Core provides some conveniences for common tasks.
|
||||
|
||||
!!! note
|
||||
Use `import Core`
|
||||
|
||||
## Background
|
||||
|
||||
Easily create a background thread using `background()`
|
||||
|
|
|
|||
|
|
@ -1,11 +1,9 @@
|
|||
!!! warning
|
||||
This section may contain outdated information.
|
||||
|
||||
# Deploying with Nginx
|
||||
|
||||
Nginx is an extremely fast, battle tested, and easy-to-configure HTTP server and proxy. While Vapor supports directly serving HTTP requests with or without TLS, proxying behind Nginx can provide increased performance, security, and ease-of-use.
|
||||
|
||||
> Note: We recommend proxying Vapor HTTP servers behind Nginx.
|
||||
!!! note
|
||||
We recommend proxying Vapor HTTP servers behind Nginx.
|
||||
|
||||
## Overview
|
||||
|
||||
|
|
@ -19,7 +17,8 @@ An important feature of this middleman proxy is that it can alter or even redire
|
|||
|
||||
The default port for receiving HTTP requests is port `80` (and `443` for HTTPS). When you bind a Vapor server to port `80`, it will directly receive and respond to the HTTP requests that come to your server. When adding a proxy like Nginx, you bind Vapor to an internal port, like port `8080`.
|
||||
|
||||
> Note: Ports greater than 1024 do not require `sudo` to bind.
|
||||
!!! note
|
||||
Ports greater than 1024 do not require `sudo` to bind.
|
||||
|
||||
When Vapor is bound to a port besides `80` or `443`, it will not be accessible to the outside internet. You then bind Nginx to port `80` and configure it to route requests to your Vapor server bound at port `8080` (or whichever port you've chosen).
|
||||
|
||||
|
|
@ -30,6 +29,7 @@ And that's it. If Nginx is properly configured, you will see your Vapor app resp
|
|||
The first step is installing Nginx. One of the great parts of Nginx is the tremendous amount of community resources and documentation surrounding it. Because of this, we will not go into great detail here about installing Nginx as there is almost definitely a tutorial for your specific platform, OS, and provider.
|
||||
|
||||
Tutorials:
|
||||
|
||||
- [How To Install Nginx on Ubuntu 14.04 LTS](https://www.digitalocean.com/community/tutorials/how-to-install-nginx-on-ubuntu-14-04-lts)
|
||||
- [How To Install Nginx on Ubuntu 16.04](https://www.digitalocean.com/community/tutorials/how-to-install-nginx-on-ubuntu-16-04)
|
||||
- [How to Deploy Nginx on Heroku](https://blog.codeship.com/how-to-deploy-nginx-on-heroku/)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,3 @@
|
|||
!!! warning
|
||||
This section may contain outdated information.
|
||||
|
||||
# Supervisor
|
||||
|
||||
[Supervisor](http://supervisord.org) is a process control system that makes it easy to start, stop, and restart your Vapor app.
|
||||
|
|
@ -18,7 +15,7 @@ Each Vapor app on your server should have its own configuration file. For an exa
|
|||
|
||||
```sh
|
||||
[program:hello]
|
||||
command=/home/vapor/hello/.build/release/App serve --env=production
|
||||
command=/home/vapor/hello/.build/release/Run serve --env=production
|
||||
directory=/home/vapor/hello/
|
||||
user=www-data
|
||||
stdout_logfile=/var/log/supervisor/%(program_name)-stdout.log
|
||||
|
|
@ -42,9 +39,7 @@ Exported variables can be used in Vapor's configuration files with the `$` prefi
|
|||
`Config/production/servers.json `
|
||||
```json
|
||||
{
|
||||
"my-server": {
|
||||
"port": "$PORT"
|
||||
}
|
||||
"port": "$PORT"
|
||||
}
|
||||
```
|
||||
|
||||
|
|
@ -60,4 +55,5 @@ supervisorctl add hello
|
|||
supervisorctl start hello
|
||||
```
|
||||
|
||||
> Note: The `add` command may have already started your app.
|
||||
!!! note
|
||||
The `add` command may have already started your app.
|
||||
|
|
|
|||
|
|
@ -126,24 +126,17 @@ Boot up the server by running the following command.
|
|||
vapor run serve
|
||||
```
|
||||
|
||||
You should see a message `Server starting...`. You can now visit `http://localhost:8080/plaintext` in your browser.
|
||||
You should see a message `Server starting...`.
|
||||
|
||||
You can now visit `localhost:8080/plaintext` in your browser or run
|
||||
|
||||
```sh
|
||||
curl localhost:8080/plaintext
|
||||
```
|
||||
|
||||
!!! note
|
||||
Certain port numbers require super user access to bind. Simply run `sudo vapor run` to allow access. If you decide to run on a port besides `80`, make sure to direct your browser accordingly.
|
||||
|
||||
#### Production
|
||||
|
||||
Serving your application in the production environment increases its security and performance.
|
||||
|
||||
```sh
|
||||
vapor run serve --env=production
|
||||
```
|
||||
|
||||
Debug errors will be silenced while in the production environment, so make sure to check your logs for errors.
|
||||
|
||||
!!! warning
|
||||
If you compiled your application with `--release`, make sure to add that flag to the `vapor run` command as well. e.g., `vapor run serve --env=production --release`.
|
||||
|
||||
### Hello, World
|
||||
|
||||
You should see the following output in your browser window.
|
||||
|
|
@ -157,3 +150,19 @@ Hello, world!
|
|||
|
||||
<iframe src="https://ghbtns.com/github-btn.html?user=vapor&repo=vapor&type=star&count=true&size=large" frameborder="0" scrolling="0" width="160px" height="30px"></iframe>
|
||||
|
||||
|
||||
#### Production
|
||||
|
||||
Serving your application in the production environment increases its security and performance.
|
||||
|
||||
```sh
|
||||
vapor run serve --env=production
|
||||
```
|
||||
|
||||
Some debug messages will be silenced while in the production environment, so make sure to check your logs for errors.
|
||||
|
||||
!!! warning
|
||||
If you compiled your application with `--release`, make sure to add that flag to the `vapor run` command as well. e.g., `vapor run serve --env=production --release`.
|
||||
|
||||
For more information on deploying your code, check out the [deploy section](http://127.0.0.1:8000/deploy/nginx/).
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ After Xcode 8 has been downloaded, you must open it to finish the installation.
|
|||
Double check the installation was successful by running:
|
||||
|
||||
```sh
|
||||
eval "$(curl -sL check2.vapor.sh)"
|
||||
eval "$(curl -sL check.vapor.sh)"
|
||||
```
|
||||
|
||||
## Install Vapor
|
||||
|
|
|
|||
|
|
@ -2,6 +2,16 @@
|
|||
|
||||
Installing Vapor on Ubuntu only takes a couple of minutes.
|
||||
|
||||
## Supported
|
||||
|
||||
Vapor supports the same versions of Ubuntu that Swift supports.
|
||||
|
||||
| Version | Codename |
|
||||
|---------|--------------|
|
||||
| 16.10 | Yakkety Yak |
|
||||
| 16.04 | Xenial Xerus |
|
||||
| 14.04 | Trusty Tahr |
|
||||
|
||||
## APT Repo
|
||||
|
||||
Add Vapor's APT repo to get access to all of Vapor's system packages.
|
||||
|
|
@ -14,6 +24,9 @@ Easily add Vapor's APT repo with this handy script.
|
|||
eval "$(curl -sL https://apt.vapor.sh)"
|
||||
```
|
||||
|
||||
!!! note
|
||||
This command requires `curl` which can be installed using `sudo apt-get install curl`
|
||||
|
||||
### Manual
|
||||
|
||||
Or add the repo manually.
|
||||
|
|
@ -37,7 +50,7 @@ sudo apt-get install swift vapor
|
|||
Double check the installation was successful by running:
|
||||
|
||||
```sh
|
||||
eval "$(curl -sL check2.vapor.sh)"
|
||||
eval "$(curl -sL check.vapor.sh)"
|
||||
```
|
||||
|
||||
## Next
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Manual Quickstart
|
||||
|
||||
Learn how to create a Vapor project _without_ the Toolbox using just Swift 3 and the Swift Package Manager (SPM).
|
||||
Learn how to create a Vapor project _without_ the Toolbox using just Swift 3.1 and the Swift Package Manager (SPM).
|
||||
|
||||
This document assumes that you have Swift 3.1 installed, if not please refer to [Swift.org](https://swift.org/getting-started/#installing-swift) before you can continue.
|
||||
|
||||
|
|
|
|||
|
|
@ -29,8 +29,8 @@ brew upgrade vapor
|
|||
### APT
|
||||
|
||||
```
|
||||
apt-get update
|
||||
apt-get install vapor
|
||||
sudo apt-get update
|
||||
sudo apt-get install vapor
|
||||
```
|
||||
|
||||
## Templates
|
||||
|
|
@ -38,9 +38,19 @@ apt-get install vapor
|
|||
The toolbox can create a project from the Vapor basic-template or any other git repo.
|
||||
|
||||
```sh
|
||||
vapor new <name> [--template=<repo-url-or-github-path>]
|
||||
vapor new <name> [--template]
|
||||
```
|
||||
|
||||
| Name | Flag | Description |
|
||||
|------|----------------|-----------------------------------|
|
||||
| API | --template=api | JSON API with Fluent database. |
|
||||
| Web | --template=web | HTML website with Leaf templates. |
|
||||
|
||||
|
||||
!!! note
|
||||
If you do not specify a template option, the API template will be used.
|
||||
This may change in the future.
|
||||
|
||||
### Options
|
||||
|
||||
The toolbox will build an absolute URL based on what you pass as the template option.
|
||||
|
|
@ -48,6 +58,5 @@ The toolbox will build an absolute URL based on what you pass as the template op
|
|||
- `--template=web` clones `http://github.com/vapor/web-template`
|
||||
- `--template=user/repo` clones `http://github.com/user/repo`.
|
||||
- `--template=http://example.com/repo-path` clones the full url given.
|
||||
- `--branch=foo` can be used to specify a branch besides `master`.
|
||||
|
||||
!!! note
|
||||
If you do not specify a template option, the project will be built from Vapor's [API template](https://github.com/vapor/api-template).
|
||||
|
|
|
|||
|
|
@ -1,8 +1,3 @@
|
|||
!!! warning
|
||||
This section may contain outdated information.
|
||||
|
||||
> Module: `import HTTP`
|
||||
|
||||
# Body
|
||||
|
||||
The `HTTP.Body` represents the payload of an `HTTP.Message`, and is used to pass the underlying data. Some examples of this in practice would be `JSON`, `HTML` text, or the bytes of an image. Let's look at the implementation:
|
||||
|
|
|
|||
|
|
@ -1,8 +1,3 @@
|
|||
!!! warning
|
||||
This section may contain outdated information.
|
||||
|
||||
> Module: `import HTTP`
|
||||
|
||||
# Client
|
||||
|
||||
The client provided by `HTTP` is used to make outgoing requests to remote servers. Let's look at a simple outgoing request.
|
||||
|
|
@ -12,9 +7,9 @@ The client provided by `HTTP` is used to make outgoing requests to remote server
|
|||
Let's jump right in to make a simple HTTP Request. Here's a basic `GET` request using your Vapor `Droplet`.
|
||||
|
||||
```swift
|
||||
let query = ...
|
||||
let spotifyResponse = try drop.client.get("https://api.spotify.com/v1/search?type=artist&q=\(query)")
|
||||
print(spotifyR)
|
||||
let query = "..."
|
||||
let res = try drop.client.get("https://api.spotify.com/v1/search?type=artist&q=\(query)")
|
||||
print(res)
|
||||
```
|
||||
|
||||
### Clean Up
|
||||
|
|
@ -22,138 +17,78 @@ print(spotifyR)
|
|||
The url above can be a little tricky to read, so let's use the query parameter to clean it up a little bit:
|
||||
|
||||
```swift
|
||||
try drop.client.get("https://api.spotify.com/v1/search", query: ["type": "artist", "q": query])
|
||||
let res = try drop.client.get("https://api.spotify.com/v1/search", query: [
|
||||
"type": "artist",
|
||||
"q": query
|
||||
])
|
||||
```
|
||||
|
||||
### Continued
|
||||
|
||||
In addition to `GET` requests, Vapor's client provides support for most common HTTP functions. `GET`, `POST`, `PUT`, `PATCH`, `DELETE`
|
||||
|
||||
### POST as json
|
||||
```swift
|
||||
try drop.client.post("http://some-endpoint/json", headers: ["Content-Type": "application/json"], body: myJSON.makeBody())
|
||||
```
|
||||
### Headers
|
||||
|
||||
### POST as x-www-form-urlencoded
|
||||
```swift
|
||||
try drop.client.post("http://some-endpoint", headers: [
|
||||
"Content-Type": "application/x-www-form-urlencoded"
|
||||
], body: Body.data( Node(node: [
|
||||
"email": "mymail@vapor.codes"
|
||||
]).formURLEncoded()))
|
||||
```
|
||||
|
||||
### Full Request
|
||||
|
||||
To access additional functionality or custom methods, use the underlying `request` function directly.
|
||||
You can also add additional headers to the request.
|
||||
|
||||
```swift
|
||||
public static func get(_ method: Method,
|
||||
_ uri: String,
|
||||
headers: [HeaderKey: String] = [:],
|
||||
query: [String: CustomStringConvertible] = [:],
|
||||
body: Body = []) throws -> Response
|
||||
try drop.client.get("http://some-endpoint/json", headers: [
|
||||
"API-Key": "vapor123"
|
||||
])
|
||||
```
|
||||
|
||||
For example:
|
||||
### Custom Request
|
||||
|
||||
You can ask the client to respond to any `Request` that you create.
|
||||
This is useful if you need to add JSON or FormURLEncoded data to the request.
|
||||
|
||||
```swift
|
||||
try drop.client.request(.other(method: "CUSTOM"), "http://some-domain", headers: ["My": "Header"], query: ["key": "value"], body: [])
|
||||
let req = Request(method: .post, uri: "http://some-endpoint")
|
||||
req.formURLEncoded = Node(node: [
|
||||
"email": "mymail@vapor.codes"
|
||||
])
|
||||
|
||||
try drop.client.response(to: req)
|
||||
```
|
||||
|
||||
## Config
|
||||
## Re-usable Connection
|
||||
|
||||
The `Config/clients.json` file can be used to modify the client's settings.
|
||||
Up to this point, we've been using `drop.client` which is a `ClientFactory`. This creates a new client and TCP connection for each request.
|
||||
|
||||
### TLS
|
||||
|
||||
Host and certificate verification can be disabled.
|
||||
|
||||
> Note: Use extreme caution when modifying these settings.
|
||||
|
||||
```json
|
||||
{
|
||||
"tls": {
|
||||
"verifyHost": false,
|
||||
"verifyCertificates": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Mozilla
|
||||
|
||||
The Mozilla certificates are included by default to make fetching content from secure sites easy.
|
||||
|
||||
```json
|
||||
{
|
||||
"tls": {
|
||||
"certificates": "mozilla"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Advanced
|
||||
|
||||
In addition to our Droplet, we can also use and interact with the `Client` manually. Here's how our default implementation in Vapor looks:
|
||||
For more better performance, you can create an re-use a single client.
|
||||
|
||||
```swift
|
||||
let response = try Client<TCPClientStream>.get("http://some-endpoint/mine")
|
||||
```
|
||||
let pokemonClient = try drop.client.makeClient(
|
||||
scheme: "http",
|
||||
host: "pokeapi.co",
|
||||
securityLayer: .none
|
||||
)
|
||||
|
||||
The first thing we likely noticed is `TCPClientStream` being used as a Generic value. This will be the underlying connection that the `HTTP.Client` can use when performing the request. By conforming to the underlying `ClientStream`, an `HTTP.Client` can accept custom stream implementations seamlessly.
|
||||
|
||||
## Save Connection
|
||||
|
||||
Up to this point, we've been interacting with the Client via `class` or `static` level functions. This allows us to end the connection upon a completed request and is the recommended interaction for most use cases. For some advanced situations, we may want to reuse a connection. For these, we can initialize our client and perform multiple requests like this.
|
||||
|
||||
```swift
|
||||
let pokemonClient = try drop?.client.make(scheme: "http", host: "pokeapi.co")
|
||||
for i in 0...1 {
|
||||
let response = try pokemonClient?.get(path: "/api/v2/pokemon/", query: ["limit": 20, "offset": i])
|
||||
let response = try pokemonClient.get("/api/v2/pokemon/", query: [
|
||||
"limit": 20,
|
||||
"offset": i
|
||||
])
|
||||
print("response: \(response)")
|
||||
}
|
||||
```
|
||||
|
||||
## ClientProtocol
|
||||
!!! note
|
||||
Clients created using `.makeClient` can not connect to a different server after initialization. (Proxy servers are an exception)
|
||||
|
||||
Up to this point, we've focused on the built in `HTTP.Client`, but users can also include their own customized clients by conforming to `HTTP.ClientProtocol`. Let's look at the implementation:
|
||||
## Proxy
|
||||
|
||||
```swift
|
||||
public protocol Responder {
|
||||
func respond(to request: Request) throws -> Response
|
||||
}
|
||||
The `drop.client` can be configured to use a proxy by default.
|
||||
|
||||
public protocol Program {
|
||||
var host: String { get }
|
||||
var port: Int { get }
|
||||
var securityLayer: SecurityLayer { get }
|
||||
// default implemented
|
||||
init(host: String, port: Int, securityLayer: SecurityLayer) throws
|
||||
}
|
||||
|
||||
public protocol ClientProtocol: Program, Responder {
|
||||
var scheme: String { get }
|
||||
var stream: Stream { get }
|
||||
init(scheme: String, host: String, port: Int, securityLayer: SecurityLayer) throws
|
||||
`Config/client.json`
|
||||
```json
|
||||
{
|
||||
"proxy": {
|
||||
"hostname": "google.com",
|
||||
"port": 80,
|
||||
"securityLayer": "none"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
By conforming to these underlying functions, we immediately gain access to the public `ClientProtocol` apis we viewed above.
|
||||
|
||||
## Customize Droplet
|
||||
|
||||
If we've introduced a custom conformance to `HTTP.ClientProtocol`, we can pass this into our droplet without changing the underlying behavior in our application.
|
||||
|
||||
For example:
|
||||
|
||||
```swift
|
||||
let drop = Droplet()
|
||||
|
||||
drop.client = MyCustomClient.self
|
||||
```
|
||||
|
||||
Going forward, all of your calls to `drop.client` will use `MyCustomClient.self`:
|
||||
|
||||
```swift
|
||||
drop.client.get(... // uses `MyCustomClient`
|
||||
```
|
||||
For the above example, all requests sent to `drop.client.get(...)` would be proxied through google.com.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,3 @@
|
|||
!!! warning
|
||||
This section may contain outdated information.
|
||||
|
||||
# CORS
|
||||
|
||||
Vapor by default provides a middleware for implementing proper support for Cross-Origin Resource Sharing (CORS) named `CORSMiddleware`.
|
||||
|
|
@ -16,10 +13,37 @@ To learn more about middlewares, please visit the Middleware section of the docu
|
|||
|
||||
First of all, add the CORS middleware into your droplet middlewares array.
|
||||
|
||||
```swift
|
||||
# Insert CORS before any other middlewares
|
||||
drop.middleware.insert(CORSMiddleware(), at: 0)
|
||||
```
|
||||
`Config/droplet.json`
|
||||
```json
|
||||
{
|
||||
...,
|
||||
"middleware": [
|
||||
...,
|
||||
"cors",
|
||||
...,
|
||||
],
|
||||
...,
|
||||
}
|
||||
```
|
||||
|
||||
Next time you boot your application, you will be prompted to add a `Config/cors.json` file.
|
||||
|
||||
|
||||
`Config/cors.json`
|
||||
```json
|
||||
{
|
||||
"allowedOrigin": "*",
|
||||
"allowedMethods": ["GET", "POST", "PUT", "OPTIONS", "DELETE", "PATCH"],
|
||||
"allowedHeaders": [
|
||||
"Accept",
|
||||
"Authorization",
|
||||
"Content-Type",
|
||||
"Origin",
|
||||
"X-Requested-With"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
> Note: Make sure you insert CORS middleware before any other throwing middlewares, like the AbortMiddleware or similar. Otherwise the proper headers might not be added to the response.
|
||||
|
||||
|
|
@ -43,51 +67,32 @@ See below for how to set up both and what are the options.
|
|||
The `CORSConfiguration` struct is used to configure the `CORSMiddleware`. You can instanitate one like this:
|
||||
|
||||
```swift
|
||||
let configuration = CORSConfiguration(allowedOrigin: .custom("https://vapor.codes"),
|
||||
allowedMethods: [.get, .post, .options],
|
||||
allowedHeaders: ["Accept", "Authorization"],
|
||||
allowCredentials: false,
|
||||
cacheExpiration: 600,
|
||||
exposedHeaders: ["Cache-Control", "Content-Language"])
|
||||
let config = try Config()
|
||||
config.addConfigurable(middleware: { config in
|
||||
return CORSConfiguration(
|
||||
allowedOrigin: .custom("https://vapor.codes"),
|
||||
allowedMethods: [.get, .post, .options],
|
||||
allowedHeaders: ["Accept", "Authorization"],
|
||||
allowCredentials: false,
|
||||
cacheExpiration: 600,
|
||||
exposedHeaders: ["Cache-Control", "Content-Language"]
|
||||
)
|
||||
}, name: "custom-cors")
|
||||
```
|
||||
|
||||
After creating a configuration you can add the CORS middleware.
|
||||
Then set the `custom-cors` in your Droplet's middleware array.
|
||||
|
||||
```swift
|
||||
drop.middleware.insert(CORSMiddleware(configuration: configuration), at: 0)
|
||||
`Config/droplet.json`
|
||||
```json
|
||||
{
|
||||
...,
|
||||
"middleware": [
|
||||
...,
|
||||
"custom-cors",
|
||||
...,
|
||||
],
|
||||
...,
|
||||
}
|
||||
```
|
||||
|
||||
> Note: Please consult the documentation in the source code of the `CORSConfiguration` for more information about available values for the settings.
|
||||
|
||||
|
||||
### JSON Config
|
||||
|
||||
Optionally, `CORSMiddleware` can be configured using the Vapor's `Config` which is created out of the json files contained in your Config folder. You will need to create a file called `cors.json` or `CORS.json` in your Config folder in your project and add the required keys.
|
||||
|
||||
Example of how such a file could look as follows:
|
||||
|
||||
```swift
|
||||
{
|
||||
"allowedOrigin": "origin",
|
||||
"allowedMethods": "GET,POST,PUT,OPTIONS,DELETE,PATCH",
|
||||
"allowedHeaders": ["Accept", "Authorization", "Content-Type", "Origin", "X-Requested-With"]
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
> Note: Following keys are required: `allowedOrigin`, `allowedMethods`, `allowedHeaders`. If they are not present an error will be thrown while instantiating the middleware.
|
||||
>
|
||||
> Optionally you can also specify the keys `allowCredentials` (Bool), `cacheExpiration` (Int) and `exposedHeaders` ([String]).
|
||||
|
||||
Afterwards you can add the middleware using the a throwing overload of the initialiser that accepts Vapor's `Config`.
|
||||
|
||||
```swift
|
||||
let drop = Droplet()
|
||||
|
||||
do {
|
||||
drop.middleware.insert(try CORSMiddleware(configuration: drop.config), at: 0)
|
||||
} catch {
|
||||
fatalError("Error creating CORSMiddleware, please check that you've setup cors.json correctly.")
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -147,7 +147,7 @@ Anything added to the `authed` group must pass through `AuthMiddleware`. Because
|
|||
|
||||
Appending middleware to the `drop.middleware` array is the simplest way to add middleware--it will be used every time the application starts.
|
||||
|
||||
You can also use the [configuration](../settings/config.md) 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.
|
||||
You can also use the [configuration](../configs/config.md) 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.
|
||||
|
||||
Appending configurable middleware looks like the following:
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
# Using HTTP
|
||||
|
||||
## With Vapor
|
||||
|
||||
This package is included with Vapor by default, just add:
|
||||
|
||||
```Swift
|
||||
import HTTP
|
||||
```
|
||||
|
||||
## Without Vapor
|
||||
|
||||
HTTP provides everything you need to create an HTTP-based application for any server-side Swift project. To include it in your package, add the following to your `Package.swift` file.
|
||||
|
||||
```Swift
|
||||
import PackageDescription
|
||||
|
||||
let package = Package(
|
||||
name: "Project",
|
||||
dependencies: [
|
||||
...
|
||||
.Package(url: "https://github.com/vapor/engine.git", majorVersion: 2)
|
||||
],
|
||||
exclude: [ ... ]
|
||||
)
|
||||
```
|
||||
|
||||
Use `import HTTP` to access HTTP's APIs
|
||||
|
|
@ -1,8 +1,3 @@
|
|||
!!! warning
|
||||
This section may contain outdated information.
|
||||
|
||||
> Module: `import HTTP`
|
||||
|
||||
# Request
|
||||
|
||||
The most common part of the `HTTP` library we'll be interacting with is the `Request` type. Here's a look at some of the most commonly used attributes in this type.
|
||||
|
|
|
|||
|
|
@ -1,8 +1,3 @@
|
|||
!!! warning
|
||||
This section may contain outdated information.
|
||||
|
||||
> Module: `import HTTP`
|
||||
|
||||
# Responder
|
||||
|
||||
The `Responder` is a simple protocol defining the behavior of objects that can accept a `Request` and return a `Response`. Most notably in Vapor, it is the core API endpoint that connects the `Droplet` to the `Server`. Let's look at the definition:
|
||||
|
|
|
|||
|
|
@ -1,8 +1,3 @@
|
|||
!!! warning
|
||||
This section may contain outdated information.
|
||||
|
||||
> Module: `import HTTP`
|
||||
|
||||
# ResponseRepresentable
|
||||
|
||||
Traditionally HTTP servers take a `Request` and return a `Response`. 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.
|
||||
|
|
@ -23,7 +18,7 @@ Because string conforms to `ResponseRepresentable`, we can return it directly in
|
|||
|
||||
```swift
|
||||
drop.get("hello") { request in
|
||||
return "Hello, World!"
|
||||
return "Hello, World!"
|
||||
}
|
||||
```
|
||||
|
||||
|
|
@ -33,15 +28,10 @@ drop.get("hello") { request in
|
|||
|
||||
```swift
|
||||
drop.get("hello") { request in
|
||||
return try JSON(node: [
|
||||
"hello": "world",
|
||||
"some-numbers": [
|
||||
1,
|
||||
2,
|
||||
3
|
||||
]
|
||||
]
|
||||
)
|
||||
var json = JSON()
|
||||
try json.set("hello", "world")
|
||||
try json.set("some-numbers", [1, 2, 3])
|
||||
return json
|
||||
}
|
||||
```
|
||||
|
||||
|
|
@ -51,7 +41,11 @@ Of course, we can also return Responses for anything not covered:
|
|||
|
||||
```swift
|
||||
drop.get("hello") { request in
|
||||
return Response(status: .ok, headers: ["Content-Type": "text/plain"], body: "Hello, World!")
|
||||
return Response(
|
||||
status: .ok,
|
||||
headers: ["Content-Type": "text/plain"],
|
||||
body: "Hello, World!"
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
|
|
@ -73,31 +67,27 @@ And now, let's conform it to response representable.
|
|||
|
||||
```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()
|
||||
}
|
||||
func makeResponse() throws -> Response {
|
||||
var json = JSON()
|
||||
try json.set("id", id)
|
||||
try json.set("content", content)
|
||||
try json.set("created-at", createdAt.timeIntervalSince1970)
|
||||
return try json.makeResponse()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> Don't forget to import HTTP.
|
||||
|
||||
Now that we've modeled our BlogPost, we can return it directly in route handlers.
|
||||
|
||||
```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
|
||||
guard let content = request.data["content"] else {
|
||||
throw Error.missingContent
|
||||
}
|
||||
let post = Post(content: content)
|
||||
try post.save(to: database)
|
||||
return post
|
||||
}
|
||||
```
|
||||
|
|
|
|||
|
|
@ -1,8 +1,3 @@
|
|||
!!! warning
|
||||
This section may contain outdated information.
|
||||
|
||||
> Module: `import HTTP`
|
||||
|
||||
# Response
|
||||
|
||||
When building endpoints, we'll often be returning responses for requests. If we're making outgoing requests, we'll be receiving them.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,3 @@
|
|||
!!! warning
|
||||
This section may contain outdated information.
|
||||
|
||||
# Server
|
||||
|
||||
The server is responsible for accepting connections from clients, parsing their requests, and delivering them a response.
|
||||
|
|
@ -12,51 +9,25 @@ Starting your Droplet with a default server is simple.
|
|||
```swift
|
||||
import Vapor
|
||||
|
||||
let drop = Droplet()
|
||||
|
||||
drop.run()
|
||||
let drop = try Droplet()
|
||||
try drop.run()
|
||||
```
|
||||
|
||||
The default server will bind to host `0.0.0.0` at port `8080`.
|
||||
|
||||
## Config
|
||||
|
||||
If you are using a `Config/servers.json` file, this is where you can easily change your host and port or even boot multiple servers.
|
||||
If you are using a `Config/server.json` file, this is where you can easily change your host and port.
|
||||
|
||||
```json
|
||||
{
|
||||
"default": {
|
||||
"port": "$PORT:8080",
|
||||
"host": "0.0.0.0",
|
||||
"securityLayer": "none"
|
||||
}
|
||||
"port": "$PORT:8080",
|
||||
"host": "0.0.0.0",
|
||||
"securityLayer": "none"
|
||||
}
|
||||
```
|
||||
|
||||
The default `servers.json` is above. The port with try to resolve the environment variable `$PORT` or fallback to `8080`.
|
||||
|
||||
### Multiple
|
||||
|
||||
You can start multiple servers in the same application. This is especially useful if you want to boot an `HTTP` and `HTTPS` server side by side.
|
||||
|
||||
```json
|
||||
{
|
||||
"plaintext": {
|
||||
"port": "80",
|
||||
"host": "vapor.codes",
|
||||
"securityLayer": "none"
|
||||
},
|
||||
"secure": {
|
||||
"port": "443",
|
||||
"host": "vapor.codes",
|
||||
"securityLayer": "tls",
|
||||
"tls": {
|
||||
"certificates": "none",
|
||||
"signature": "selfSigned"
|
||||
}
|
||||
},
|
||||
}
|
||||
```
|
||||
The default `server.json` is above. The port with try to resolve the environment variable `$PORT` or fallback to `8080`.
|
||||
|
||||
## TLS
|
||||
|
||||
|
|
@ -70,8 +41,8 @@ Verificiation of hosts and certificates can be disabled. They are enabled by def
|
|||
|
||||
```json
|
||||
"tls": {
|
||||
"verifyHost": false,
|
||||
"verifyCertificates": false
|
||||
"verifyHost": false,
|
||||
"verifyCertificates": false
|
||||
}
|
||||
```
|
||||
|
||||
|
|
@ -142,68 +113,23 @@ Verificiation of hosts and certificates can be disabled. They are enabled by def
|
|||
|
||||
## Example
|
||||
|
||||
Here is an example `servers.json` file using certificate files with a self signed signature and host verification redundantly set to `true`.
|
||||
Here is an example `server.json` file using certificate files with a self signed signature and host verification redundantly set to `true`.
|
||||
|
||||
```json
|
||||
{
|
||||
"secure": {
|
||||
"port": "8443",
|
||||
"host": "0.0.0.0",
|
||||
"securityLayer": "tls",
|
||||
"tls": {
|
||||
"verifyHost": true,
|
||||
"certificates": "files",
|
||||
"certificateFile": "/vapor/certs/cert.pem",
|
||||
"privateKeyFile": "/vapor/certs/key.pem",
|
||||
"signature": "selfSigned"
|
||||
}
|
||||
"port": "8443",
|
||||
"host": "0.0.0.0",
|
||||
"securityLayer": "tls",
|
||||
"tls": {
|
||||
"verifyHost": true,
|
||||
"certificates": "files",
|
||||
"certificateFile": "/vapor/certs/cert.pem",
|
||||
"privateKeyFile": "/vapor/certs/key.pem",
|
||||
"signature": "selfSigned"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Manual
|
||||
## Nginx
|
||||
|
||||
Servers can also be configured manually, without configuration files.
|
||||
|
||||
> Note: If servers are configured programatically, they override any config settings.
|
||||
|
||||
### Simple
|
||||
|
||||
The `run` method on the Droplet takes a dictionary of server configuration objects. The key is the name of the server.
|
||||
|
||||
```swift
|
||||
import Vapor
|
||||
|
||||
let drop = Droplet()
|
||||
|
||||
drop.run(servers: [
|
||||
"default": (host: "vapor.codes", port: 8080, securityLayer: .none)
|
||||
]
|
||||
```
|
||||
|
||||
### TLS
|
||||
|
||||
TLS can also be configured manually, and works similarly to the `servers.json` config files described above.
|
||||
|
||||
```swift
|
||||
import Vapor
|
||||
import TLS
|
||||
|
||||
let drop = Droplet()
|
||||
|
||||
let config = try TLS.Config(
|
||||
mode: .server,
|
||||
certificates: .files(
|
||||
certificateFile: "/Users/tanner/Desktop/certs/cert.pem",
|
||||
privateKeyFile: "/Users/tanner/Desktop/certs/key.pem",
|
||||
signature: .selfSigned
|
||||
),
|
||||
verifyHost: true,
|
||||
verifyCertificates: true
|
||||
)
|
||||
|
||||
drop.run(servers: [
|
||||
"plaintext": ("vapor.codes", 8080, .none),
|
||||
"secure": ("vapor.codes", 8443, .tls(config)),
|
||||
])
|
||||
````
|
||||
It is highly recommended that you serve your Vapor project behind Nginx in production. Read more in the [deploy Nginx](../deploy/nginx.md) section.
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
# JSON
|
||||
|
||||
JSON is an integral part of Vapor. It powers Vapor's [Config](../settings/config.md) and is easy to use in both requests and responses.
|
||||
JSON is an integral part of Vapor. It powers Vapor's [Config](../configs/config.md) and is easy to use in both requests and responses.
|
||||
|
||||
## Request
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,28 @@
|
|||
# Using JSON
|
||||
|
||||
This package is included with the Vapor dependency, use
|
||||
## With Vapor
|
||||
|
||||
This package is included with Vapor by default, just add:
|
||||
|
||||
```Swift
|
||||
import JSON
|
||||
```
|
||||
|
||||
## Without Vapor
|
||||
|
||||
JSON provides easy-to-use JSON support for any server-side, or client side Swift project. To include it in your package, add the following to your `Package.swift` file.
|
||||
|
||||
```Swift
|
||||
import PackageDescription
|
||||
|
||||
let package = Package(
|
||||
name: "Project",
|
||||
dependencies: [
|
||||
...
|
||||
.Package(url: "https://github.com/vapor/json.git", majorVersion: 2)
|
||||
],
|
||||
exclude: [ ... ]
|
||||
)
|
||||
```
|
||||
|
||||
Use `import JSON` to access JSON's APIs
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ Once the provider is added to your Droplet, you can configure your Droplet to us
|
|||
```
|
||||
|
||||
!!! seealso
|
||||
Learn more about configuration files in the [Settings guide](../settings/config.md).
|
||||
Learn more about configuration files in the [Settings guide](../configs/config.md).
|
||||
|
||||
## Manual
|
||||
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ Once the provider is added to your Droplet, you can configure Fluent to use the
|
|||
```
|
||||
|
||||
!!! seealso
|
||||
Learn more about configuration files in the [Settings guide](../settings/config.md).
|
||||
Learn more about configuration files in the [Settings guide](../configs/config.md).
|
||||
|
||||
## Configure MySQL
|
||||
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ Once the provider is added to your Droplet, you can configure Vapor to use Redis
|
|||
```
|
||||
|
||||
!!! seealso
|
||||
Learn more about configuration files in the [Settings guide](../settings/config.md).
|
||||
Learn more about configuration files in the [Settings guide](../configs/config.md).
|
||||
|
||||
## Configure Redis
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
# Using Sessions
|
||||
|
||||
This module is a part of Vapor, just add:
|
||||
|
||||
```Swift
|
||||
import Sessions
|
||||
```
|
||||
|
|
@ -1,36 +1,45 @@
|
|||
!!! warning
|
||||
This section may contain outdated information.
|
||||
|
||||
# Sessions
|
||||
|
||||
Sessions help you store information about a user between requests. As long as the client supports cookies, sessions are easy to create.
|
||||
|
||||
## Middleware
|
||||
|
||||
Enable sessions on your `Droplet` by adding an instance of `SessionMiddleware`.
|
||||
Enable sessions on your `Droplet` by adding `"sessions"` to your middleware array.
|
||||
|
||||
`Config/droplet.json`
|
||||
```json
|
||||
{
|
||||
...,
|
||||
"middleware": [
|
||||
...,
|
||||
"sessions",
|
||||
...,
|
||||
],
|
||||
...,
|
||||
}
|
||||
```
|
||||
|
||||
By default, the memory sessions driver will be used. You can change this with the `droplet.sessions` key.
|
||||
|
||||
|
||||
`Config/droplet.json`
|
||||
```json
|
||||
{
|
||||
...,
|
||||
"sessions": "memory",
|
||||
...,
|
||||
}
|
||||
```
|
||||
|
||||
## Request
|
||||
|
||||
After `SessionMiddleware` has been enabled, you can access the `req.assertSession()` method to get access to session.
|
||||
|
||||
```swift
|
||||
import Sessions
|
||||
|
||||
let memory = MemorySessions()
|
||||
let sessions = SessionsMiddleware(sessions: memory)
|
||||
```
|
||||
|
||||
Then add to the `Droplet`.
|
||||
|
||||
```
|
||||
let drop = Droplet()
|
||||
drop.middleware.append(sessions)
|
||||
```
|
||||
|
||||
> Note: If you'd like to enable or disable the middleware based on config files, check out [middleware](../http/middleware.md).
|
||||
|
||||
## Request
|
||||
|
||||
After `SessionMiddleware` has been enabled, you can access the `req.sessions()` method to get access to session data.
|
||||
|
||||
```swift
|
||||
let data = try req.session().data
|
||||
let session = try req.assertSession()
|
||||
print(session.data)
|
||||
```
|
||||
|
||||
## Example
|
||||
|
|
@ -42,10 +51,11 @@ Let's create an example that remembers the user's name.
|
|||
```swift
|
||||
drop.post("remember") { req in
|
||||
guard let name = req.data["name"]?.string else {
|
||||
throw Abort.badRequest
|
||||
throw Abort(.badRequest)
|
||||
}
|
||||
|
||||
try req.session().data["name"] = Node.string(name)
|
||||
let session = try req.assertSession()
|
||||
try session.data.set("name", name)
|
||||
|
||||
return "Remebered name."
|
||||
}
|
||||
|
|
@ -59,8 +69,10 @@ On `GET /remember`, fetch the `name` from the session data and return it.
|
|||
|
||||
```swift
|
||||
drop.get("remember") { req in
|
||||
guard let name = try req.session().data["name"]?.string else {
|
||||
return throw Abort.custom(status: .badRequest, message: "Please POST the name first.")
|
||||
let session = try req.assertSession()
|
||||
|
||||
guard let name = session.data["name"]?.string else {
|
||||
return throw Abort(.badRequest, reason: "Please POST the name first.")
|
||||
}
|
||||
|
||||
return name
|
||||
|
|
@ -70,7 +82,3 @@ drop.get("remember") { req in
|
|||
## Cookie
|
||||
|
||||
The session will be stored using the `vapor-session` cookie.
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
!!! warning
|
||||
This section may contain outdated information.
|
||||
In addition to the commands provided by Vapor (like `serve`, and `routes`) you can build your own custom commands.
|
||||
|
||||
# Commands
|
||||
Custom console commands on Vapor are a breeze.
|
||||
!!! note
|
||||
Commands are a great way to script your application with CRON jobs.
|
||||
|
||||
## Example
|
||||
To make a custom console command we must first create a new `.swift` file, import `Vapor` and `Console`, and implement the `Command` protocol.
|
||||
|
|
@ -12,7 +11,7 @@ import Vapor
|
|||
import Console
|
||||
|
||||
final class MyCustomCommand: Command {
|
||||
public let id = "command"
|
||||
public let id = "my-command"
|
||||
public let help = ["This command does things, like foo, and bar."]
|
||||
public let console: ConsoleProtocol
|
||||
|
||||
|
|
@ -26,19 +25,51 @@ final class MyCustomCommand: Command {
|
|||
}
|
||||
```
|
||||
|
||||
- The **id** property is the string you will type in the console to access the command. `.build/debug/App command` will run the Custom Command.
|
||||
- The **help** property is the help message that will give your custom command's users some idea of how to access it.
|
||||
- The **console** property is the object passed to your custom command that adheres to the console protocol, allowing manipulation of the console.
|
||||
- The **run** method is where you put the logic relating to your command.
|
||||
- The **id** property is the string you will type in the console to access the command. `.build/debug/App command` will run the Custom Command.
|
||||
- The **help** property is the help message that will give your custom command's users some idea of how to access it.
|
||||
- The **console** property is the object passed to your custom command that adheres to the console protocol, allowing manipulation of the console.
|
||||
- The **run** method is where you put the logic relating to your command.
|
||||
|
||||
## Config Initializable
|
||||
|
||||
To make our command configurable, conform it to `ConfigInitializable`
|
||||
|
||||
After we work our magic in the Custom Command file, we switch over to our `main.swift` file and add the custom command to the droplet like so.
|
||||
```swift
|
||||
drop.commands.append(MyCustomCommand(console: drop.console))
|
||||
extension MyCustomCommand: ConfigInitializable {
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
## Add to Droplet
|
||||
|
||||
After we work our magic in the Custom Command file, we switch over to our `main.swift` file and add the custom command to the Droplet like so.
|
||||
|
||||
```swift
|
||||
import Vapor
|
||||
|
||||
let config = try Config()
|
||||
try config.addConfigurable(command: MyCustomCommand.init, name: "my-command")
|
||||
|
||||
let drop = try Droplet(config)
|
||||
```
|
||||
|
||||
This allows Vapor access to our custom command and lets it know to display it in the `--help` section of the program.
|
||||
|
||||
### Configure
|
||||
|
||||
Now that you've made the command configurable, just add it to the `commands` array in your `Config/droplet.json` file.
|
||||
|
||||
`Config/droplet.json`
|
||||
```json
|
||||
{
|
||||
...,
|
||||
"commands": ["my-command"],
|
||||
...,
|
||||
}
|
||||
```
|
||||
|
||||
After compiling the application we can run our custom command like so.
|
||||
|
||||
```
|
||||
.build/debug/App command
|
||||
vapor run my-command
|
||||
```
|
||||
|
|
|
|||
|
|
@ -45,20 +45,24 @@ You can also use controller methods with type-safe routing.
|
|||
final class HelloController {
|
||||
...
|
||||
|
||||
func sayHelloAlternate(_ req: Request, _ name: String) -> ResponseRepresentable {
|
||||
func sayHelloAlternate(_ req: Request) -> ResponseRepresentable {
|
||||
let name: String = try req.parameters.next(String.self)
|
||||
return "Hello, \(name)"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
We add a new method called `sayHelloAlternate` to the `HelloController` that accepts a second parameter `name: String`.
|
||||
We add a new method called `sayHelloAlternate` to the `HelloController` that fetches a `String` from the request's parameters.
|
||||
|
||||
```swift
|
||||
let hc = HelloController()
|
||||
drop.get("hello", String.self, handler: hc.sayHelloAlternate)
|
||||
drop.get("hello", String.parameter, handler: hc.sayHelloAlternate)
|
||||
```
|
||||
|
||||
Since this type-safe `drop.get` accepts a signature `(Request, String) throws -> ResponseRepresentable`, our method can now be used as the closure for this route.
|
||||
Since `drop.get` accepts a signature `(Request) throws -> ResponseRepresentable`, our method can now be used as the closure for this route.
|
||||
|
||||
!!! note
|
||||
Read more about type safe routing in the [Routing Parameters](https://docs.vapor.codes/2.0/routing/parameters/#type-safe) section.
|
||||
|
||||
## Resources
|
||||
|
||||
|
|
@ -139,4 +143,4 @@ drop.resource("users", users)
|
|||
Controllers can go anywhere in your application, but they are most often stored in the `App/Controllers/` directory.
|
||||
|
||||
!!! tip
|
||||
If you are building a large application, you may want to create your controllers in a separate module. This will allow you to perform unit tests on your controllers. For more information on creating modules, see the [modules](../advanced/modules.md) section in Advanced.
|
||||
If you are building a large application, you may want to create your controllers in a separate module. This will allow you to perform unit tests on your controllers.
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ try drop.run()
|
|||
Creation of the `Droplet` normally happens in the `main.swift` file.
|
||||
|
||||
!!! note
|
||||
For the sake of simplicity, most of the documentations sample code uses just the `main.swift` file. See the [modules](../advanced/modules.md) section in Advanced to learn more about using multiple modules.
|
||||
For the sake of simplicity, most of the documentations sample code uses just the `main.swift` file. You can read more about packages and modules in the Swift Package Manager [conceptual overview](https://swift.org/package-manager/).
|
||||
|
||||
## Environment
|
||||
|
||||
|
|
@ -34,7 +34,7 @@ if drop.environment == .production {
|
|||
}
|
||||
```
|
||||
|
||||
The environment affects [Config](../settings/config.md) and [Logging](log.md). The environment is `development` by default. To change it, pass the `--env=` flag as an argument.
|
||||
The environment affects [Config](../configs/config.md) and [Logging](log.md). The environment is `development` by default. To change it, pass the `--env=` flag as an argument.
|
||||
|
||||
```sh
|
||||
vapor run serve --env=production
|
||||
|
|
@ -45,7 +45,7 @@ If you are in Xcode, you can pass arguments through the scheme editor.
|
|||
!!! warning
|
||||
Debug logs can reduce the number of requests your application can handle per second. Enable production mode to silence non-critical logs.
|
||||
|
||||
## Working Directory
|
||||
## Config Directory
|
||||
|
||||
The `workDir` property contains a path to the current working directory of the application. Vapor uses this property to find the folders related to your project, such as `Resources`, `Public`, and `Config`.
|
||||
|
||||
|
|
|
|||
|
|
@ -80,6 +80,6 @@ Vapor has a sophisticated configuration system that involves a hierarchy of conf
|
|||
└── app.json // overrides app.json in all environments, ignored by git
|
||||
```
|
||||
|
||||
`.json` files are structured in the `Config` folder as shown above. The configuration will be applied dependant on where the `.json` file exists in the hierarchy. Learn more in [Config](../settings/config.md).
|
||||
`.json` files are structured in the `Config` folder as shown above. The configuration will be applied dependant on where the `.json` file exists in the hierarchy. Learn more in [Config](../configs/config.md).
|
||||
|
||||
Learn about changing environments (the `--env=` flag) in the [Droplet](droplet.md) section.
|
||||
|
|
|
|||
|
|
@ -4,15 +4,34 @@ Log information using `drop.log`.
|
|||
drop.log.info("Informational log")
|
||||
```
|
||||
|
||||
Log types supported are:
|
||||
## Types
|
||||
|
||||
- info
|
||||
- warning
|
||||
- verbose
|
||||
- debug
|
||||
- error
|
||||
- fatal
|
||||
Below are the following methods you can call on the log protocol. Only `error` and `fatal` will be shown in `production` mode.
|
||||
|
||||
| Method | Production |
|
||||
|---------|------------|
|
||||
| info | No |
|
||||
| warning | No |
|
||||
| verbose | No |
|
||||
| debug | No |
|
||||
| error | Yes |
|
||||
| fatal | Yes |
|
||||
|
||||
## Protocol
|
||||
|
||||
Create your own logger by conforming to `LogProtocol`.
|
||||
|
||||
```swift
|
||||
/// Logger protocol. Custom loggers must conform
|
||||
/// to this protocol
|
||||
public protocol LogProtocol: class {
|
||||
/// Enabled log levels. Only levels in this
|
||||
/// array should be logged.
|
||||
var enabled: [LogLevel] { get set }
|
||||
|
||||
/// Log the given message at the passed filter level.
|
||||
/// file, function and line of the logging call
|
||||
/// are automatically injected in the convenience function.
|
||||
func log(_ level: LogLevel, message: String, file: String, function: String, line: Int)
|
||||
}
|
||||
```
|
||||
|
|
@ -33,7 +33,7 @@ Here is what importing the MySQL provider looks like:
|
|||
|
||||
```swift
|
||||
import Vapor
|
||||
import VaporMySQL
|
||||
import MySQLProvider
|
||||
```
|
||||
|
||||
### Add to Droplet
|
||||
|
|
@ -42,7 +42,7 @@ Every provider comes with a class named `Provider`. Add this class to your Dropl
|
|||
|
||||
```swift
|
||||
let config = try Config()
|
||||
try config.addProvider(VaporMySQL.Provider.self)
|
||||
try config.addProvider(MySQLProvider.Provider.self)
|
||||
|
||||
let drop = try Droplet(config)
|
||||
|
||||
|
|
@ -53,7 +53,7 @@ drop.run()
|
|||
|
||||
### Configuration
|
||||
|
||||
Some drivers may require a configuration file. For example, `VaporMySQL` requires a `Config/mysql.json` file like the following:
|
||||
Some drivers may require a configuration file. For example, `MySQLProvider` requires a `Config/mysql.json` file like the following:
|
||||
|
||||
```json
|
||||
{
|
||||
|
|
|
|||
|
|
@ -19,8 +19,8 @@ pages:
|
|||
- 'Hash': 'vapor/hash.md'
|
||||
- 'Log': 'vapor/log.md'
|
||||
- 'Commands': 'vapor/commands.md'
|
||||
- Settings:
|
||||
- 'Config': 'settings/config.md'
|
||||
- Configs:
|
||||
- 'Config': 'configs/config.md'
|
||||
- JSON:
|
||||
- 'Package': 'json/package.md'
|
||||
- 'Overview': 'json/overview.md'
|
||||
|
|
@ -56,8 +56,10 @@ pages:
|
|||
- 'Password': 'auth/password.md'
|
||||
- 'Persist': 'auth/persist.md'
|
||||
- Sessions:
|
||||
- 'Package': 'sessions/package.md'
|
||||
- 'Sessions': 'sessions/sessions.md'
|
||||
- HTTP:
|
||||
- 'Package': 'http/package.md'
|
||||
- 'Request': 'http/request.md'
|
||||
- 'Response': 'http/response.md'
|
||||
- 'Middleware': 'http/middleware.md'
|
||||
|
|
@ -84,8 +86,9 @@ pages:
|
|||
- Debugging:
|
||||
- 'Package': 'debugging/package.md'
|
||||
- 'Overview': 'debugging/overview.md'
|
||||
- Advanced:
|
||||
- 'Modules': 'advanced/modules.md'
|
||||
- Deploy:
|
||||
- 'Nginx': 'deploy/nginx.md'
|
||||
- 'Supervisor': 'deploy/supervisor.md'
|
||||
- Version (2.0):
|
||||
- '1.5': 'version/1_5.md'
|
||||
- '2.0': 'version/2_0.md'
|
||||
|
|
|
|||
Loading…
Reference in New Issue