Sources/Instrumentation/WKWebView/BodyCache/AjaxBodyHelper.swift (113 lines of code) (raw):
//
// Copyright 2023 aliyun-sls Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import Foundation
class AjaxBodyHelper {
static func setBodyRequest(bodyRequest: [String: Any], request: inout URLRequest) {
guard let value = bodyRequest["value"] else {
return
}
let bodyType = bodyRequest["bodyType"] as! String
let formEnctype: String = bodyRequest["formEnctype"] as? String ?? ""
var data: Data?
if bodyType == "Blob"{
data = AjaxBodyHelper.dataFromBase64(base64: value as! String)
} else if bodyType == "ArrayBuffer" {
data = AjaxBodyHelper.dataFromBase64(base64: value as! String)
} else if bodyType == "FormData" {
self.setFormData(value: value as! [String: Any], enctype: formEnctype, request: &request)
return
} else {
if let value = value as? [String: Any] {
data = try? JSONSerialization.data(withJSONObject: value, options: .prettyPrinted)
} else if let value = value as? String {
data = value.data(using: .utf8)
} else {
data = value as? Data
}
}
request.httpBody = data
}
static func dataFromBase64(base64: String) -> Data {
let components: [String] = base64.components(separatedBy: ",")
let splitBase64: String
if components.count == 2 {
splitBase64 = components.last ?? ""
} else {
splitBase64 = base64
}
let paddedLength = splitBase64.count + (splitBase64.count % 4)
let fixedBase64 = splitBase64.padding(toLength: paddedLength, withPad: "=", startingAt: 0)
return Data(base64Encoded: fixedBase64, options: .ignoreUnknownCharacters)!
}
static func setFormData(value: [String: Any], enctype: String, request: inout URLRequest) {
guard let formData = value["formData"] as? [[Any]] else {
return
}
let fileKeys = value["fileKeys"] as? [String]
var params = [String: Any]()
var fileDatas = [FileFormData]()
for pair: [Any] in formData {
if pair.count < 2 {
continue
}
guard let key = pair[0] as? String else {
continue
}
if let fileKeys = fileKeys, fileKeys.contains(key) {
guard let fileJSON = pair[1] as? [String: Any] else {
continue
}
var fileName: String
if let name = fileJSON["name"] as? String, name.count > 0 {
fileName = name
} else {
fileName = key
}
var fileFormData = FileFormData(key: key, fileName: fileName)
fileFormData.key = key
fileFormData.size = (fileJSON["size"] as? NSNumber)?.intValue
fileFormData.type = fileJSON["type"] as? String
if let lastModified = fileJSON["lastModified"] as? NSNumber, lastModified.intValue > 0 {
fileFormData.lastModified = lastModified.intValue
}
if "multipart/form-data" == enctype, let d = fileJSON["data"] as? String {
fileFormData.data = self.dataFromBase64(base64: d)
fileDatas.append(fileFormData)
} else {
params[key] = fileFormData.fileName
}
} else {
params[key] = pair[1]
}
}
if "multipart/form-data" == enctype {
URLRequestSerialization.shared.multipartFormRequestWithRequest(request: &request, params: params) { formData in
for fileData in fileDatas {
formData.appendPart(data: fileData.data ?? Data(), name: fileData.key, fileName: fileData.fileName, mimeType: fileData.type ?? "")
}
}
} else if "text/plain" == enctype {
var string = String()
let keys = Array(params.keys)
let last = keys.last
for key in keys {
string.append("\(URLRequestSerialization.percentEscapedString(from: key as NSString))=\(URLRequestSerialization.percentEscapedString(from: params[key] as! NSString))")
if key != last {
string.append("\r\n")
}
}
let data = string.data(using: .utf8)
request.httpBody = data
} else {
// application/x-www-form-urlencoded
var string = String()
let keys = Array(params.keys)
let last = keys.last
for key in keys {
string.append("\(URLRequestSerialization.percentEscapedString(from: key as NSString))=\(URLRequestSerialization.percentEscapedString(from: params[key] as! NSString))")
if key != last {
string.append("&")
}
}
let data = string.data(using: .utf8)
request.httpBody = data
}
}
}