12
12
//
13
13
//===----------------------------------------------------------------------===//
14
14
15
- import CoreFoundation
16
15
import Foundation
17
16
import HTTPTypes
18
17
18
+ #if canImport(CoreFoundation)
19
+ import CoreFoundation
20
+ #endif // canImport(CoreFoundation)
21
+
19
22
extension HTTPRequest {
20
23
/// The URL of the request synthesized from the scheme, authority, and path pseudo header
21
24
/// fields.
@@ -80,6 +83,7 @@ extension URL {
80
83
buffer. append ( contentsOf: authority)
81
84
buffer. append ( contentsOf: path)
82
85
86
+ #if canImport(CoreFoundation)
83
87
if let url = buffer. withUnsafeBytes ( { buffer in
84
88
CFURLCreateAbsoluteURLWithBytes (
85
89
kCFAllocatorDefault,
@@ -94,9 +98,14 @@ extension URL {
94
98
} else {
95
99
return nil
96
100
}
101
+ #else // canImport(CoreFoundation)
102
+ // This initializer does not preserve WHATWG URLs
103
+ self . init ( string: String ( decoding: buffer, as: UTF8 . self) )
104
+ #endif // canImport(CoreFoundation)
97
105
}
98
106
99
107
fileprivate var httpRequestComponents : ( scheme: [ UInt8 ] , authority: [ UInt8 ] ? , path: [ UInt8 ] ) {
108
+ #if canImport(CoreFoundation)
100
109
// CFURL parser based on byte ranges does not unnecessarily percent-encode WHATWG URL
101
110
let url = unsafeBitCast ( self . absoluteURL as NSURL , to: CFURL . self)
102
111
let length = CFURLGetBytes ( url, nil , 0 )
@@ -133,11 +142,11 @@ extension URL {
133
142
let requestPathRange = unionRange ( pathRange, queryRange)
134
143
if pathRange. length == 0 {
135
144
if requestPathRange. length == 0 {
136
- path = Array ( " / " . utf8 )
145
+ path = [ UInt8 ( ascii : " / " ) ]
137
146
} else {
138
147
let pathBuffer = bufferSlice ( requestPathRange)
139
148
path = [ UInt8] ( unsafeUninitializedCapacity: pathBuffer. count + 1 ) { buffer, initializedCount in
140
- buffer [ 0 ] = 0x2F
149
+ buffer [ 0 ] = UInt8 ( ascii : " / " )
141
150
UnsafeMutableRawBufferPointer ( UnsafeMutableBufferPointer ( rebasing: buffer [ 1 ... ] ) ) . copyMemory (
142
151
from: UnsafeRawBufferPointer ( pathBuffer)
143
152
)
@@ -149,5 +158,52 @@ extension URL {
149
158
}
150
159
return ( scheme, authority, path)
151
160
}
161
+ #else // canImport(CoreFoundation)
162
+ guard let components = URLComponents ( url: self , resolvingAgainstBaseURL: true ) ,
163
+ let urlString = components. string
164
+ else {
165
+ fatalError ( " Invalid URL " )
166
+ }
167
+
168
+ guard let schemeRange = components. rangeOfScheme else {
169
+ fatalError ( " Schemeless URL is not supported " )
170
+ }
171
+ let scheme = Array ( urlString [ schemeRange] . utf8)
172
+
173
+ let authority : [ UInt8 ] ?
174
+ if let hostRange = components. rangeOfHost {
175
+ let authorityRange =
176
+ if let portRange = components. rangeOfPort {
177
+ hostRange. lowerBound..< portRange. upperBound
178
+ } else {
179
+ hostRange
180
+ }
181
+ authority = Array ( urlString [ authorityRange] . utf8)
182
+ } else {
183
+ authority = nil
184
+ }
185
+
186
+ let pathRange = components. rangeOfPath
187
+ let queryRange = components. rangeOfQuery
188
+ let requestPathRange : Range < String . Index > ?
189
+ if let lowerBound = pathRange? . lowerBound ?? queryRange? . lowerBound,
190
+ let upperBound = queryRange? . upperBound ?? pathRange? . upperBound
191
+ {
192
+ requestPathRange = lowerBound..< upperBound
193
+ } else {
194
+ requestPathRange = nil
195
+ }
196
+ let path : [ UInt8 ]
197
+ if let pathRange, !pathRange. isEmpty, let requestPathRange {
198
+ path = Array ( urlString [ requestPathRange] . utf8)
199
+ } else {
200
+ if let requestPathRange, !requestPathRange. isEmpty {
201
+ path = [ UInt8 ( ascii: " / " ) ] + Array( urlString [ requestPathRange] . utf8)
202
+ } else {
203
+ path = [ UInt8 ( ascii: " / " ) ]
204
+ }
205
+ }
206
+ return ( scheme, authority, path)
207
+ #endif // canImport(CoreFoundation)
152
208
}
153
209
}
0 commit comments