Skip to content

Commit 93682ab

Browse files
Yasumotoartemredkin
authored andcommitted
HTTPCookie is a subtype of HTTPClient (#36)
* HTTPCookie is a subtype of HTTPClient to not collide with Foundations top-level type
1 parent 317f4fa commit 93682ab

File tree

3 files changed

+125
-123
lines changed

3 files changed

+125
-123
lines changed
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the SwiftNIOHTTPClient open source project
4+
//
5+
// Copyright (c) 2018-2019 Swift Server Working Group and the SwiftNIOHTTPClient project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of SwiftNIOHTTPClient project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
import Foundation
16+
import NIOHTTP1
17+
18+
extension HTTPClient {
19+
public struct Cookie {
20+
public var name: String
21+
public var value: String
22+
public var path: String
23+
public var domain: String?
24+
public var expires: Date?
25+
public var maxAge: Int?
26+
public var httpOnly: Bool
27+
public var secure: Bool
28+
29+
public init?(from string: String, defaultDomain: String) {
30+
let components = string.components(separatedBy: ";").map {
31+
$0.trimmingCharacters(in: .whitespaces)
32+
}
33+
34+
if components.isEmpty {
35+
return nil
36+
}
37+
38+
let nameAndValue = components[0].split(separator: "=", maxSplits: 1).map {
39+
$0.trimmingCharacters(in: .whitespaces)
40+
}
41+
42+
guard nameAndValue.count == 2 else {
43+
return nil
44+
}
45+
46+
self.name = nameAndValue[0]
47+
self.value = nameAndValue[1]
48+
49+
self.path = "/"
50+
self.domain = defaultDomain
51+
self.expires = nil
52+
self.maxAge = nil
53+
self.httpOnly = false
54+
self.secure = false
55+
56+
for component in components[1...] {
57+
if component.starts(with: "Path"), let value = parseComponentValue(component) {
58+
self.path = value
59+
continue
60+
}
61+
62+
if component.starts(with: "Domain"), let value = parseComponentValue(component) {
63+
self.domain = value
64+
continue
65+
}
66+
67+
if component.starts(with: "Expires") {
68+
let formatter = DateFormatter()
69+
formatter.locale = Locale(identifier: "en_US")
70+
formatter.timeZone = TimeZone(identifier: "GMT")
71+
formatter.dateFormat = "EEE, dd MMM yyyy HH:mm:ss z"
72+
self.expires = self.parseComponentValue(component).flatMap { formatter.date(from: $0) }
73+
continue
74+
}
75+
76+
if component.starts(with: "Max-Age"), let value = parseComponentValue(component).flatMap(Int.init) {
77+
self.maxAge = value
78+
continue
79+
}
80+
81+
if component == "Secure" {
82+
self.secure = true
83+
continue
84+
}
85+
86+
if component == "HttpOnly" {
87+
self.httpOnly = true
88+
continue
89+
}
90+
}
91+
}
92+
93+
public init(name: String, value: String, path: String = "/", domain: String? = nil, expires: Date? = nil, maxAge: Int? = nil, httpOnly: Bool = false, secure: Bool = false) {
94+
self.name = name
95+
self.value = value
96+
self.path = path
97+
self.domain = domain
98+
self.expires = expires
99+
self.httpOnly = httpOnly
100+
self.secure = secure
101+
}
102+
103+
func parseComponentValue(_ component: String) -> String? {
104+
let nameAndValue = component.split(separator: "=", maxSplits: 1).map {
105+
$0.trimmingCharacters(in: .whitespaces)
106+
}
107+
if nameAndValue.count == 2 {
108+
return nameAndValue[1]
109+
}
110+
return nil
111+
}
112+
}
113+
}
114+
115+
public extension HTTPClient.Response {
116+
internal var cookieHeaders: [HTTPHeaders.Element] {
117+
return headers.filter { $0.name.lowercased() == "set-cookie" }
118+
}
119+
120+
var cookies: [HTTPClient.Cookie] {
121+
return self.cookieHeaders.compactMap { HTTPClient.Cookie(from: $0.value, defaultDomain: self.host) }
122+
}
123+
}

Sources/NIOHTTPClient/HTTPCookie.swift

Lines changed: 0 additions & 121 deletions
This file was deleted.

Tests/NIOHTTPClientTests/HTTPCookieTests.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import XCTest
1919
class HTTPCookieTests: XCTestCase {
2020
func testCookie() {
2121
let v = "key=value; Path=/path; Domain=example.com; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Max-Age=42; Secure; HttpOnly"
22-
let c = HTTPCookie(from: v, defaultDomain: "exampe.org")!
22+
let c = HTTPClient.Cookie(from: v, defaultDomain: "exampe.org")!
2323
XCTAssertEqual("key", c.name)
2424
XCTAssertEqual("value", c.value)
2525
XCTAssertEqual("/path", c.path)
@@ -32,7 +32,7 @@ class HTTPCookieTests: XCTestCase {
3232

3333
func testCookieDefaults() {
3434
let v = "key=value"
35-
let c = HTTPCookie(from: v, defaultDomain: "example.org")!
35+
let c = HTTPClient.Cookie(from: v, defaultDomain: "example.org")!
3636
XCTAssertEqual("key", c.name)
3737
XCTAssertEqual("value", c.value)
3838
XCTAssertEqual("/", c.path)

0 commit comments

Comments
 (0)