File tree Expand file tree Collapse file tree 4 files changed +40
-7
lines changed Expand file tree Collapse file tree 4 files changed +40
-7
lines changed Original file line number Diff line number Diff line change @@ -60,8 +60,15 @@ struct HTTPConnection: Sendable {
6060 switch response. payload {
6161 case . httpBody( let sequence) :
6262 try await socket. write ( header)
63+ var sent = 0
6364 for try await chunk in sequence {
64- try await socket. write ( chunk)
65+ do {
66+ try await socket. write ( chunk)
67+ sent += chunk. count
68+ } catch {
69+ let total = sequence. count. map ( String . init) ?? " unknown "
70+ throw Error ( " \( error. localizedDescription) , sent: \( sent) / \( total) . " )
71+ }
6572 }
6673 case . webSocket( let handler) :
6774 try await switchToWebSocket ( with: handler, response: header)
@@ -82,6 +89,14 @@ struct HTTPConnection: Sendable {
8289 func close( ) throws {
8390 try socket. close ( )
8491 }
92+
93+ struct Error : LocalizedError {
94+ var errorDescription : String ?
95+
96+ init ( _ description: String ) {
97+ self . errorDescription = description
98+ }
99+ }
85100}
86101
87102extension HTTPConnection : Hashable {
Original file line number Diff line number Diff line change @@ -352,7 +352,8 @@ extension Logging {
352352 }
353353
354354 func logRequest( _ request: HTTPRequest , on connection: HTTPConnection ) {
355- logInfo ( " \( connection. identifer) request: \( request. method. rawValue) \( request. path) " )
355+ let suffix = request. headers [ . range] != nil ? " <ranged> " : " "
356+ logInfo ( " \( connection. identifer) request: \( request. method. rawValue) \( request. path) \( suffix) " )
356357 }
357358
358359 func logError( _ error: any Error , on connection: HTTPConnection ) {
Original file line number Diff line number Diff line change @@ -105,7 +105,7 @@ public struct FileHTTPHandler: HTTPHandler {
105105 )
106106 }
107107
108- if let range = Self . makePartialRange ( for: request. headers) {
108+ if let range = Self . makePartialRange ( for: request. headers, fileSize : fileSize ) {
109109 headers [ . contentRange] = " bytes \( range. lowerBound) - \( range. upperBound) / \( fileSize) "
110110 return try HTTPResponse (
111111 statusCode: . partialContent,
@@ -124,17 +124,19 @@ public struct FileHTTPHandler: HTTPHandler {
124124 }
125125 }
126126
127- static func makePartialRange( for headers: [ HTTPHeader : String ] ) -> ClosedRange < Int > ? {
127+ static func makePartialRange( for headers: [ HTTPHeader : String ] , fileSize : Int ) -> ClosedRange < Int > ? {
128128 guard let headerValue = headers [ . range] else { return nil }
129129 let scanner = Scanner ( string: headerValue)
130130 guard scanner. scanString ( " bytes " ) != nil ,
131131 scanner. scanString ( " = " ) != nil ,
132132 let start = scanner. scanInt ( ) ,
133- scanner. scanString ( " - " ) != nil ,
134- let end = scanner. scanInt ( ) ,
135- start <= end else {
133+ scanner. scanString ( " - " ) != nil else {
136134 return nil
137135 }
136+
137+ // if no end clamp at 10MB
138+ let end = scanner. scanInt ( ) ?? min ( start + 10_000_000 , fileSize) - 1
139+ guard start <= end else { return nil }
138140 return start... end
139141 }
140142}
Original file line number Diff line number Diff line change @@ -186,6 +186,15 @@ struct HTTPHandlerTests {
186186 #expect(
187187 FileHTTPHandler . makePartialRange ( for: [ . range: " bytes=1-5 " ] ) == 1 ... 5
188188 )
189+ #expect(
190+ FileHTTPHandler . makePartialRange ( for: [ . range: " bytes=0-5100 " ] ) == 0 ... 5100
191+ )
192+ #expect(
193+ FileHTTPHandler . makePartialRange ( for: [ . range: " bytes=0- " ] , fileSize: 10 ) == 0 ... 9
194+ )
195+ #expect(
196+ FileHTTPHandler . makePartialRange ( for: [ . range: " bytes=2- " ] , fileSize: 10 ) == 2 ... 9
197+ )
189198 #expect(
190199 FileHTTPHandler . makePartialRange ( for: [ . range: " bytes = 8 - 10 " ] ) == 8 ... 10
191200 )
@@ -313,3 +322,9 @@ struct HTTPHandlerTests {
313322 #expect( response. statusCode == . ok)
314323 }
315324}
325+
326+ private extension FileHTTPHandler {
327+ static func makePartialRange( for headers: [ HTTPHeader : String ] ) -> ClosedRange < Int > ? {
328+ makePartialRange ( for: headers, fileSize: 10000 )
329+ }
330+ }
You can’t perform that action at this time.
0 commit comments