Kịch bản:Tải lên tệp nhanh Alamofire với yêu cầu đã ký: cách gửi tiêu đề ủy quyền?
- iPhone iOS 8+ ứng dụng
- dùng đăng nhập bằng sẽ tải lên một hình ảnh tiểu sử
Ứng dụng đã sử dụng Alamofire để đưa ra yêu cầu ký hợp đồng với các API backend. Thực sự đơn giản: ứng dụng gửi ba tiêu đề HTTP cụ thể (Authorization
, X-Api-Key
và timestamp
) để yêu cầu được ký. Gọi số Alamofire.request
thật dễ dàng để gửi headers
làm thông số để nó hoạt động tốt đẹp.
Bây giờ, người dùng cần có thể tải lên ảnh tiểu sử của họ. Vì người dùng đã đăng nhập vào ứng dụng, API phụ trợ sẽ biết người dùng nào đang gửi hình ảnh theo số yêu cầu đã ký - và đó là phần khó khăn mà tôi đã đấu tranh trong vài giờ qua. Alamofire.upload
chấp nhận các thông số hoàn toàn khác nhau từ .request
, vì vậy tôi không thể tìm ra cách gửi tiêu đề khi tải lên tệp.
Đã thử số Alamofire.Manager.session.configuration.HTTPAdditionalHeaders
cũ, nhưng đó là no longer supported. Tìm thấy các ví dụ về mã tải lên của tệp, không ai xem xét việc gửi tiêu đề tùy chỉnh.
Làm cách nào để gửi tiêu đề tùy chỉnh khi sử dụng phương thức Alamofire.upload
?
typealias requestDataType = [String:AnyObject]
private func signRequest(data: requestDataType) -> [String:String] {
var headers = [String:String]()
var authString = ""
var signatureHeaders = ""
// Iterates over SORTED data dictionary to build headers
for (k,v) in (data.sort{$0.0 < $1.0}) {
if !authString.isEmpty {
authString += "\n"
signatureHeaders += " "
}
authString += "\(k): \(v)"
signatureHeaders += "\(k)"
headers[k] = "\(v)"
}
let userApiKey = _loggedInUser!["api_key"].string!
let signature = authString.sha256(_loggedInUser!["api_secret"].string!)
headers["X-Api-Key"] = userApiKey
headers["Authorization"] = "Signature headers=\"\(signatureHeaders)\",keyId=\"\(userApiKey)\",algorithm=\"hmac-sha256\",signature=\"\(signature)\""
return headers
}
func uploadProfilePicture(photo: UIImage, callback: apiCallback){
guard let userId = _loggedInUser?["pk"].int else {
callback(Response(success: false, responseMessage: "User not logged in"))
return
}
let requestData: requestDataType = ["timestamp": "\(Int(NSDate().timeIntervalSince1970))"]
let aManager = Manager.sharedInstance
print(self.signRequest(requestData)) // Prints correct headers (Authorization, X-Api-Key, timestamp)
aManager.session.configuration.HTTPAdditionalHeaders = self.signRequest(requestData)
print(aManager.session.configuration.HTTPAdditionalHeaders) // Prints default headers, completely ignoring my custom headers
aManager.upload(.POST, "\(_apiBaseUrl)profiles/\(userId)/photo/", multipartFormData: { multipartFormData in
if let imageData = UIImageJPEGRepresentation(photo, 0.8) {
multipartFormData.appendBodyPart(data: imageData, name: "upload", fileName: "userphoto.jpg", mimeType: "image/jpeg")
}
for (key, value) in requestData {
multipartFormData.appendBodyPart(data: value.dataUsingEncoding(NSUTF8StringEncoding)!, name: key)
}
}, encodingCompletion: {
encodingResult in
debugPrint(encodingResult)
})
}
Yêu cầu đi qua. Trong nhật ký phụ trợ, tôi có thể thấy yêu cầu được trả lại HTTP 403
- Không được ủy quyền vì không thể ký yêu cầu. In các tiêu đề yêu cầu, không nhận được tiêu đề auth tùy chỉnh nào từ máy chủ.
Thêm ít nhất là nguyên mẫu cho phương thức 'signRequest' –
@DavidBerry được cập nhật. – mathielo