-
Notifications
You must be signed in to change notification settings - Fork 17
Improvement/attachments and requests #147
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
Changes from 7 commits
951c3a8
b422cea
ec3f888
63f19f0
7983155
b447b73
84619eb
c2fb53a
ef88290
e7e659e
e5cbedb
bb3f7f6
e1cd517
4c2fbde
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -38,5 +38,4 @@ - (IBAction) crashAction: (id) sender { | |
array[1]; | ||
} | ||
|
||
|
||
@end |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,7 +6,7 @@ let package = Package( | |
name: "Backtrace", | ||
platforms: [ | ||
.iOS(.v12), | ||
.macOS(.v10_13), | ||
.macOS(.v11), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why do we want to bump the macos target? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. macos 11 is way past its end of life, this was a perfect opportunity to let it go.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should it this be a part of this pull request? Later if we will try to find where have we changed the macos version, it would be hard to understand why we did that here There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. reverted |
||
.tvOS(.v12) | ||
], | ||
products: [ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -48,41 +48,59 @@ extension MultipartRequest { | |
var multipartRequest = urlRequest | ||
let boundary = generateBoundaryString() | ||
multipartRequest.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type") | ||
|
||
let boundaryPrefix = "--\(boundary)\r\n" | ||
let body = NSMutableData() | ||
|
||
// temporary file to stream data | ||
let tempURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what happen to the file if the app is restarted while file is being created? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. file is created in Temp directory managed by OS, if the app is restarted there is no guarantee the file is persisted but :
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. unlike NSMutableData it's even possible to recover multipart request file! (not sure if necessary but can be a good excuse to consider for |
||
FileManager.default.createFile(atPath: tempURL.path, contents: nil, attributes: nil) | ||
let fileHandle = try FileHandle(forWritingTo: tempURL) | ||
|
||
defer { fileHandle.closeFile() } | ||
|
||
// attributes | ||
for attribute in report.attributes { | ||
body.appendString(boundaryPrefix) | ||
body.appendString("Content-Disposition: form-data; name=\"\(attribute.key)\"\r\n\r\n") | ||
body.appendString("\(attribute.value)\r\n") | ||
writeToFile(fileHandle, "--\(boundary)\r\n") | ||
writeToFile(fileHandle, "Content-Disposition: form-data; name=\"\(attribute.key)\"\r\n\r\n") | ||
writeToFile(fileHandle, "\(attribute.value)\r\n") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. shouldn't we do one write operation instead of multiple? I know opening writing and closing cost resources and time There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My intention was multiple small write operations with batched writes to reduce system overhead, i'll look into it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hmm i think it would be faster if we create a string with attributes in memory and then do one write operation. There is no chance we will oom the app via string with attributes so we should be good to go |
||
} | ||
// report file | ||
body.appendString(boundaryPrefix) | ||
body.appendString("Content-Disposition: form-data; name=\"upload_file\"; filename=\"upload_file\"\r\n") | ||
body.appendString("Content-Type: application/octet-stream\r\n\r\n") | ||
body.append(report.reportData) | ||
body.appendString("\r\n") | ||
|
||
|
||
// report | ||
writeToFile(fileHandle, "--\(boundary)\r\n") | ||
writeToFile(fileHandle, "Content-Disposition: form-data; name=\"upload_file\"; filename=\"upload_file\"\r\n") | ||
writeToFile(fileHandle, "Content-Type: application/octet-stream\r\n\r\n") | ||
fileHandle.write(report.reportData) | ||
writeToFile(fileHandle, "\r\n") | ||
|
||
// attachments | ||
for attachment in Set(report.attachmentPaths).compactMap(Attachment.init(filePath:)) { | ||
body.appendString(boundaryPrefix) | ||
body.appendString("Content-Disposition: form-data; name=\"\(attachment.filename)\"; filename=\"\(attachment.filename)\"\r\n") | ||
body.appendString("Content-Type: \(attachment.mimeType)\r\n\r\n") | ||
body.append(attachment.data) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can we stream data instead of reading it to memory? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we can use a Stream. Benefits:
Caviats:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. comment is on original not the updated code |
||
body.appendString("\r\n") | ||
writeToFile(fileHandle, "--\(boundary)\r\n") | ||
writeToFile(fileHandle, "Content-Disposition: form-data; name=\"\(attachment.filename)\"; filename=\"\(attachment.filename)\"\r\n") | ||
writeToFile(fileHandle, "Content-Type: \(attachment.mimeType)\r\n\r\n") | ||
fileHandle.write(attachment.data) | ||
writeToFile(fileHandle, "\r\n") | ||
} | ||
body.appendString("\(boundaryPrefix)--") | ||
multipartRequest.httpBody = body as Data | ||
|
||
multipartRequest.setValue("\(body.length)", forHTTPHeaderField: "Content-Length") | ||
|
||
|
||
// Final boundary | ||
writeToFile(fileHandle, "--\(boundary)--\r\n") | ||
|
||
// Set Content-Length | ||
let fileSize = try FileManager.default.attributesOfItem(atPath: tempURL.path)[.size] as? Int ?? 0 | ||
multipartRequest.setValue("\(fileSize)", forHTTPHeaderField: "Content-Length") | ||
|
||
// Attach file stream to HTTP body | ||
multipartRequest.httpBodyStream = InputStream(url: tempURL) | ||
|
||
return multipartRequest | ||
} | ||
|
||
private static func generateBoundaryString() -> String { | ||
return "Boundary-\(NSUUID().uuidString)" | ||
} | ||
|
||
private static func writeToFile(_ fileHandle: FileHandle, _ string: String) { | ||
if let data = string.data(using: .utf8) { | ||
fileHandle.write(data) | ||
} | ||
} | ||
} | ||
|
||
private extension NSMutableData { | ||
|
Uh oh!
There was an error while loading. Please reload this page.