update routing

This commit is contained in:
Tanner Nelson 2016-07-30 21:44:30 -04:00
parent fe27e04af4
commit 67ee447ae1
No known key found for this signature in database
GPG Key ID: 9C24375C64856B76
8 changed files with 372 additions and 15 deletions

View File

@ -29,6 +29,12 @@ menu:
guide:
name: Guide
items:
guide-droplet:
text: Droplet
relativeUrl: guide/droplet.html
guide-folder-structure:
text: Folder Structure
relativeUrl: guide/folder-structure.html
guide-routing:
text: Routing
relativeUrl: guide/routing.html

View File

@ -28,7 +28,7 @@ export PATH="$SWIFTENV_ROOT/bin:$PATH"
eval "$(swiftenv init -)"
```
Note: macOS uses `~/.bash_profile` and Ubuntu uses `~/.bashrc`
> Note: macOS uses `~/.bash_profile` and Ubuntu uses `~/.bashrc`
### Verify

View File

@ -14,7 +14,7 @@ Run the following script to install the [Toolbox](https://github.com/qutheory/to
curl -sL toolbox.qutheory.io | bash
```
Note: You must have the correct version of Swift 3 installed.
> Note: You must have the correct version of Swift 3 installed.
## Verify

82
guide/droplet.md Normal file
View File

@ -0,0 +1,82 @@
---
currentMenu: guide-droplet
---
# Droplet
The `Droplet` is a service container that gives you access to many of Vapor's facilities. It is responsible for registering routes, starting the server, appending middleware, and more.
## Initialization
As you have probably already seen, the only thing required to create an instance of `Droplet` is to import Vapor.
```swift
import Vapor
let drop = Droplet()
// your magic here
drop.start()
```
Creation of the `Droplet` normally happens in the `main.swift` file.
## Environment
The `environment` property contains the current environment your application is running in. Usually development, testing, or production.
```swift
if drop.config.environment == .production {
...
}
```
The environment affects [Config](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
```
If you are in Xcode, you can pass arguments through the scheme editor.
> Note: Debug logs can reduce the number of requests your application can handle per second. Enabling the production environment can improve performance.
## Working Directory
The `workDir` property contains a path to the current working directory of the application relative to where it was started. By default, this property assumes you started the Droplet from its root directory.
```swift
drop.workDir // "/var/www/my-project/"
```
You can override the working directory through the `Droplet`'s initializer, or by passing the `--workdir` argument.
```sh
vapor run serve --workdir="/var/www/my-project"
```
## Initialization
The `Droplet` has several customizable properties.
Most plugins for Vapor come with a [Provider](providers.md), these take care of configuration details for you.
```swift
Droplet(
arguments: [String]?,
workDir workDirProvided: String?,
config configProvided: Config?,
localization localizationProvided: Localization?,
server: ServerProtocol.Type?,
sessions: Sessions?,
hash: Hash?,
console: ConsoleProtocol?,
log: Log?,
client: ClientProtocol.Type?,
database: Database?,
preparations: [Preparation.Type],
providers: [Provider.Type],
initializedProviders: [Provider]
)
```

88
guide/folder-structure.md Normal file
View File

@ -0,0 +1,88 @@
---
currentMenu: guide-folder-structure
---
# Folder Structure
The first step to creating an awesome application is knowing where things are. If you created your project using the [Toolbox](../getting-started/toolbox.md) or from a template, you will already have the folder structure created.
If you are making a Vapor application from scratch, this will show you exactly how to set it up.
## Minimum Folder Structure
We recommend putting all of your Swift code inside of the `App/` folder. This will allow you to create subfolders in `App/` to organize your models and resources.
This works best with the Swift package manager's restrictions on how packages should be structured.
```
.
├── App
│ └── main.swift
├── Public
└── Package.swift
```
The `Public` folder is where all publicly accessible files should go. This folder will be automatically checked every time a URL is requested that is not found in your routes.
> Note: The `FileMiddleware` is responsible for accessing files from the `Public` folder.
## Models
The `Models` folder is a recommendation of where you can put your database and other models, following the MVC pattern.
```
.
├── App
. └── Models
. └── User.swift
```
## Controllers
The `Controllers` folder is a recommendation of where you can put your route controllers, following the MVC pattern.
```
.
├── App
. └── Controllers
. └── UserController.swift
```
## Views
The `Views` folder in `Resources` is where Vapor will look when you render views.
```
.
├── App
└── Resources
└── Views
└── user.html
```
The following code would load the `user.html` file.
```swift
drop.view("user.html")
```
## Config
Vapor has a sophisticated configuration system that involves a hierarchy of configuration importance.
```
.
├── App
└── Config
└── app.json // default app.json
└── development
└── app.json // overrides app.json when in development environment
└── production
└── app.json // overrides app.json when in production environment
└── secrets
└── 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](config.md).
Learn about changing environments (the `--env=` flag) in the [Droplet](droplet.md) section.

View File

@ -4,8 +4,163 @@ currentMenu: guide-routing
# Routing
This is how routing works.
Routes in Vapor can be defined in any file that has access to your instance of `Droplet`. This is usually in the `main.swift` file.
## Basic
The most basic route includes a method, path, and closure.
```swift
let drop = Droplet()
```
drop.get("welcome") { request in
return "Hello"
}
```
The standard HTTP methods are available including `get`, `post`, `put`, `patch`, `delete`, and `options`.
You can also use `any` to match all methods.
## Request
The first parameter passed into your route closure is an instance of [Request](request.md). This contains the method, URI, body, and more.
```swift
let method = request.method
```
When you add a parameter type, like `String.self`, the closure will be required to contain another input variable. This variable will be the same type. In this case, `String`.
## JSON
To respond with JSON, simply wrap your data structure with `JSON(node: )`
```swift
drop.get("version") { request in
return try JSON(node: ["version": "1.0"])
}
```
## Response Representable
All routing closures can return a [ResponseRepresentable](response.md) data structure. By default, Strings and JSON conform to this protocol, but you can add your own.
```swift
public protocol ResponseRepresentable {
func makeResponse() throws -> Response
}
```
## Parameters
Parameters are described by passing the type of data you would like to receive.
```swift
drop.get("hello", String.self) { request, name in
return "Hello \(name)"
}
```
## String Initializable
Any type that conforms to `StringInitializable` can be used as a parameter. By default, `String` and `Int` conform to this protocol, but you can add your own.
```swift
struct User: StringInitializable {
...
}
app.get("users", User.self) { request, user in
return "Hello \(user.name)"
}
```
Using Swift extensions, you can extend your existing types to support this behavior.
```swift
extension User: StringInitializable {
init?(from string: String) throws {
guard let int = Int(string) else {
return nil //Will Abort.InvalidRequest
}
guard let user = User.find(int) else {
throw UserError.NotFound
}
self = user
}
}
```
You can throw your own errors or return `nil` to throw the default error.
## Groups
Prefix a group of routes with a common string, host, or middleware using `group` and `grouped`.
### Group
Group (without the "ed" at the end) takes a closure that is passed a `GroupBuilder`.
```swift
drop.group("v1") { v1 in
v1.get("users") { request in
// get the users
}
}
```
### Grouped
Grouped returns a `GroupBuilder` that you can pass around.
```swift
let v1 = drop.grouped("v1")
v1.get("users") { request in
// get the users
}
```
### Middleware
You can add middleware to a group of routes. This is especially useful for authentication.
```swift
drop.group(AuthMiddleware()) { authorized in
authorized.get("token") { request in
// has been authorized
}
}
```
### Host
You can limit the host for a group of routes.
```
drop.group(host: "qutheory.io") { qt
qt.get { request in
// only responds to requests to qutheory.io
}
}
```
### Chaining
Groups can be chained together.
```swift
drop.grouped(host: "qutheory.io").grouped(AuthMiddleware()).group("v1") { authedSecureV1 in
// add routes here
}
```
## Custom Routing
Vapor still supports traditional routing for custom use-cases or long URLs.
```swift
drop.get("users/:user_id") { request in
request.parameters["user_id"] // String?
}
```

View File

@ -57,7 +57,7 @@
</nav>
<main>
<a href="https://github.com/qutheory/documentation/blob/master/CONTRIBUTING.md" class="edit">✏️ Edit</a>
<a href="https://github.com/qutheory/documentation/blob/master/CONTRIBUTING.md" class="edit">✎ Edit on GitHub</a>
{{ content | raw }}
</main>

View File

@ -20,7 +20,7 @@ a:hover {
}
h1 {
font-size: 48px;
font-size: 42px;
font-weight: 200;
}
@ -112,7 +112,7 @@ nav {
left: 0;
top: 0;
bottom: 0;
width: 200px;
width: 216px;
z-index: 8;
padding-top: 96px;
@ -127,6 +127,7 @@ nav a {
font-size: 14px;
display: block;
color: #777;
font-size: 12px;
height: 24px;
}
@ -141,9 +142,9 @@ nav .active a {
nav h3 {
text-transform: uppercase;
color: #999;
color: #bbb;
font-size: 14px;
margin-bottom: 4px;
margin-bottom: 6px;
font-weight: 400;
}
@ -154,7 +155,7 @@ nav ul, nav ul li {
}
nav ul {
margin-bottom: 24px;
margin-bottom: 18px;
}
div.scroll {
@ -169,7 +170,7 @@ main {
font-weight: 200;
padding: 22px;
padding-top: 110px;
padding-left: 222px;
padding-left: 240px;
position: absolute;
position: relative;
@ -191,15 +192,39 @@ main a.edit {
border-bottom: none;
}
main h1 {
margin-bottom: 12px;
}
main h2 {
margin-top: 24px;
border-bottom: 1px dotted rgba(0, 0, 0, 0.10);
margin-bottom: 12px;
border-bottom: 1px dotted rgba(0, 0, 0, 0.10);
}
main h3 {
margin-top: 18px;
}
main p {
margin-top: 0;
margin-bottom: 6px;
margin-bottom: 12px;
line-height: 1.75;
}
main blockquote {
background: rgba(247, 202, 201, 0.2);
margin-top: 18px;
margin-bottom: 18px;
margin-left: 0;
padding: 6px;
padding-left: 12px;
border-left: 5px solid #f6cfcf;
}
main blockquote p {
margin: 0;
padding: 0;
}
pre, code {
@ -209,10 +234,11 @@ pre, code {
p code {
background: #fbfbfb;
border-radius: 10px;
border-radius: 5px;
padding: 3px;
display: inline-block;
color: #92a0b9;
box-shadow: 0 1px 0px 0px rgba(0, 0, 0, 0.1);
}
pre {