Skip to content

Commit

Permalink
Merge pull request #14 from noppoMan/intercept_response
Browse files Browse the repository at this point in the history
Intercept response
  • Loading branch information
noppoMan committed Apr 17, 2016
2 parents a1dfdff + 9341abc commit afa6b93
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 16 deletions.
14 changes: 6 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,19 +77,17 @@ app.get("/articles/:id") { req, responder in


## Middlewares
Middleware is functions that have access to the http request, the http response, and the next function in the application' s request-response cycle.
Middleware is functions that have access to the http request, the http response, and the next function in the application' s request-response cycle. We offers 3 types of registration ways for that.

See more to visit https://github.com/slimane-swift/Middleware

We have 3 registration types for that

### MiddlewareType
```swift

struct AccessLogMiddleware: MiddlewareType {
func respond(req: Request, res: Response, next: MiddlewareChain) {
print("[\(Suv.Time())] \(req.uri.path ?? "/")")
next(.Chain(res))
next(.Chain(req, res))
}
}

Expand Down Expand Up @@ -122,19 +120,19 @@ app.use(AccessLogMiddleware())
```swift
app.use { req, res, next in
print("[\(Suv.Time())] \(req.uri.path ?? "/")")
next(.Chain(res))
next(.Chain(req, res))
}
```

### Intercept Response

Can intercept response at the middleware with passing any values the Response.body object.
Can intercept response at the middleware with storing any values to the Response.body object.
It means, **never reaches** next middleware chains and the route.

```swift
app.use { req, res, next in
var res = res // first, response object is immutable.
res.body("Intercepted at the middleware")
var res = res
res.body("I'm intercepted at the middleware")
next(.Chain(res))
}
```
Expand Down
27 changes: 27 additions & 0 deletions Sources/AsyncMiddlewareWrapper.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//
// AsyncMiddlewareWrapper.swift
// Slimane
//
// Created by Yuki Takei on 4/18/16.
//
//


internal struct AsyncMiddlewareWrapper: AsyncMiddleware {
let handler: AsyncMiddleware

init(handler: AsyncMiddleware){
self.handler = handler
}

func respond(to request: Request, chainingTo next: AsyncResponder, result: (Void throws -> Response) -> Void) {
// Intercept response
if request.response.isIntercepted {
result {
request.response
}
return
}
handler.respond(to: request, chainingTo: next, result: result)
}
}
14 changes: 13 additions & 1 deletion Sources/Request.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@
// Copyright © 2016 MikeTOKYO. All rights reserved.
//

let storageKeyForResponse = __SLIMANE_INTERNAL_STORAGE_KEY + "Response"

extension Request {
var params: [String: String] {
public var params: [String: String] {
get {
guard let params = storage["params"] as? [String: String] else {
return [:]
Expand All @@ -20,4 +22,14 @@ extension Request {
storage["params"] = newValue
}
}

internal var response: Response {
get {
return self.storage[storageKeyForResponse] as! Response
}

set {
self.storage[storageKeyForResponse] = newValue
}
}
}
4 changes: 3 additions & 1 deletion Sources/Response.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,16 @@ extension Response {
return 0
}

public func merged(target: Response) -> Response {
func merged(target: Response) -> Response {
var response = self
for (k,v) in target.headers {
response.headers[k] = v
}
for (k,v) in target.storage {
response.storage[k] = v
}
response.version = target.version
response.status = target.status
response.body = target.body
return response
}
Expand Down
10 changes: 8 additions & 2 deletions Sources/Router.swift → Sources/Slimane+Router.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,18 @@
extension Slimane {
public func use(handler: (Request, Response, MiddlewareChain) -> ()){
let middleware = BasicMiddleware(handler: handler)
use(middleware)
middlewares.append(middleware)
}

public func use(handler: AsyncMiddleware){
public func use(handler: MiddlewareType){
middlewares.append(handler)
}

public func use(handler: AsyncMiddleware){
// Wrap with basicMiddleware to enable response interceptor
let middleware = AsyncMiddlewareWrapper(handler: handler)
middlewares.append(middleware)
}
}

extension Slimane {
Expand Down
File renamed without changes.
10 changes: 6 additions & 4 deletions Sources/Slimane.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,17 @@ public class Slimane {
}

internal func dispatch(request: Request, stream: Skelton.HTTPStream){
self.middlewares.reversed().chain(to: BasicAsyncResponder { _, result in
var request = request
request.response = Response(status: .ok, headers: ["data": Header(Time.rfc1123), "server": Header("Slimane")])

self.middlewares.chain(to: BasicAsyncResponder { _, result in
result {
return Response(status: .ok, headers: ["data": Header(Time.rfc1123), "server": Header("Slimane")])
return request.response
}
})
.respond(to: request, result: { [unowned self] in
do {
var request = request
var response = try $0()
let response = try $0()
if response.isIntercepted {
self.processStream(response, request, stream)
} else {
Expand Down

0 comments on commit afa6b93

Please sign in to comment.