Skip to content
This repository was archived by the owner on Dec 10, 2024. It is now read-only.

Commit 83a4b1b

Browse files
committed
Merge branch 'link_header_support' into swift-2.0
2 parents 3d9428c + 6674e2a commit 83a4b1b

File tree

6 files changed

+81
-2
lines changed

6 files changed

+81
-2
lines changed

Docs/QuickStart.playground/Contents.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,22 @@ if let json = Just.post(
178178
}
179179

180180

181+
//: ## Link Headers
182+
//: Many HTTP APIs feature Link headers. They make APIs more self describing
183+
//: and discoverable.
184+
//:
185+
//: Github uses these for pagination in their API, for example:
186+
187+
let gh = Just.head("https://api.github.com/users/dduan/repos?page=1&per_page=5")
188+
gh.headers["link"] // <https://api.github.com/user/75067/repos?page=2&per_page=5>; rel="next", <https://api.github.com/user/75067/repos?page=9&per_page=5>; rel="last"
189+
190+
//: Just will automatically parse these link headers and make them easily consumable:
191+
192+
gh.links["next"] // ["rel": "next", "url":"https://api.github.com/user/75067/repos?page=2&per_page=5"]
193+
gh.links["last"] // ["rel": "last", "url":"https://api.github.com/user/75067/repos?page=9&per_page=5"]
194+
195+
//: (be aware of Github's rate limits when you play with these)
196+
181197
//: ## Cookies
182198
//:
183199
//: If you expect the server to return some cookie, you can find them this way:

Docs/QuickStart.playground/timeline.xctimeline

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,17 @@
33
version = "3.0">
44
<TimelineItems>
55
<LoggerValueHistoryTimelineItem
6-
documentLocation = "#CharacterRangeLen=0&amp;CharacterRangeLoc=0&amp;EndingColumnNumber=20&amp;EndingLineNumber=179&amp;StartingColumnNumber=9&amp;StartingLineNumber=179&amp;Timestamp=455693370.322447"
6+
documentLocation = "#CharacterRangeLen=0&amp;CharacterRangeLoc=0&amp;EndingColumnNumber=20&amp;EndingLineNumber=182&amp;StartingColumnNumber=9&amp;StartingLineNumber=182&amp;Timestamp=462872685.952829"
7+
selectedRepresentationIndex = "0"
8+
shouldTrackSuperviewWidth = "NO">
9+
</LoggerValueHistoryTimelineItem>
10+
<LoggerValueHistoryTimelineItem
11+
documentLocation = "#CharacterRangeLen=6&amp;CharacterRangeLoc=2853&amp;EndingColumnNumber=7&amp;EndingLineNumber=81&amp;StartingColumnNumber=1&amp;StartingLineNumber=81&amp;Timestamp=462872716.632806"
12+
selectedRepresentationIndex = "0"
13+
shouldTrackSuperviewWidth = "NO">
14+
</LoggerValueHistoryTimelineItem>
15+
<LoggerValueHistoryTimelineItem
16+
documentLocation = "#CharacterRangeLen=0&amp;CharacterRangeLoc=7062&amp;EndingColumnNumber=17&amp;EndingLineNumber=195&amp;StartingColumnNumber=1&amp;StartingLineNumber=194&amp;Timestamp=462873916.609416"
717
selectedRepresentationIndex = "0"
818
shouldTrackSuperviewWidth = "NO">
919
</LoggerValueHistoryTimelineItem>

Docs/QuickStart.zip

1.34 KB
Binary file not shown.

Just/Just.swift

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ public final class HTTPResult : NSObject {
117117
}
118118
return nil
119119
}
120+
120121
public var statusCode: Int? {
121122
if let theResponse = self.response as? NSHTTPURLResponse {
122123
return theResponse.statusCode
@@ -133,7 +134,7 @@ public final class HTTPResult : NSObject {
133134

134135
public lazy var headers:CaseInsensitiveDictionary<String,String> = {
135136
return CaseInsensitiveDictionary<String,String>(dictionary: (self.response as? NSHTTPURLResponse)?.allHeaderFields as? [String:String] ?? [:])
136-
}()
137+
}()
137138

138139
public lazy var cookies:[String:NSHTTPCookie] = {
139140
let foundCookies: [NSHTTPCookie]
@@ -156,6 +157,35 @@ public final class HTTPResult : NSObject {
156157
public var url:NSURL? {
157158
return response?.URL
158159
}
160+
public lazy var links: [String:[String:String]] = {
161+
var result = [String:[String:String]]()
162+
if let content = self.headers["link"] {
163+
content.componentsSeparatedByString(",").forEach { s in
164+
let linkComponents = s.componentsSeparatedByString(";").map { ($0 as NSString).stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet()) }
165+
if linkComponents.count > 1 { // although a link without a rel is valid, there's no way to reference it
166+
let urlComponent = linkComponents.first!
167+
let urlRange = urlComponent.startIndex.advancedBy(1)..<urlComponent.endIndex.advancedBy(-1)
168+
var link: [String: String] = ["url": String(urlComponent.characters[urlRange])]
169+
linkComponents.dropFirst().forEach { s in
170+
if let equalIndex = s.characters.indexOf("=") {
171+
let componentKey = String(s.characters[s.startIndex..<equalIndex])
172+
let componentValueCharacters = s.characters[equalIndex.advancedBy(1)..<s.endIndex]
173+
if componentValueCharacters.first == "\"" && componentValueCharacters.last == "\"" {
174+
let unquotedValueRange = componentValueCharacters.startIndex.advancedBy(1)..<componentValueCharacters.endIndex.advancedBy(-1)
175+
link[componentKey] = String(componentValueCharacters[unquotedValueRange])
176+
} else {
177+
link[componentKey] = String(componentValueCharacters)
178+
}
179+
}
180+
}
181+
if let rel = link["rel"] {
182+
result[rel] = link
183+
}
184+
}
185+
}
186+
}
187+
return result
188+
}()
159189
}
160190

161191

JustTests/JustSpecs.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -640,5 +640,27 @@ class JustSpec: QuickSpec {
640640
expect(r.ok).to(beTrue())
641641
}
642642
}
643+
644+
describe("link header support") {
645+
it("should always have a value for .links") {
646+
expect(Just.get("https://api.github.com/users/dduan/repos?page=1&per_page=10").links).toNot(beNil())
647+
}
648+
it("should contain key \"next\" for this specific github API") {
649+
let r = Just.get("https://api.github.com/users/dduan/repos?page=1&per_page=10")
650+
expect(r.ok).to(beTrue())
651+
expect(r.links["next"]).toNot(beNil())
652+
}
653+
it("should contain key \"last\" for this specific github API") {
654+
let r = Just.get("https://api.github.com/users/dduan/repos?page=1&per_page=10")
655+
expect(r.ok).to(beTrue())
656+
expect(r.links["last"]).toNot(beNil())
657+
}
658+
it("should contain key \"url\" in \"next\" and \"last\" for this specific github API") {
659+
let r = Just.get("https://api.github.com/users/dduan/repos?page=1&per_page=10")
660+
expect(r.links["next"]?["url"]).toNot(beNil())
661+
expect(r.links["last"]?["url"]).toNot(beNil())
662+
663+
}
664+
}
643665
}
644666
}

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ Just lets you to the following effortlessly:
2525
- timeouts
2626
- synchrounous / asyncrounous requests
2727
- upload / download progress tracking for asynchronous requests
28+
link headers
2829
- friendly accessible results
2930

3031
# Use

0 commit comments

Comments
 (0)