Skip to content

preserve trailing slash in uri path #107

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Sep 20, 2019
36 changes: 32 additions & 4 deletions Sources/AsyncHTTPClient/HTTPHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -385,14 +385,42 @@ extension HTTPClientResponseDelegate {
public func didReceiveError(task: HTTPClient.Task<Response>, _: Error) {}
}

internal extension URL {
extension URL {
var percentEncodedPath: String {
if self.path.isEmpty {
return "/"
}
return self.path.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? self.path
}

var pathHasTrailingSlash: Bool {
let url = self.absoluteString

var pathEndIndex = url.index(before: url.endIndex)
if let queryIndex = url.firstIndex(of: "?") {
pathEndIndex = url.index(before: queryIndex)
} else if let fragmentIndex = url.firstIndex(of: "#") {
pathEndIndex = url.index(before: fragmentIndex)
}

return url[pathEndIndex] == "/"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Writing this against the absolute string seems to be making life quite hard: why not write it against self.path?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

self.path removes trailing slash

}

var uri: String {
let urlEncodedPath = path.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? path
return path.isEmpty ? "/" : urlEncodedPath + (query.map { "?" + $0 } ?? "")
var uri = self.percentEncodedPath
if self.pathHasTrailingSlash, uri != "/" {
uri += "/"
}

if let query = self.query {
uri += "?" + query
}

return uri
}

func hasTheSameOrigin(as other: URL) -> Bool {
return host == other.host && scheme == other.scheme && port == other.port
return self.host == other.host && self.scheme == other.scheme && self.port == other.port
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ extension HTTPClientInternalTests {
("testProxyStreaming", testProxyStreaming),
("testProxyStreamingFailure", testProxyStreamingFailure),
("testUploadStreamingBackpressure", testUploadStreamingBackpressure),
("testRequestURITrailingSlash", testRequestURITrailingSlash),
]
}
}
35 changes: 35 additions & 0 deletions Tests/AsyncHTTPClientTests/HTTPClientInternalTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -193,4 +193,39 @@ class HTTPClientInternalTests: XCTestCase {

XCTAssertEqual(delegate.reads, 3)
}

func testRequestURITrailingSlash() throws {
let request1 = try Request(url: "https://someserver.com:8888/some/path?foo=bar#ref")
XCTAssertEqual(request1.url.uri, "/some/path?foo=bar")

let request2 = try Request(url: "https://someserver.com:8888/some/path/?foo=bar#ref")
XCTAssertEqual(request2.url.uri, "/some/path/?foo=bar")

let request3 = try Request(url: "https://someserver.com:8888?foo=bar#ref")
XCTAssertEqual(request3.url.uri, "/?foo=bar")

let request4 = try Request(url: "https://someserver.com:8888/?foo=bar#ref")
XCTAssertEqual(request4.url.uri, "/?foo=bar")

let request5 = try Request(url: "https://someserver.com:8888/some/path")
XCTAssertEqual(request5.url.uri, "/some/path")

let request6 = try Request(url: "https://someserver.com:8888/some/path/")
XCTAssertEqual(request6.url.uri, "/some/path/")

let request7 = try Request(url: "https://someserver.com:8888")
XCTAssertEqual(request7.url.uri, "/")

let request8 = try Request(url: "https://someserver.com:8888/")
XCTAssertEqual(request8.url.uri, "/")

let request9 = try Request(url: "https://someserver.com:8888#ref")
XCTAssertEqual(request9.url.uri, "/")

let request10 = try Request(url: "https://someserver.com:8888/#ref")
XCTAssertEqual(request10.url.uri, "/")

let request11 = try Request(url: "https://someserver.com/some%20path")
XCTAssertEqual(request11.url.uri, "/some%20path")
}
}