1212//
1313//===----------------------------------------------------------------------===//
1414
15- import CoreFoundation
1615import Foundation
1716import HTTPTypes
1817
18+ #if canImport(CoreFoundation)
19+ import CoreFoundation
20+ #endif // canImport(CoreFoundation)
21+
1922extension HTTPRequest {
2023 /// The URL of the request synthesized from the scheme, authority, and path pseudo header
2124 /// fields.
@@ -80,6 +83,7 @@ extension URL {
8083 buffer. append ( contentsOf: authority)
8184 buffer. append ( contentsOf: path)
8285
86+ #if canImport(CoreFoundation)
8387 if let url = buffer. withUnsafeBytes ( { buffer in
8488 CFURLCreateAbsoluteURLWithBytes (
8589 kCFAllocatorDefault,
@@ -94,9 +98,14 @@ extension URL {
9498 } else {
9599 return nil
96100 }
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)
97105 }
98106
99107 fileprivate var httpRequestComponents : ( scheme: [ UInt8 ] , authority: [ UInt8 ] ? , path: [ UInt8 ] ) {
108+ #if canImport(CoreFoundation)
100109 // CFURL parser based on byte ranges does not unnecessarily percent-encode WHATWG URL
101110 let url = unsafeBitCast ( self . absoluteURL as NSURL , to: CFURL . self)
102111 let length = CFURLGetBytes ( url, nil , 0 )
@@ -133,11 +142,11 @@ extension URL {
133142 let requestPathRange = unionRange ( pathRange, queryRange)
134143 if pathRange. length == 0 {
135144 if requestPathRange. length == 0 {
136- path = Array ( " / " . utf8 )
145+ path = [ UInt8 ( ascii : " / " ) ]
137146 } else {
138147 let pathBuffer = bufferSlice ( requestPathRange)
139148 path = [ UInt8] ( unsafeUninitializedCapacity: pathBuffer. count + 1 ) { buffer, initializedCount in
140- buffer [ 0 ] = 0x2F
149+ buffer [ 0 ] = UInt8 ( ascii : " / " )
141150 UnsafeMutableRawBufferPointer ( UnsafeMutableBufferPointer ( rebasing: buffer [ 1 ... ] ) ) . copyMemory (
142151 from: UnsafeRawBufferPointer ( pathBuffer)
143152 )
@@ -149,5 +158,52 @@ extension URL {
149158 }
150159 return ( scheme, authority, path)
151160 }
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)
152208 }
153209}
0 commit comments