-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathHTTPRequest.swift
More file actions
130 lines (109 loc) · 3.51 KB
/
HTTPRequest.swift
File metadata and controls
130 lines (109 loc) · 3.51 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
//
// HTTPRequest.swift
// SimpleHTTP
//
// Created by Edvinas Byla on 14/05/2025.
//
import Foundation
/// Represents an HTTP request.
public struct HTTPRequest: Sendable {
/// A unique identifier for this request.
public let id = UUID()
/// The HTTP method (GET, POST, etc.).
public let method: Method
/// Custom headers to include.
public var headers: [String: String]
/// The body to send.
public var body: HTTPBody
private var options = [ObjectIdentifier: AnyHTTPRequestOption]()
private var urlComponents = URLComponents()
/// Creates a request.
///
/// - Parameters:
/// - method: The HTTP method.
/// - scheme: URL scheme (e.g. "https").
/// - host: The host (e.g. "api.example.com").
/// - port: The port of the server, if any (e.g. `8080`).
/// - path: The URL path (e.g. "/v1/resource").
/// - headers: Initial headers.
/// - body: The request body.
public init(
method: Method,
scheme: String = "https",
host: String? = nil,
port: Int? = nil,
path: String,
headers: [String: String] = [:],
body: HTTPBody = EmptyBody()
) {
self.method = method
self.headers = headers
self.body = body
urlComponents.scheme = scheme
urlComponents.host = host
urlComponents.port = port
urlComponents.path = path
}
/// Common HTTP methods.
public struct Method: Sendable {
public static let get = Self(rawValue: "GET")
public static let post = Self(rawValue: "POST")
public static let put = Self(rawValue: "PUT")
public static let delete = Self(rawValue: "DELETE")
/// The raw string value (e.g. `"GET"`).
public let rawValue: String
}
/// Per-request option access by type.
///
/// Allows to pass custom options that can later be access from `HTTPHandler`.
public subscript<Option: HTTPRequestOption>(option type: Option.Type) -> Option.Value {
get {
let id = ObjectIdentifier(type)
guard let value = options[id]?.value as? Option.Value else {
return type.defaultOptionValue
}
return value
}
set {
let id = ObjectIdentifier(type)
options[id] = AnyHTTPRequestOption(value: newValue)
}
}
}
extension HTTPRequest {
/// The fully composed URL, if valid.
public var url: URL? {
urlComponents.url
}
/// The host component of the URL.
public var host: String? {
get { urlComponents.host }
set { urlComponents.host = newValue }
}
/// The URL scheme for this request.
public var scheme: String? {
get { urlComponents.scheme }
set { urlComponents.scheme = newValue }
}
/// The port component of the URL.
public var port: Int? {
get { urlComponents.port }
set { urlComponents.port = newValue }
}
/// The path component of the URL.
public var path: String {
get { urlComponents.path }
set { urlComponents.path = newValue }
}
/// The query items component of the URL.
public var queryItems: [URLQueryItem] {
get { urlComponents.queryItems ?? [] }
set { urlComponents.queryItems = newValue }
}
}
fileprivate struct AnyHTTPRequestOption: @unchecked Sendable {
let value: Any
init<Value: Sendable>(value: Value) {
self.value = value
}
}