|
14 | 14 |
|
15 | 15 | // MARK: HTTPHeaders |
16 | 16 |
|
| 17 | +import HTTPTypes |
| 18 | + |
17 | 19 | public typealias HTTPHeaders = [String: String] |
18 | 20 | public typealias HTTPMultiValueHeaders = [String: [String]] |
19 | 21 |
|
@@ -72,178 +74,31 @@ extension String.UTF8View { |
72 | 74 | } |
73 | 75 | } |
74 | 76 |
|
75 | | -// MARK: HTTPMethod |
76 | | - |
77 | | -public struct HTTPMethod: RawRepresentable, Equatable { |
78 | | - public var rawValue: String |
79 | | - |
80 | | - public init?(rawValue: String) { |
81 | | - guard rawValue.isValidHTTPToken else { |
82 | | - return nil |
83 | | - } |
84 | | - self.rawValue = rawValue |
85 | | - } |
86 | | - |
87 | | - public static var GET: HTTPMethod { HTTPMethod(rawValue: "GET")! } |
88 | | - public static var POST: HTTPMethod { HTTPMethod(rawValue: "POST")! } |
89 | | - public static var PUT: HTTPMethod { HTTPMethod(rawValue: "PUT")! } |
90 | | - public static var PATCH: HTTPMethod { HTTPMethod(rawValue: "PATCH")! } |
91 | | - public static var DELETE: HTTPMethod { HTTPMethod(rawValue: "DELETE")! } |
92 | | - public static var OPTIONS: HTTPMethod { HTTPMethod(rawValue: "OPTIONS")! } |
93 | | - public static var HEAD: HTTPMethod { HTTPMethod(rawValue: "HEAD")! } |
94 | | - |
95 | | - public static func RAW(value: String) -> HTTPMethod? { HTTPMethod(rawValue: value) } |
96 | | -} |
97 | | - |
98 | | -extension HTTPMethod: Codable { |
99 | | - public init(from decoder: Decoder) throws { |
100 | | - let container = try decoder.singleValueContainer() |
101 | | - let rawMethod = try container.decode(String.self) |
102 | | - |
103 | | - guard let method = HTTPMethod(rawValue: rawMethod) else { |
104 | | - throw DecodingError.dataCorruptedError( |
105 | | - in: container, |
106 | | - debugDescription: #"Method "\#(rawMethod)" does not conform to allowed http method syntax defined in RFC 7230 Section 3.2.6"# |
107 | | - ) |
108 | | - } |
109 | | - |
110 | | - self = method |
111 | | - } |
112 | | - |
113 | | - public func encode(to encoder: Encoder) throws { |
| 77 | +extension HTTPResponse.Status: Codable { |
| 78 | + public func encode(to encoder: any Encoder) throws { |
114 | 79 | var container = encoder.singleValueContainer() |
115 | | - try container.encode(self.rawValue) |
116 | | - } |
117 | | -} |
118 | | - |
119 | | -// MARK: HTTPResponseStatus |
120 | | - |
121 | | -public struct HTTPResponseStatus { |
122 | | - public let code: UInt |
123 | | - public let reasonPhrase: String? |
124 | | - |
125 | | - public init(code: UInt, reasonPhrase: String? = nil) { |
126 | | - self.code = code |
127 | | - self.reasonPhrase = reasonPhrase |
| 80 | + try container.encode(self.code) |
128 | 81 | } |
129 | 82 |
|
130 | | - public static var `continue`: HTTPResponseStatus { HTTPResponseStatus(code: 100) } |
131 | | - public static var switchingProtocols: HTTPResponseStatus { HTTPResponseStatus(code: 101) } |
132 | | - public static var processing: HTTPResponseStatus { HTTPResponseStatus(code: 102) } |
133 | | - public static var earlyHints: HTTPResponseStatus { HTTPResponseStatus(code: 103) } |
134 | | - |
135 | | - public static var ok: HTTPResponseStatus { HTTPResponseStatus(code: 200) } |
136 | | - public static var created: HTTPResponseStatus { HTTPResponseStatus(code: 201) } |
137 | | - public static var accepted: HTTPResponseStatus { HTTPResponseStatus(code: 202) } |
138 | | - public static var nonAuthoritativeInformation: HTTPResponseStatus { HTTPResponseStatus(code: 203) } |
139 | | - public static var noContent: HTTPResponseStatus { HTTPResponseStatus(code: 204) } |
140 | | - public static var resetContent: HTTPResponseStatus { HTTPResponseStatus(code: 205) } |
141 | | - public static var partialContent: HTTPResponseStatus { HTTPResponseStatus(code: 206) } |
142 | | - public static var multiStatus: HTTPResponseStatus { HTTPResponseStatus(code: 207) } |
143 | | - public static var alreadyReported: HTTPResponseStatus { HTTPResponseStatus(code: 208) } |
144 | | - public static var imUsed: HTTPResponseStatus { HTTPResponseStatus(code: 226) } |
145 | | - |
146 | | - public static var multipleChoices: HTTPResponseStatus { HTTPResponseStatus(code: 300) } |
147 | | - public static var movedPermanently: HTTPResponseStatus { HTTPResponseStatus(code: 301) } |
148 | | - public static var found: HTTPResponseStatus { HTTPResponseStatus(code: 302) } |
149 | | - public static var seeOther: HTTPResponseStatus { HTTPResponseStatus(code: 303) } |
150 | | - public static var notModified: HTTPResponseStatus { HTTPResponseStatus(code: 304) } |
151 | | - public static var useProxy: HTTPResponseStatus { HTTPResponseStatus(code: 305) } |
152 | | - public static var temporaryRedirect: HTTPResponseStatus { HTTPResponseStatus(code: 307) } |
153 | | - public static var permanentRedirect: HTTPResponseStatus { HTTPResponseStatus(code: 308) } |
154 | | - |
155 | | - public static var badRequest: HTTPResponseStatus { HTTPResponseStatus(code: 400) } |
156 | | - public static var unauthorized: HTTPResponseStatus { HTTPResponseStatus(code: 401) } |
157 | | - public static var paymentRequired: HTTPResponseStatus { HTTPResponseStatus(code: 402) } |
158 | | - public static var forbidden: HTTPResponseStatus { HTTPResponseStatus(code: 403) } |
159 | | - public static var notFound: HTTPResponseStatus { HTTPResponseStatus(code: 404) } |
160 | | - public static var methodNotAllowed: HTTPResponseStatus { HTTPResponseStatus(code: 405) } |
161 | | - public static var notAcceptable: HTTPResponseStatus { HTTPResponseStatus(code: 406) } |
162 | | - public static var proxyAuthenticationRequired: HTTPResponseStatus { HTTPResponseStatus(code: 407) } |
163 | | - public static var requestTimeout: HTTPResponseStatus { HTTPResponseStatus(code: 408) } |
164 | | - public static var conflict: HTTPResponseStatus { HTTPResponseStatus(code: 409) } |
165 | | - public static var gone: HTTPResponseStatus { HTTPResponseStatus(code: 410) } |
166 | | - public static var lengthRequired: HTTPResponseStatus { HTTPResponseStatus(code: 411) } |
167 | | - public static var preconditionFailed: HTTPResponseStatus { HTTPResponseStatus(code: 412) } |
168 | | - public static var payloadTooLarge: HTTPResponseStatus { HTTPResponseStatus(code: 413) } |
169 | | - public static var uriTooLong: HTTPResponseStatus { HTTPResponseStatus(code: 414) } |
170 | | - public static var unsupportedMediaType: HTTPResponseStatus { HTTPResponseStatus(code: 415) } |
171 | | - public static var rangeNotSatisfiable: HTTPResponseStatus { HTTPResponseStatus(code: 416) } |
172 | | - public static var expectationFailed: HTTPResponseStatus { HTTPResponseStatus(code: 417) } |
173 | | - public static var imATeapot: HTTPResponseStatus { HTTPResponseStatus(code: 418) } |
174 | | - public static var misdirectedRequest: HTTPResponseStatus { HTTPResponseStatus(code: 421) } |
175 | | - public static var unprocessableEntity: HTTPResponseStatus { HTTPResponseStatus(code: 422) } |
176 | | - public static var locked: HTTPResponseStatus { HTTPResponseStatus(code: 423) } |
177 | | - public static var failedDependency: HTTPResponseStatus { HTTPResponseStatus(code: 424) } |
178 | | - public static var upgradeRequired: HTTPResponseStatus { HTTPResponseStatus(code: 426) } |
179 | | - public static var preconditionRequired: HTTPResponseStatus { HTTPResponseStatus(code: 428) } |
180 | | - public static var tooManyRequests: HTTPResponseStatus { HTTPResponseStatus(code: 429) } |
181 | | - public static var requestHeaderFieldsTooLarge: HTTPResponseStatus { HTTPResponseStatus(code: 431) } |
182 | | - public static var unavailableForLegalReasons: HTTPResponseStatus { HTTPResponseStatus(code: 451) } |
183 | | - |
184 | | - public static var internalServerError: HTTPResponseStatus { HTTPResponseStatus(code: 500) } |
185 | | - public static var notImplemented: HTTPResponseStatus { HTTPResponseStatus(code: 501) } |
186 | | - public static var badGateway: HTTPResponseStatus { HTTPResponseStatus(code: 502) } |
187 | | - public static var serviceUnavailable: HTTPResponseStatus { HTTPResponseStatus(code: 503) } |
188 | | - public static var gatewayTimeout: HTTPResponseStatus { HTTPResponseStatus(code: 504) } |
189 | | - public static var httpVersionNotSupported: HTTPResponseStatus { HTTPResponseStatus(code: 505) } |
190 | | - public static var variantAlsoNegotiates: HTTPResponseStatus { HTTPResponseStatus(code: 506) } |
191 | | - public static var insufficientStorage: HTTPResponseStatus { HTTPResponseStatus(code: 507) } |
192 | | - public static var loopDetected: HTTPResponseStatus { HTTPResponseStatus(code: 508) } |
193 | | - public static var notExtended: HTTPResponseStatus { HTTPResponseStatus(code: 510) } |
194 | | - public static var networkAuthenticationRequired: HTTPResponseStatus { HTTPResponseStatus(code: 511) } |
195 | | -} |
196 | | - |
197 | | -extension HTTPResponseStatus: Equatable { |
198 | | - public static func == (lhs: Self, rhs: Self) -> Bool { |
199 | | - lhs.code == rhs.code |
| 83 | + public init(from decoder: any Decoder) throws { |
| 84 | + let code = try decoder.singleValueContainer().decode(Int.self) |
| 85 | + self.init(code: code) |
200 | 86 | } |
201 | 87 | } |
202 | 88 |
|
203 | | -extension HTTPResponseStatus: Codable { |
204 | | - public init(from decoder: Decoder) throws { |
205 | | - let container = try decoder.singleValueContainer() |
206 | | - self.code = try container.decode(UInt.self) |
207 | | - self.reasonPhrase = nil |
208 | | - } |
209 | | - |
210 | | - public func encode(to encoder: Encoder) throws { |
| 89 | +extension HTTPRequest.Method: Codable { |
| 90 | + public func encode(to encoder: any Encoder) throws { |
211 | 91 | var container = encoder.singleValueContainer() |
212 | | - try container.encode(self.code) |
| 92 | + try container.encode(self.rawValue) |
213 | 93 | } |
214 | | -} |
215 | 94 |
|
216 | | -extension String { |
217 | | - internal var isValidHTTPToken: Bool { |
218 | | - self.utf8.allSatisfy { char -> Bool in |
219 | | - switch char { |
220 | | - case UInt8(ascii: "a") ... UInt8(ascii: "z"), |
221 | | - UInt8(ascii: "A") ... UInt8(ascii: "Z"), |
222 | | - UInt8(ascii: "0") ... UInt8(ascii: "9"), |
223 | | - UInt8(ascii: "!"), |
224 | | - UInt8(ascii: "#"), |
225 | | - UInt8(ascii: "$"), |
226 | | - UInt8(ascii: "%"), |
227 | | - UInt8(ascii: "&"), |
228 | | - UInt8(ascii: "'"), |
229 | | - UInt8(ascii: "*"), |
230 | | - UInt8(ascii: "+"), |
231 | | - UInt8(ascii: "-"), |
232 | | - UInt8(ascii: "."), |
233 | | - UInt8(ascii: "^"), |
234 | | - UInt8(ascii: "_"), |
235 | | - UInt8(ascii: "`"), |
236 | | - UInt8(ascii: "|"), |
237 | | - UInt8(ascii: "~"): |
238 | | - return true |
239 | | - default: |
240 | | - return false |
241 | | - } |
| 95 | + public init(from decoder: any Decoder) throws { |
| 96 | + let container = try decoder.singleValueContainer() |
| 97 | + let rawMethod = try container.decode(String.self) |
| 98 | + guard let method = HTTPRequest.Method(rawMethod) else { |
| 99 | + throw DecodingError.dataCorruptedError(in: container, debugDescription: "\"\(rawMethod)\" is not a valid method") |
242 | 100 | } |
| 101 | + |
| 102 | + self = method |
243 | 103 | } |
244 | 104 | } |
245 | | - |
246 | | -#if swift(>=5.6) |
247 | | -extension HTTPMethod: Sendable {} |
248 | | -extension HTTPResponseStatus: Sendable {} |
249 | | -#endif |
0 commit comments