-
Notifications
You must be signed in to change notification settings - Fork 52
Closed
Description
While trying to implement a web server in an iOS app that handles remote file uploads, I've run into an issue where receiving a request with a body over a certain size will always time out.
Iterating over request.bodySequence produces the correct amount of chunks, but indefinitely suspends after reaching the total content size.
I've reproduced the issue in sample code below. When the request body size is small everything is fine, but you can see this problem after increasing it to a certain point (seems to be bodySize = 2049*1024).
Sample code
struct ContentView: View {
let bodySize = 4096*1024
@State var server = HTTPServer(port: 80)
@State var state = "Idle"
@State var response: String?
@State var received: Int?
@State var task: Task<Void, Never>?
var body: some View {
ScrollView {
VStack {
GroupBox("State") {
Text(state)
}
if let received {
GroupBox("Received") {
Text(
Measurement(value: Double(received), unit: UnitInformationStorage.bytes),
format: .byteCount(style: .binary)
)
}
}
if let response {
GroupBox("Response") {
Text(response)
}
}
}
}
.safeAreaInset(edge: .bottom) {
Button("Send") {
task = Task {
defer { task = nil }
do {
let data = Data(repeating: 0, count: bodySize)
var request = URLRequest(url: URL(string: "http://localhost/upload")!)
request.httpMethod = "PUT"
let (_, response) = try await URLSession.shared.upload(for: request, from: data)
self.response = "Status Code: \((response as! HTTPURLResponse).statusCode)"
} catch {
response = error.localizedDescription
}
}
}
.disabled(task != nil)
}
.task {
await server.appendRoute("PUT /upload") { request in
await setState("Receiving")
await setReceived(0)
var total = 0
do {
for try await chunk in request.bodySequence {
total += chunk.count
await setReceived(total)
}
} catch {
await setState("Error: \(error.localizedDescription)")
throw error
}
await setState("Idle")
return HTTPResponse(statusCode: .ok)
}
try? await server.run()
}
}
func setState(_ state: String) {
self.state = state
}
func setReceived(_ received: Int?) {
self.received = received
}
}Metadata
Metadata
Assignees
Labels
No labels