From ec9a19a5a62fc0b175f2617f71035b7ad69fc0af Mon Sep 17 00:00:00 2001 From: Ken Carroll Date: Fri, 31 Mar 2023 09:13:12 +0100 Subject: [PATCH 1/3] Support range-requests beyond EOF. Return up to EOF. --- Sources/Vapor/HTTP/Headers/HTTPHeaders+ContentRange.swift | 5 +++-- Sources/Vapor/Utilities/FileIO.swift | 6 ++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Sources/Vapor/HTTP/Headers/HTTPHeaders+ContentRange.swift b/Sources/Vapor/HTTP/Headers/HTTPHeaders+ContentRange.swift index 9672929465..d2694f23bd 100644 --- a/Sources/Vapor/HTTP/Headers/HTTPHeaders+ContentRange.swift +++ b/Sources/Vapor/HTTP/Headers/HTTPHeaders+ContentRange.swift @@ -262,11 +262,12 @@ extension HTTPHeaders.Range.Value { } return .withinWithLimit(start: (limit - end), end: limit - 1, limit: limit) case .within(let start, let end): - guard start >= 0, end >= 0, start < end, start <= limit, end <= limit else { + guard start >= 0, end >= 0, start < end, start <= limit else { throw Abort(.badRequest) } - return .withinWithLimit(start: start, end: end, limit: limit) + let myEnd = min(end, limit) + return .withinWithLimit(start: start, end: myEnd, limit: limit) } } } diff --git a/Sources/Vapor/Utilities/FileIO.swift b/Sources/Vapor/Utilities/FileIO.swift index 1be3312232..2b46388d3c 100644 --- a/Sources/Vapor/Utilities/FileIO.swift +++ b/Sources/Vapor/Utilities/FileIO.swift @@ -265,6 +265,7 @@ public struct FileIO { extension HTTPHeaders.Range.Value { fileprivate func asByteBufferBounds(withMaxSize size: Int, logger: Logger) throws -> (offset: Int64, byteCount: Int) { + switch self { case .start(let value): guard value <= size, value >= 0 else { @@ -279,7 +280,7 @@ extension HTTPHeaders.Range.Value { } return (offset: numericCast(size - value), byteCount: value) case .within(let start, let end): - guard start >= 0, end >= 0, start < end, start <= size, end <= size else { + guard start >= 0, end >= 0, start < end, start <= size else { logger.debug("Requested range was invalid: \(start)-\(end)") throw Abort(.badRequest) } @@ -288,7 +289,8 @@ extension HTTPHeaders.Range.Value { logger.debug("Requested range was invalid: \(start)-\(end)") throw Abort(.badRequest) } - return (offset: numericCast(start), byteCount: byteCount) + let myByteCount = end <= size ? byteCount : byteCount - (end - size) + return (offset: numericCast(start), byteCount: myByteCount) } } } From 9ca9dbe42e2a41efa7b2554e6620049f87efcfdb Mon Sep 17 00:00:00 2001 From: Ken Carroll Date: Fri, 25 Aug 2023 11:49:10 +0100 Subject: [PATCH 2/3] Clarify code, variable names. --- Sources/Vapor/HTTP/Headers/HTTPHeaders+ContentRange.swift | 4 ++-- Sources/Vapor/Utilities/FileIO.swift | 8 ++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Sources/Vapor/HTTP/Headers/HTTPHeaders+ContentRange.swift b/Sources/Vapor/HTTP/Headers/HTTPHeaders+ContentRange.swift index d2694f23bd..a935843877 100644 --- a/Sources/Vapor/HTTP/Headers/HTTPHeaders+ContentRange.swift +++ b/Sources/Vapor/HTTP/Headers/HTTPHeaders+ContentRange.swift @@ -266,8 +266,8 @@ extension HTTPHeaders.Range.Value { throw Abort(.badRequest) } - let myEnd = min(end, limit) - return .withinWithLimit(start: start, end: myEnd, limit: limit) + let endToRequest = min(end, limit) + return .withinWithLimit(start: start, end: endToRequest, limit: limit) } } } diff --git a/Sources/Vapor/Utilities/FileIO.swift b/Sources/Vapor/Utilities/FileIO.swift index 2b46388d3c..74807e777c 100644 --- a/Sources/Vapor/Utilities/FileIO.swift +++ b/Sources/Vapor/Utilities/FileIO.swift @@ -289,8 +289,12 @@ extension HTTPHeaders.Range.Value { logger.debug("Requested range was invalid: \(start)-\(end)") throw Abort(.badRequest) } - let myByteCount = end <= size ? byteCount : byteCount - (end - size) - return (offset: numericCast(start), byteCount: myByteCount) + var byteCountToReqeust = byteCount + // Request past EOF, return up to EOF bytes + if (end > size) { + byteCountToReqeust = byteCount - (end - size) + } + return (offset: numericCast(start), byteCount: byteCountToReqeust) } } } From 215f6885f6e54e009b46e7ab10fad15c43ea1ae8 Mon Sep 17 00:00:00 2001 From: Ken Carroll Date: Fri, 25 Aug 2023 13:10:07 +0100 Subject: [PATCH 3/3] Test for range limit. --- Tests/VaporTests/HTTPHeaderTests.swift | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Tests/VaporTests/HTTPHeaderTests.swift b/Tests/VaporTests/HTTPHeaderTests.swift index fe4e983ead..5a9289e6bd 100644 --- a/Tests/VaporTests/HTTPHeaderTests.swift +++ b/Tests/VaporTests/HTTPHeaderTests.swift @@ -358,6 +358,16 @@ final class HTTPHeaderTests: XCTestCase { ) } + func testRangeLimit() throws { + let contentRanges = HTTPHeaders.Range(unit: .bytes, ranges: [ + .within(start: 200, end: 1000) + ]) + + let firstRange = contentRanges.ranges.first + let accept = try firstRange!.asResponseContentRange(limit: 600) + XCTAssertEqual(accept.serialize(), "200-600/600") + } + func testLinkHeaderParsing() throws { let headers = HTTPHeaders([ ("link", #"; rel="next", ; rel="last"; custom1="whatever", ; rel=related, ; rel=related"#)