Skip to content

Commit 5efaa09

Browse files
committed
Extract Response into a protocol and rename code in statusCode #56
1 parent 659735b commit 5efaa09

File tree

2 files changed

+70
-18
lines changed

2 files changed

+70
-18
lines changed

KakapoExample/KakapoTests/RouterTests.swift

+37-3
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,18 @@ import Nimble
1313

1414
@testable import Kakapo
1515

16+
struct CustomResponse: ResponseFieldsProvider {
17+
let statusCode: Int
18+
let body: Serializable
19+
let headerFields: [String : String]?
20+
21+
init(statusCode: Int, body: Serializable, headerFields: [String : String]? = nil) {
22+
self.statusCode = statusCode
23+
self.body = body
24+
self.headerFields = headerFields
25+
}
26+
}
27+
1628
class RouterTests: QuickSpec {
1729

1830
override func spec() {
@@ -304,7 +316,7 @@ class RouterTests: QuickSpec {
304316
var responseDictionary: NSDictionary? = nil
305317

306318
router.get("/users/:id"){ request in
307-
return Response(code: 200, body: db.find(UserFactory.self, id: Int(request.components["id"]!)!))
319+
return Response(statusCode: 200, body: db.find(UserFactory.self, id: Int(request.components["id"]!)!))
308320
}
309321

310322
NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: "http://www.test.com/users/2")!) { (data, response, _) in
@@ -324,7 +336,7 @@ class RouterTests: QuickSpec {
324336

325337
router.get("/users/:id"){ request in
326338
// Optional.Some("none") -> not valid JSON object
327-
return Response(code: 400, body: Optional.Some("none"))
339+
return Response(statusCode: 400, body: Optional.Some("none"))
328340
}
329341

330342
NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: "http://www.test.com/users/2")!) { (data, response, _) in
@@ -341,7 +353,7 @@ class RouterTests: QuickSpec {
341353
var allHeaders: [String : String]? = nil
342354

343355
router.get("/users/:id"){ request in
344-
return Response(code: 400, body: ["id" : "foo", "type" : "User"], headerFields: ["access_token" : "094850348502", "user_id" : "124"])
356+
return Response(statusCode: 400, body: ["id" : "foo", "type" : "User"], headerFields: ["access_token" : "094850348502", "user_id" : "124"])
345357
}
346358

347359
NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: "http://www.test.com/users/2")!) { (data, response, _) in
@@ -354,6 +366,27 @@ class RouterTests: QuickSpec {
354366
expect(allHeaders?["bar"]).toEventually(beNil())
355367
}
356368

369+
it("should gets the response fields from custom response object adopting the ResponseFieldsProvider protocol") {
370+
var allHeaders: [String : String]? = nil
371+
var responseDictionary: NSDictionary? = nil
372+
var statusCode: Int? = nil
373+
374+
router.get("/users/:id"){ request in
375+
return CustomResponse(statusCode: 400, body: ["id" : 2], headerFields: ["access_token" : "094850348502"])
376+
}
377+
378+
NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: "http://www.test.com/users/2")!) { (data, response, _) in
379+
let response = response as! NSHTTPURLResponse
380+
allHeaders = response.allHeaderFields as? [String : String]
381+
responseDictionary = try! NSJSONSerialization.JSONObjectWithData(data!, options: .MutableLeaves) as? NSDictionary
382+
statusCode = response.statusCode
383+
}.resume()
384+
385+
expect(allHeaders?["access_token"]).toEventually(equal("094850348502"))
386+
expect(statusCode).toEventually(equal(400))
387+
expect(responseDictionary?["id"]).toEventually(be(2))
388+
}
389+
357390
it("should return the specified array of objects when requesting a registered url") {
358391
db.create(UserFactory.self, number: 20)
359392

@@ -610,6 +643,7 @@ class RouterTests: QuickSpec {
610643

611644
expect(thirdInfo).toEventually(beNil())
612645
expect(thirdResponseURL?.host).toEventually(equal("www.another.com"))
646+
Swift.assert(thirdResponseURL?.host != nil)
613647
}
614648

615649
it("Should fail when not properly registering Routers") {

Source/Router.swift

+33-15
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import Foundation
1212
A RouteHandler used when registering different HTTP methods, which can return any Serializable object.
1313

1414
By default, though, the Router will return a 200 status code and no header fields when only returning a Serializable object.
15-
In order to customize that behavior, check `Response` to provide custom status code and header fields.
15+
In order to customize that behavior, check `ResponseFieldsProvider` to provide custom status code and header fields.
1616
*/
1717
public typealias RouteHandler = Request -> Serializable?
1818

@@ -34,29 +34,47 @@ public struct Request {
3434
}
3535

3636
/**
37-
A Response struct which can be used in `RouteHandlers` to provide valid responses.
37+
A protocol to adopt when a Serializable Object needs to also provide response status code and/or headerFields
38+
You may usually use `Response` to wrap your `Serializable` object to just achieve the result or directly implement the protocol. For examply `JSONAPISerializer` implement the protocol in order to be able to provide custom status code in the response.
39+
*/
40+
public protocol ResponseFieldsProvider: CustomSerializable {
41+
/// The response status code
42+
var statusCode: Int { get }
43+
44+
/// The Serializable body object
45+
var body: Serializable { get }
46+
47+
/// An optional dictionary holding the response header fields
48+
var headerFields: [String : String]? { get }
49+
}
50+
51+
extension ResponseFieldsProvider {
52+
53+
public func customSerialize() -> AnyObject? {
54+
return body.serialize()
55+
}
56+
}
57+
58+
/**
59+
A ResponseFieldsProvider implementation which can be used in `RouteHandlers` to provide valid responses that can return different status code than the default (200) or headerFields.
3860

3961
The struct provides, appart from a Serializable `body` object, a status code and header fields.
4062
*/
41-
public struct Response: CustomSerializable {
42-
/// The response code
43-
let code: Int
63+
public struct Response: ResponseFieldsProvider {
64+
/// The response status code
65+
public let statusCode: Int
4466

4567
/// The Serializable body object
46-
let body: Serializable
68+
public let body: Serializable
4769

4870
/// An optional dictionary holding the response header fields
49-
let headerFields: [String : String]?
71+
public let headerFields: [String : String]?
5072

51-
public init(code: Int, body: Serializable, headerFields: [String : String]? = nil) {
52-
self.code = code
73+
public init(statusCode: Int, body: Serializable, headerFields: [String : String]? = nil) {
74+
self.statusCode = statusCode
5375
self.body = body
5476
self.headerFields = headerFields
5577
}
56-
57-
public func customSerialize() -> AnyObject? {
58-
return body.serialize()
59-
}
6078
}
6179

6280
/**
@@ -146,8 +164,8 @@ public class Router {
146164
}
147165
}
148166

149-
if let serializableObject = serializableObject as? Response {
150-
statusCode = serializableObject.code
167+
if let serializableObject = serializableObject as? ResponseFieldsProvider {
168+
statusCode = serializableObject.statusCode
151169
headerFields = serializableObject.headerFields
152170
}
153171

0 commit comments

Comments
 (0)