mirror of
https://github.com/swift-server/async-http-client.git
synced 2026-05-03 07:32:29 +00:00
124 lines
4.1 KiB
Swift
124 lines
4.1 KiB
Swift
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This source file is part of the AsyncHTTPClient open source project
|
|
//
|
|
// Copyright (c) 2018-2019 Swift Server Working Group and the AsyncHTTPClient project authors
|
|
// Licensed under Apache License v2.0
|
|
//
|
|
// See LICENSE.txt for license information
|
|
// See CONTRIBUTORS.txt for the list of AsyncHTTPClient project authors
|
|
//
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
import Foundation
|
|
import NIOHTTP1
|
|
|
|
extension HTTPClient {
|
|
public struct Cookie {
|
|
public var name: String
|
|
public var value: String
|
|
public var path: String
|
|
public var domain: String?
|
|
public var expires: Date?
|
|
public var maxAge: Int?
|
|
public var httpOnly: Bool
|
|
public var secure: Bool
|
|
|
|
public init?(from string: String, defaultDomain: String) {
|
|
let components = string.components(separatedBy: ";").map {
|
|
$0.trimmingCharacters(in: .whitespaces)
|
|
}
|
|
|
|
if components.isEmpty {
|
|
return nil
|
|
}
|
|
|
|
let nameAndValue = components[0].split(separator: "=", maxSplits: 1).map {
|
|
$0.trimmingCharacters(in: .whitespaces)
|
|
}
|
|
|
|
guard nameAndValue.count == 2 else {
|
|
return nil
|
|
}
|
|
|
|
self.name = nameAndValue[0]
|
|
self.value = nameAndValue[1]
|
|
|
|
self.path = "/"
|
|
self.domain = defaultDomain
|
|
self.expires = nil
|
|
self.maxAge = nil
|
|
self.httpOnly = false
|
|
self.secure = false
|
|
|
|
for component in components[1...] {
|
|
if component.starts(with: "Path"), let value = parseComponentValue(component) {
|
|
self.path = value
|
|
continue
|
|
}
|
|
|
|
if component.starts(with: "Domain"), let value = parseComponentValue(component) {
|
|
self.domain = value
|
|
continue
|
|
}
|
|
|
|
if component.starts(with: "Expires") {
|
|
let formatter = DateFormatter()
|
|
formatter.locale = Locale(identifier: "en_US")
|
|
formatter.timeZone = TimeZone(identifier: "GMT")
|
|
formatter.dateFormat = "EEE, dd MMM yyyy HH:mm:ss z"
|
|
self.expires = self.parseComponentValue(component).flatMap { formatter.date(from: $0) }
|
|
continue
|
|
}
|
|
|
|
if component.starts(with: "Max-Age"), let value = parseComponentValue(component).flatMap(Int.init) {
|
|
self.maxAge = value
|
|
continue
|
|
}
|
|
|
|
if component == "Secure" {
|
|
self.secure = true
|
|
continue
|
|
}
|
|
|
|
if component == "HttpOnly" {
|
|
self.httpOnly = true
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
|
|
public init(name: String, value: String, path: String = "/", domain: String? = nil, expires: Date? = nil, maxAge: Int? = nil, httpOnly: Bool = false, secure: Bool = false) {
|
|
self.name = name
|
|
self.value = value
|
|
self.path = path
|
|
self.domain = domain
|
|
self.expires = expires
|
|
self.httpOnly = httpOnly
|
|
self.secure = secure
|
|
}
|
|
|
|
func parseComponentValue(_ component: String) -> String? {
|
|
let nameAndValue = component.split(separator: "=", maxSplits: 1).map {
|
|
$0.trimmingCharacters(in: .whitespaces)
|
|
}
|
|
if nameAndValue.count == 2 {
|
|
return nameAndValue[1]
|
|
}
|
|
return nil
|
|
}
|
|
}
|
|
}
|
|
|
|
public extension HTTPClient.Response {
|
|
internal var cookieHeaders: [HTTPHeaders.Element] {
|
|
return headers.filter { $0.name.lowercased() == "set-cookie" }
|
|
}
|
|
|
|
var cookies: [HTTPClient.Cookie] {
|
|
return self.cookieHeaders.compactMap { HTTPClient.Cookie(from: $0.value, defaultDomain: self.host) }
|
|
}
|
|
}
|