Skip to content

Commit

Permalink
Added support for global middleware.
Browse files Browse the repository at this point in the history
  • Loading branch information
OrkhanAlikhanov committed Jul 5, 2017
1 parent 625060b commit 2f51337
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 3 deletions.
4 changes: 4 additions & 0 deletions HttpSwift.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
9DDDF8751F0C159400C3D4A6 /* Url.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DDDF86A1F0C159400C3D4A6 /* Url.swift */; };
9DDDF8771F0C44D100C3D4A6 /* ErrorHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DDDF8761F0C44D100C3D4A6 /* ErrorHandler.swift */; };
9DDDF8791F0C455C00C3D4A6 /* ServerError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DDDF8781F0C455C00C3D4A6 /* ServerError.swift */; };
9DF8836D1F0D2C9F0060C11F /* Middleware.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DF8836C1F0D2C9F0060C11F /* Middleware.swift */; };
B45BD331C71B497A1D77F294 /* Pods_HttpSwiftTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC48C3375D6FFB8BD32368AD /* Pods_HttpSwiftTests.framework */; };
D09C49846EC39EAF72119492 /* Pods_HttpSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3240C74D92CEDAE3FB8B1743 /* Pods_HttpSwift.framework */; };
/* End PBXBuildFile section */
Expand Down Expand Up @@ -58,6 +59,7 @@
9DDDF86A1F0C159400C3D4A6 /* Url.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Url.swift; sourceTree = "<group>"; };
9DDDF8761F0C44D100C3D4A6 /* ErrorHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ErrorHandler.swift; sourceTree = "<group>"; };
9DDDF8781F0C455C00C3D4A6 /* ServerError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ServerError.swift; sourceTree = "<group>"; };
9DF8836C1F0D2C9F0060C11F /* Middleware.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Middleware.swift; sourceTree = "<group>"; };
DC48C3375D6FFB8BD32368AD /* Pods_HttpSwiftTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_HttpSwiftTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */

Expand Down Expand Up @@ -122,6 +124,7 @@
9DDDF8601F0C159400C3D4A6 /* Response.swift */,
9DDDF8661F0C159400C3D4A6 /* RequestParser.swift */,
9DDDF8631F0C159400C3D4A6 /* ResponseWriter.swift */,
9DF8836C1F0D2C9F0060C11F /* Middleware.swift */,
9DDDF8651F0C159400C3D4A6 /* Regex.swift */,
9DDDF86A1F0C159400C3D4A6 /* Url.swift */,
9DDDF8781F0C455C00C3D4A6 /* ServerError.swift */,
Expand Down Expand Up @@ -356,6 +359,7 @@
9DDDF86E1F0C159400C3D4A6 /* ResponseWriter.swift in Sources */,
9DDDF8751F0C159400C3D4A6 /* Url.swift in Sources */,
9DDDF8771F0C44D100C3D4A6 /* ErrorHandler.swift in Sources */,
9DF8836D1F0D2C9F0060C11F /* Middleware.swift in Sources */,
9DDDF8721F0C159400C3D4A6 /* Server.swift in Sources */,
9DDDF8701F0C159400C3D4A6 /* Regex.swift in Sources */,
);
Expand Down
13 changes: 13 additions & 0 deletions Sources/Middleware.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//
// Middleware.swift
// Http.swift
//
// Created by Orkhan Alikhanov on 7/5/17.
// Copyright © 2017 BiAtoms. All rights reserved.
//

open class Middleware {
open func handle(request: Request, closure: RouteHandler) throws -> Response {
return try closure(request)
}
}
22 changes: 20 additions & 2 deletions Sources/Server.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ open class Server {
open var router = Router()
open var socket: Socket!
open var errorHandler: ErrorHandler.Type = ErrorHandler.self
open var middlewares: [Middleware] = []

open func run(port: SocketSwift.Port = 8080, address: String? = nil) {
DispatchQueue.init(label: "testinggsfsf").async {
Expand All @@ -29,8 +30,8 @@ open class Server {
open func handleConnection(_ client: Socket) {
var request: Request!
do {
request = try RequestParser.parse(socket: client)
let response = try router.respond(to: request)
request = try RequestParser.parse(socket: client)
let response = try getResponse(request)
try client.write(response)
} catch {
do {
Expand All @@ -42,6 +43,23 @@ open class Server {
}
}

open func getResponse(_ request: Request) throws -> Response {
var i = 0

func next() throws -> RouteHandler? {
if i == middlewares.count {
return nil
}
let copied = i
i += 1
return { req in
return try self.middlewares[copied].handle(request: req, closure: try next() ?? self.router.getRoute(for: req).handler)
}
}

return try next()?(request) ?? router.respond(to: request)
}

open func stop() {
socket?.close()
}
Expand Down
82 changes: 81 additions & 1 deletion Tests/Tests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import XCTest
import SocketSwift
import Alamofire
@testable import HttpSwift
typealias Request = HttpSwift.Request


class HttpSwiftTests: XCTestCase {
Expand Down Expand Up @@ -94,7 +95,7 @@ class HttpSwiftTests: XCTestCase {
}

class MyErrorHandler: ErrorHandler {
override class func onError(request: HttpSwift.Request?, error: Error) -> Response? {
override class func onError(request: Request?, error: Error) -> Response? {
if let error = error as? ServerError {
if error == .httpRouteNotFound {
return Response(.ok, body: "Error is handled")
Expand All @@ -105,6 +106,85 @@ class HttpSwiftTests: XCTestCase {
}
}

func testMiddleware() {
server.middlewares = [Req1(), Req2(), Req3(), Res1(), Res2(), Res3()]
let url = "/testMiddleware"
server.get(url) { request in
XCTAssertTrue(request.headers.contains(["middleware": "123"]))
self.server.middlewares = []
return .ok("passed")
}

let ex = expectation(description: "ext")
client.request(url).responseString { r in
XCTAssert(r.response!.contains(["middleware": "CBA"]))
ex.fulfill()
}

waitForExpectations()

//changing order
server.middlewares = [ Res1(), Req1(), Req2(), Req3(), Res2(), Res3()]
let url2 = "/testMiddleware2"
server.get(url2) { request in
XCTAssertTrue(request.headers.contains(["middleware": "123"]))
self.server.middlewares = []
return .ok("passed")
}

let ex2 = expectation(description: "ext")
client.request(url2).responseString { r in
XCTAssert(r.response!.contains(["middleware": "CBA"]))
ex2.fulfill()
}

waitForExpectations()
}

class Req1: Middleware {
override func handle(request: Request, closure: (Request) throws -> Response) throws -> Response {
request.headers["middleware"] = (request.headers["middleware"] ?? "") + "1"
return try closure(request)
}
}

class Req2: Middleware {
override func handle(request: Request, closure: (Request) throws -> Response) throws -> Response {
request.headers["middleware"] = (request.headers["middleware"] ?? "") + "2"
return try closure(request)
}
}

class Req3: Middleware {
override func handle(request: Request, closure: (Request) throws -> Response) throws -> Response {
request.headers["middleware"] = (request.headers["middleware"] ?? "") + "3"
return try closure(request)
}
}

class Res1: Middleware {
override func handle(request: Request, closure: (Request) throws -> Response) throws -> Response {
let response = try closure(request)
response.headers["middleware"] = (response.headers["middleware"] ?? "") + "A"
return response
}
}

class Res2: Middleware {
override func handle(request: Request, closure: (Request) throws -> Response) throws -> Response {
let response = try closure(request)
response.headers["middleware"] = (response.headers["middleware"] ?? "") + "B"
return response
}
}

class Res3: Middleware {
override func handle(request: Request, closure: (Request) throws -> Response) throws -> Response {
let response = try closure(request)
response.headers["middleware"] = (response.headers["middleware"] ?? "") + "C"
return response
}
}
}
private extension SessionManager {
func request(_ url: String,
Expand Down

0 comments on commit 2f51337

Please sign in to comment.