Skip to content

Commit a4f1aff

Browse files
committed
Fix how redirect requests are constructed
https://bugs.swift.org/browse/SR-13027
1 parent 60fb698 commit a4f1aff

File tree

1 file changed

+23
-19
lines changed

1 file changed

+23
-19
lines changed

Sources/FoundationNetworking/URLSession/HTTP/HTTPURLProtocol.swift

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -689,28 +689,32 @@ internal extension _HTTPURLProtocol {
689689
return request
690690
}
691691

692-
let scheme = request.url?.scheme
693-
let host = request.url?.host
694-
let port = request.url?.port
695-
696-
var components = URLComponents()
697-
components.scheme = scheme
698-
components.host = host
699-
// Use the original port if the new URL does not contain a host
700-
// ie Location: /foo => <original host>:<original port>/Foo
701-
// but Location: newhost/foo will ignore the original port
702-
if targetURL.host == nil {
703-
components.port = port
704-
}
705-
//The path must either begin with "/" or be an empty string.
706-
if targetURL.relativeString.first != "/" {
707-
components.path = "/" + targetURL.relativeString
692+
guard
693+
let fromUrl = fromRequest.url,
694+
var components = URLComponents(url: fromUrl, resolvingAgainstBaseURL: false)
695+
else { return nil }
696+
697+
// If the new URL contains a host, use the host and port from the new URL.
698+
// Otherwise, the host and port from the original URL are used.
699+
if targetURL.host != nil {
700+
components.host = targetURL.host
701+
components.port = targetURL.port
702+
}
703+
704+
// The path must either begin with "/" or be an empty string.
705+
if targetURL.path.hasPrefix("/") {
706+
components.path = targetURL.path
708707
} else {
709-
components.path = targetURL.relativeString
708+
components.path = "/" + targetURL.path
710709
}
710+
711+
// The query and fragment components are set separately to prevent them from being
712+
// percent encoded again.
713+
components.percentEncodedQuery = targetURL.query
714+
components.percentEncodedFragment = targetURL.fragment
711715

712-
guard let urlString = components.string else { fatalError("Invalid URL") }
713-
request.url = URL(string: urlString)
716+
guard let url = components.url else { fatalError("Invalid URL") }
717+
request.url = url
714718

715719
// Inherit the timeout from the previous request
716720
request.timeoutInterval = fromRequest.timeoutInterval

0 commit comments

Comments
 (0)