Skip to content

Commit

Permalink
drop.middleware + package updates
Browse files Browse the repository at this point in the history
  • Loading branch information
tanner0101 committed Jun 6, 2017
1 parent c554bd2 commit 5110e9a
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 42 deletions.
19 changes: 14 additions & 5 deletions 2.0/docs/auth/getting-started.md
Expand Up @@ -10,6 +10,9 @@ authorization easy and secure. It supports common auth patterns such as:

Auth's modular, protocol-based nature also makes it a great foundation for custom auth needs.

!!! tip
Use `vapor new <name> --template=vapor/auth-template` to create a new [project template](https://github.com/vapor/auth-template) with AuthProvider and samples included.

## Package

To use Auth, you will need to have the [Auth Provider](https://github.com/vapor/auth-provider) added to your project.
Expand Down Expand Up @@ -130,12 +133,18 @@ import Vapor
import AuthProvider
import FluentProvider

let drop = try Droplet()
let config = try Config()

config.preparations.append(ExampleUser.self)
config.preparations.append(ExampleToken.self)

let drop = try Droplet(config)

drop.preparations += [ExampleUser.self, ExampleToken.self]

let tokenMiddleware = TokenAuthenticationMiddleware(ExampleUser.self)
drop.middleware.append(tokenMiddleware)

/// use this route group for protected routes
let authed = drop.grouped(tokenMiddleware)
```

Since our `ExampleUser` class is `TokenAuthenticatable`, we can pass it into the middleware's init method.
Expand All @@ -146,11 +155,11 @@ Since our `ExampleUser` class is `TokenAuthenticatable`, we can pass it into the

### Route

Now that our Droplet is setup to require token authentication globally, let's add a route to
Now that we have a route group protected by our TokenMiddleware, let's add a route to
return the authenticated user's name.

```swift
drop.get("me") { req in
authed.get("me") { req in
// return the authenticated user's name
return try req.user().name
}
Expand Down
23 changes: 17 additions & 6 deletions 2.0/docs/auth/password.md
Expand Up @@ -73,18 +73,29 @@ import AuthProvider

let drop = try Droplet()

drop.middleware += [
PasswordAuthenticationMiddleware(User.self)
]
let passwordMiddleware = PasswordAuthenticationMiddleware(User.self)

let authed = try drop.grouped(passwordMiddleware)

try drop.run()
```

All routes on this Droplet will now be protected by the password middleware.
All routes added to the `authed` route group will be protected by the password middleware.

!!! seealso
If you only want to require authentication for certain routes, look at our
[Route Group](../routing/group.md) section in the routing docs.
If you only want to globally require the password middleware, checkout the
[Middleware Config](../http/middleware.md/#config) section in the HTTP docs.

### Route

Now you can add a route to return the authenticated user.

```swift
authed.get("me") { req in
// return the authenticated user
return try req.auth.assertAuthenticated(User.self)
}
```

Call `req.user.authenticated(User.self)` to get access to the authenticated user.

Expand Down
10 changes: 4 additions & 6 deletions 2.0/docs/auth/persist.md
Expand Up @@ -91,22 +91,20 @@ import AuthProvider

let drop = try Droplet()

drop.middleware += [
sessionsMiddleware, persistMiddleware, passwordMiddleware
]
let authed = drop.grouped([sessionsMiddleware, persistMiddleware, passwordMiddleware])
```

!!! seealso
If you only want to require authentication for certain routes, look at our
[Route Group](../routing/group.md) section in the routing docs.
If you only want to globally require the password middleware, checkout the
[Middleware Config](../http/middleware.md/#config) section in the HTTP docs.


### Route

Now you can add a route to return the authenticated user.

```swift
drop.get("me") { req in
authed.get("me") { req in
// return the authenticated user
return try req.auth.assertAuthenticated(User.self)
}
Expand Down
17 changes: 17 additions & 0 deletions 2.0/docs/fluent/database.md
Expand Up @@ -176,6 +176,23 @@ vapor run prepare --revert --all

Logging queries is a great way to find optimizations for your application and track down bugs.

The easiest way to log queries is to enable logging in your `fluent.json` file.

`Config/fluent.json`
```json
{
...,
"log": true,
...
}
```

This will emit info-level logs for all database queries.

### Custom

You can also hook into the database's query logging callback to execute custom logic.

```swift
drop.database?.log = { query in
print(query)
Expand Down
1 change: 1 addition & 0 deletions 2.0/docs/getting-started/toolbox.md
Expand Up @@ -55,6 +55,7 @@ vapor new <name> [--template]
| API | --template=api | JSON API with Fluent database. |
| Web | --template=web | HTML website with Leaf templates. |

View a list of all [templates](https://github.com/search?utf8=✓&q=topic%3Avapor+topic%3Atemplate&type=Repositories) on GitHub.

!!! note
If you do not specify a template option, the API template will be used.
Expand Down
77 changes: 52 additions & 25 deletions 2.0/docs/http/middleware.md
Expand Up @@ -25,10 +25,20 @@ final class VersionMiddleware: Middleware {
We then supply this middleware to our `Droplet`.

```swift
let drop = Droplet()
drop.middleware.append(VersionMiddleware())
import Vapor

let config = try Config()

config.addConfigurable(middleware: VersionMiddleware(), name: "version")

let drop = try Droplet(config)
```

!!! tip
You can now dynamically enable and disable this mdidleware from your configuration files.
Simply add `"version"` to the `"middleware"` array in your `droplet.json` file.
See the [configuration](#configuration) section for more information.

You can imagine our `VersionMiddleware` sitting in the middle of a chain that connects the client and our server. Every request and response that hits our server must go through this chain of middleware.

![Middleware](https://cloud.githubusercontent.com/assets/1342803/17382676/0b51d6d6-59a0-11e6-9cbb-7585b9ab9803.png)
Expand Down Expand Up @@ -114,12 +124,15 @@ final class FooErrorMiddleware: Middleware {
}
```

We just need to append this middleware to the `Droplet`.
We just need to add this middleware to our droplet's config.

```swift
drop.middleware.append(FooErrorMiddleware())
config.addConfigurable(middleware: FooErrorMiddleware(), name: "foo-error")
```

!!! tip
Don't forget to enable the middleware in your `droplet.json` file.

Now our route closures look a lot better and we don't have to worry about code duplication.

```swift
Expand All @@ -145,41 +158,46 @@ Anything added to the `authed` group must pass through `AuthMiddleware`. Because

## Configuration

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](../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.
You can use the [configuration](../configs/config.md) files to enabled or disable middleware dynamically. This is especially useful if you have middleware that should, for example, run only in production.

Appending configurable middleware looks like the following:

```swift
let drop = Droplet()
drop.addConfigurable(middleware: myMiddleware, name: "my-middleware")
let config = try Config()

config.addConfigurable(middleware: myMiddleware, name: "my-middleware")

let drop = Droplet(config)
```

Then, in the `Config/droplet.json` file, add `my-middleware` to the appropriate `middleware` array.
Then, in the `Config/droplet.json` file, add `my-middleware` to the `middleware` array.

```json
{
...
"middleware": {
"server": [
...
"my-middleware",
...
],
"client": [
...
]
...
"my-middleware",
...
},
...
}
```

If the name of the added middleware appears in the `server` array for the loaded configuration, it will be added to the server's middleware when the application boots.
If the name of the added middleware appears in the middleware array it will be added to the server's middleware when the application boots.

The ordering of middleware is respected.

Likewise, if the middleware appears in the `client` array for the loaded configuration, it will be added to the client's middleware.
## Manual

One middleware can be appended to both the Client and the Server, and can be added multiple times. The ordering of middleware is respected.
You can also hardcode your middleware if you don't want to use configuration files.

```swift
import Vapor

let versionMiddleware = VersionMiddleware()
let drop = try Droplet(middleware: [versionMiddleware])
```

## Advanced

Expand Down Expand Up @@ -210,6 +228,13 @@ final class PokemonMiddleware: Middleware {
return response
}
}

extension PokemonMiddleware: ConfigInitializable {
convenience init(config: Config) throws {
let view = try config.resolveView()
self.init(view)
}
}
```

#### Response
Expand All @@ -233,12 +258,11 @@ Your closures can now look something like this:

```swift
import Vapor
import HTTP

let drop = try Droplet()
let config = try Config()
config.addConfigurable(middleware: PokemonMiddleware.init, name: "pokemon")

let pokemonMiddleware = PokemonMiddleware(drop.view)
drop.middleware.append(pokemonMiddleware)
let drop = try Droplet(config)

drop.get("pokemon", Pokemon.self) { request, pokemon in
let response = Response()
Expand All @@ -247,6 +271,9 @@ drop.get("pokemon", Pokemon.self) { request, pokemon in
}
```

!!! tip
Don't forget to add `"pokemon"` to your `droplet.json` middleware array.

#### Response Representable

If you want to go a step further, you can make `Pokemon` conform to `ResponseRepresentable`.
Expand Down
24 changes: 24 additions & 0 deletions 2.0/docs/http/response.md
Expand Up @@ -118,3 +118,27 @@ let json = request.response["hello"]
## Key Paths

For more on KeyPaths, visit [here](./request.md#key-paths)

## Serving Files

If you are simply looking to serve files from your public directory,
it may be useful to look at 'FileMiddleware' instead.

```swift
let res = try Response(filePath: "/path/to/file.txt")
```

Use this to initialize a file response for the exact file path.
If using from a public folder for example, the file name should be appended
to the public directory, ie: `drop.publicDir + "myFile.cool"`

```swift
Response(filePath: String, ifNoneMatch: String? = nil, chunkSize: Int = 2048) throws
```

If none match represents an ETag that will be used to check if the file has
changed since the last load by the client. This allows clients like browsers
to cache their files and avoid downloading resources unnecessarily.
Most often calculated w/ https://tools.ietf.org/html/rfc7232#section-3.2

For an example of how this is used, look at 'FileMiddleware'.

0 comments on commit 5110e9a

Please sign in to comment.