Skip to content

Commit cb2298b

Browse files
SolaWing王孝华
authored andcommitted
fix: only escaping invalid data, keep valid escaping untouched
1 parent 718f82c commit cb2298b

File tree

2 files changed

+26
-2
lines changed

2 files changed

+26
-2
lines changed

Xcode/Sources/HttpParser.swift

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public class HttpParser {
2424
}
2525
let request = HttpRequest()
2626
request.method = statusLineTokens[0]
27-
let encodedPath = statusLineTokens[1].addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? statusLineTokens[1]
27+
let encodedPath = Self.escapingInvalidURL(statusLineTokens[1])
2828
let urlComponents = URLComponents(string: encodedPath)
2929
request.path = urlComponents?.path ?? ""
3030
request.queryParams = urlComponents?.queryItems?.map { ($0.name, $0.value ?? "") } ?? []
@@ -38,7 +38,17 @@ public class HttpParser {
3838
request.body = try readBody(socket, size: contentLengthValue)
3939
}
4040
return request
41+
}
42+
43+
/// only escaping invalid chars,valid encodedPath keep untouched
44+
static func escapingInvalidURL(_ url: String) -> String {
45+
var urlAllowed: CharacterSet {
46+
var v = CharacterSet.urlQueryAllowed
47+
v.insert(charactersIn: "?#%")
48+
return v
4149
}
50+
return url.addingPercentEncoding(withAllowedCharacters: urlAllowed) ?? url
51+
}
4252

4353
private func readBody(_ socket: Socket, size: Int) throws -> [UInt8] {
4454
return try socket.read(length: size)

Xcode/Tests/SwifterTestsHttpParser.swift

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ class SwifterTestsHttpParser: XCTestCase {
175175
XCTAssertEqual(resp?.headers["header2"], "2", "Parser should extract multiple headers from the request.")
176176

177177
resp = try? parser.readHttpRequest(TestSocket("GET /some/path?subscript_query[]=1&subscript_query[]=2 HTTP/1.0\nContent-Length: 10\n\n1234567890"))
178-
let queryPairs = resp?.queryParams ?? []
178+
var queryPairs = resp?.queryParams ?? []
179179
XCTAssertEqual(queryPairs.count, 2)
180180
XCTAssertEqual(queryPairs.first?.0, "subscript_query[]")
181181
XCTAssertEqual(queryPairs.first?.1, "1")
@@ -185,5 +185,19 @@ class SwifterTestsHttpParser: XCTestCase {
185185
XCTAssertEqual(resp?.path, "/some/path", "Parser should extract HTTP path value from the status line.")
186186
XCTAssertEqual(resp?.headers["content-length"], "10", "Parser should extract Content-Length header value.")
187187

188+
resp = try? parser.readHttpRequest(TestSocket("GET /path[]/param?a[]=1&a[]=2&b=%20 HTTP/1.0\r\nContent-Length: 0\r\n\r\n"))
189+
queryPairs = resp?.queryParams ?? []
190+
191+
XCTAssertEqual(resp?.path, "/path[]/param")
192+
if queryPairs.count == 3 {
193+
XCTAssertEqual(queryPairs[0].0, "a[]")
194+
XCTAssertEqual(queryPairs[0].1, "1")
195+
XCTAssertEqual(queryPairs[1].0, "a[]")
196+
XCTAssertEqual(queryPairs[1].1, "2")
197+
XCTAssertEqual(queryPairs[2].0, "b")
198+
XCTAssertEqual(queryPairs[2].1, " ") // % escaping should keep untouch
199+
} else {
200+
XCTFail("queryPairs count should be 3")
201+
}
188202
}
189203
}

0 commit comments

Comments
 (0)