Skip to content

Commit

Permalink
make errors response representable
Browse files Browse the repository at this point in the history
  • Loading branch information
paulofaria committed May 16, 2017
1 parent 41448e8 commit 2b9cdb6
Show file tree
Hide file tree
Showing 13 changed files with 174 additions and 129 deletions.
1 change: 1 addition & 0 deletions Sources/Core/Content/Content.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ public enum ContentError : Error {
}

extension ContentError : CustomStringConvertible {
/// :nodoc:
public var description: String {
switch self {
case let .noContent(type):
Expand Down
20 changes: 20 additions & 0 deletions Sources/Core/MediaType/MediaType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,26 @@ public struct MediaType {
parameters: parameters
)
}

public static func parse(acceptHeader: String) -> [MediaType] {
var acceptedMediaTypes: [MediaType] = []

let acceptedTypesString = acceptHeader.components(separatedBy: ",")

for acceptedTypeString in acceptedTypesString {
let acceptedTypeTokens = acceptedTypeString.components(separatedBy: ";")

if acceptedTypeTokens.count >= 1 {
let mediaTypeString = acceptedTypeTokens[0].trimmingCharacters(in: .whitespacesAndNewlines)

if let acceptedMediaType = try? MediaType(string: mediaTypeString) {
acceptedMediaTypes.append(acceptedMediaType)
}
}
}

return acceptedMediaTypes
}

public func matches(other mediaType: MediaType) -> Bool {
if type == "*" || mediaType.type == "*" {
Expand Down
21 changes: 15 additions & 6 deletions Sources/Core/Parameters/Parameters.swift
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
import struct Foundation.UUID

public enum ParametersError : Error {
case parameterNotFound(parameterKey: String)
case cannotInitializeParameter(type: LosslessStringConvertible.Type, from: String)
case cannotInitializeParameters(type: ParametersInitializable.Type, from: URI.Parameters)
case valueNotFound(key: String, parameters: URI.Parameters)
case cannotInitialize(type: LosslessStringConvertible.Type, parameter: String)
}

// TODO: Make ParametersError CustomStringConvertible
extension ParametersError : CustomStringConvertible {
/// :nodoc:
public var description: String {
switch self {
case let .valueNotFound(key, parameters):
return "Cannot get parameter for key \"\(key)\". Key is not present in parameters \(parameters)."
case let .cannotInitialize(type, parameter):
return "Cannot initialize type \"\(String(describing: type))\" with parameter \"\(parameter)\"."
}
}
}

public protocol ParametersInitializable {
init(parameters: URI.Parameters) throws
Expand All @@ -19,11 +28,11 @@ extension URI.Parameters {

public func get<P : LosslessStringConvertible>(_ parameterKey: String) throws -> P {
guard let string = parameters[parameterKey] else {
throw ParametersError.parameterNotFound(parameterKey: parameterKey)
throw ParametersError.valueNotFound(key: parameterKey, parameters: self)
}

guard let parameter = P(string) else {
throw ParametersError.cannotInitializeParameter(type: P.self, from: string)
throw ParametersError.cannotInitialize(type: P.self, parameter: string)
}

return parameter
Expand Down
31 changes: 25 additions & 6 deletions Sources/Core/URI/URI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,8 @@ public struct URI {
}
}

extension URI.UserInfo : CustomStringConvertible {
public var description: String {
return username + ":" + password
}
}

extension URI : CustomStringConvertible {
/// :nodoc:
public var description: String {
var string = ""

Expand Down Expand Up @@ -113,3 +108,27 @@ extension URI : CustomStringConvertible {
return string
}
}

extension URI.UserInfo : CustomStringConvertible {
/// :nodoc:
public var description: String {
return username + ":" + password
}
}

extension URI.Parameters : CustomStringConvertible {
/// :nodoc:
public var description: String {
var string = "{"

for (offset: index, element: (key: key, value: value)) in parameters.enumerated() {
string += key + ": " + value

if index < parameters.count - 1 {
string += ", "
}
}

return string + "}"
}
}
19 changes: 9 additions & 10 deletions Sources/HTTP/Message/Version.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,25 @@ public struct Version {
self.major = major
self.minor = minor
}

internal static let oneDotZero = Version(major: 1, minor: 0)
internal static let oneDotOne = Version(major: 1, minor: 1)
}

extension Version : Hashable {
/// :nodoc:
public var hashValue: Int {
return major ^ minor
}
}

extension Version : Equatable {}

public func == (lhs: Version, rhs: Version) -> Bool {
return lhs.hashValue == rhs.hashValue
}

extension Version {
public static let oneDotZero = Version(major: 1, minor: 0)
public static let oneDotOne = Version(major: 1, minor: 1)
/// :nodoc:
public static func == (lhs: Version, rhs: Version) -> Bool {
return lhs.hashValue == rhs.hashValue
}
}

extension Version : CustomStringConvertible {
/// :nodoc:
public var description: String {
return "HTTP/" + major.description + "." + minor.description
}
Expand Down
49 changes: 25 additions & 24 deletions Sources/HTTP/Request/Cookie.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,39 +10,40 @@ public struct Cookie {
}
}

extension Cookie {
public static func parse(cookieHeader: String) -> Set<Cookie> {
var cookies: Set<Cookie> = []
let tokens = cookieHeader.components(separatedBy: ";")

for token in tokens {
let cookieTokens = token.components(separatedBy: "=")

guard cookieTokens.count == 2 else {
return []
}

cookies.insert(Cookie(name: cookieTokens[0].trimmingCharacters(in: .whitespacesAndNewlines), value: cookieTokens[1].trimmingCharacters(in: .whitespacesAndNewlines)))
}

return cookies
}
}

extension Cookie : Hashable {
/// :nodoc:
public var hashValue: Int {
return name.hashValue
}
}

extension Cookie : Equatable {}

public func == (lhs: Cookie, rhs: Cookie) -> Bool {
return lhs.hashValue == rhs.hashValue
/// :nodoc:
public static func == (lhs: Cookie, rhs: Cookie) -> Bool {
return lhs.hashValue == rhs.hashValue
}
}

extension Cookie : CustomStringConvertible {
/// :nodoc:
public var description: String {
return "\(name)=\(value)"
}
}

extension Set where Element == Cookie {
public init?(cookieHeader: String) {
var cookies = Set<Element>()
let tokens = cookieHeader.components(separatedBy: ";")

for token in tokens {
let cookieTokens = token.components(separatedBy: "=")

guard cookieTokens.count == 2 else {
return nil
}

cookies.insert(Cookie(name: cookieTokens[0].trimmingCharacters(in: .whitespacesAndNewlines), value: cookieTokens[1].trimmingCharacters(in: .whitespacesAndNewlines)))
}

self = cookies
}
}
45 changes: 24 additions & 21 deletions Sources/HTTP/Request/Method.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ public enum Method {
}

extension Method {
init(_ rawValue: String) {
let method = rawValue.uppercased()
init(_ method: String) {
let method = method.uppercased()
switch method {
case "DELETE": self = .delete
case "GET": self = .get
Expand All @@ -29,24 +29,8 @@ extension Method {
}
}

extension Method : CustomStringConvertible {
public var description: String {
switch self {
case .delete: return "DELETE"
case .get: return "GET"
case .head: return "HEAD"
case .post: return "POST"
case .put: return "PUT"
case .connect: return "CONNECT"
case .options: return "OPTIONS"
case .trace: return "TRACE"
case .patch: return "PATCH"
case .other(let method): return method.uppercased()
}
}
}

extension Method : Hashable {
/// :nodoc:
public var hashValue: Int {
switch self {
case .delete: return 0
Expand All @@ -61,8 +45,27 @@ extension Method : Hashable {
case .other(let method): return 9 + method.hashValue
}
}

/// :nodoc:
public static func == (lhs: Method, rhs: Method) -> Bool {
return lhs.description == rhs.description
}
}

public func ==(lhs: Method, rhs: Method) -> Bool {
return lhs.description == rhs.description
extension Method : CustomStringConvertible {
/// :nodoc:
public var description: String {
switch self {
case .delete: return "DELETE"
case .get: return "GET"
case .head: return "HEAD"
case .post: return "POST"
case .put: return "PUT"
case .connect: return "CONNECT"
case .options: return "OPTIONS"
case .trace: return "TRACE"
case .patch: return "PATCH"
case .other(let method): return method.uppercased()
}
}
}
26 changes: 5 additions & 21 deletions Sources/HTTP/Request/Request.swift
Original file line number Diff line number Diff line change
Expand Up @@ -148,35 +148,17 @@ extension Request {
extension Request {
public var accept: [MediaType] {
get {
var acceptedMediaTypes: [MediaType] = []

if let acceptString = headers["Accept"] {
let acceptedTypesString = acceptString.components(separatedBy: ",")

for acceptedTypeString in acceptedTypesString {
let acceptedTypeTokens = acceptedTypeString.components(separatedBy: ";")

if acceptedTypeTokens.count >= 1 {
let mediaTypeString = acceptedTypeTokens[0].trimmingCharacters(in: .whitespacesAndNewlines)

if let acceptedMediaType = try? MediaType(string: mediaTypeString) {
acceptedMediaTypes.append(acceptedMediaType)
}
}
}
}

return acceptedMediaTypes
return headers["Accept"].map({ MediaType.parse(acceptHeader: $0) }) ?? []
}

set(accept) {
headers["Accept"] = accept.map({$0.type + "/" + $0.subtype}).joined(separator: ", ")
headers["Accept"] = accept.map({ $0.type + "/" + $0.subtype }).joined(separator: ", ")
}
}

public var cookies: Set<Cookie> {
get {
return headers["Cookie"].flatMap({Set<Cookie>(cookieHeader: $0)}) ?? []
return headers["Cookie"].map({ Cookie.parse(cookieHeader: $0) }) ?? []
}
}

Expand All @@ -200,10 +182,12 @@ extension Request {
}

extension Request : CustomStringConvertible {
/// :nodoc:
public var requestLineDescription: String {
return method.description + " " + uri.description + " " + version.description + "\n"
}

/// :nodoc:
public var description: String {
return requestLineDescription + headers.description
}
Expand Down
33 changes: 22 additions & 11 deletions Sources/HTTP/Response/AttributedCookie.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,15 @@ public struct AttributedCookie {
public var secure: Bool
public var httpOnly: Bool

public init(name: String, value: String, expiration: Expiration? = nil, domain: String? = nil, path: String? = nil, secure: Bool = false, httpOnly: Bool = false) {
public init(
name: String,
value: String,
expiration: Expiration? = nil,
domain: String? = nil,
path: String? = nil,
secure: Bool = false,
httpOnly: Bool = false
) {
self.name = name
self.value = value
self.expiration = expiration
Expand Down Expand Up @@ -80,16 +88,19 @@ public struct AttributedCookie {
}

extension AttributedCookie : Hashable {
/// :nodoc:
public var hashValue: Int {
return name.hashValue
}
}

public func == (lhs: AttributedCookie, rhs: AttributedCookie) -> Bool {
return lhs.hashValue == rhs.hashValue
/// :nodoc:
public static func == (lhs: AttributedCookie, rhs: AttributedCookie) -> Bool {
return lhs.hashValue == rhs.hashValue
}
}

extension AttributedCookie : CustomStringConvertible {
/// :nodoc:
public var description: String {
var string = "\(name)=\(value)"

Expand Down Expand Up @@ -122,12 +133,12 @@ extension AttributedCookie : CustomStringConvertible {
}
}

extension AttributedCookie.Expiration : Equatable {}

public func == (lhs: AttributedCookie.Expiration, rhs: AttributedCookie.Expiration) -> Bool {
switch (lhs, rhs) {
case let (.maxAge(l), .maxAge(r)): return l == r
case let (.expires(l), .expires(r)): return l == r
default: return false
extension AttributedCookie.Expiration : Equatable {
public static func == (lhs: AttributedCookie.Expiration, rhs: AttributedCookie.Expiration) -> Bool {
switch (lhs, rhs) {
case let (.maxAge(l), .maxAge(r)): return l == r
case let (.expires(l), .expires(r)): return l == r
default: return false
}
}
}

0 comments on commit 2b9cdb6

Please sign in to comment.