Added POST, PUT, PATCH Support (#59)
Some checks are pending
Build and Release IPA / Build IPA (push) Waiting to run

This commit is contained in:
cranci 2025-03-25 06:29:57 +01:00 committed by GitHub
commit c12aa5b8b2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -78,65 +78,127 @@ extension JSContext {
} }
func setupFetchV2() { func setupFetchV2() {
let fetchV2NativeFunction: @convention(block) (String, [String: String]?, JSValue, JSValue) -> Void = { urlString, headers, resolve, reject in let fetchV2NativeFunction: @convention(block) (String, [String: String]?, String?, String?, JSValue, JSValue) -> Void = { urlString, headers, method, body, resolve, reject in
guard let url = URL(string: urlString) else { guard let url = URL(string: urlString) else {
Logger.shared.log("Invalid URL", type: "Error") Logger.shared.log("Invalid URL", type: "Error")
reject.call(withArguments: ["Invalid URL"]) reject.call(withArguments: ["Invalid URL"])
return return
} }
let httpMethod = method ?? "GET"
var request = URLRequest(url: url) var request = URLRequest(url: url)
request.httpMethod = httpMethod
Logger.shared.log("FetchV2 Request: URL=\(url), Method=\(httpMethod), Body=\(body ?? "nil")", type: "Debug")
// Ensure no body for GET requests
if httpMethod == "GET", let body = body, !body.isEmpty, body != "null", body != "undefined" {
Logger.shared.log("GET request must not have a body", type: "Error")
reject.call(withArguments: ["GET request must not have a body"])
return
}
// Set the body for non-GET requests
if httpMethod != "GET", let body = body, !body.isEmpty, body != "null", body != "undefined" {
request.httpBody = body.data(using: .utf8)
}
// Set headers
if let headers = headers { if let headers = headers {
for (key, value) in headers { for (key, value) in headers {
request.setValue(value, forHTTPHeaderField: key) request.setValue(value, forHTTPHeaderField: key)
} }
} }
let task = URLSession.cloudflareCustom.dataTask(with: request) { data, response, error in
let task = URLSession.cloudflareCustom.downloadTask(with: request) { tempFileURL, response, error in
if let error = error { if let error = error {
Logger.shared.log("Network error in fetchV2NativeFunction: \(error.localizedDescription)", type: "Error") Logger.shared.log("Network error in fetchV2NativeFunction: \(error.localizedDescription)", type: "Error")
reject.call(withArguments: [error.localizedDescription]) reject.call(withArguments: [error.localizedDescription])
return return
} }
guard let data = data else {
guard let tempFileURL = tempFileURL else {
Logger.shared.log("No data in response", type: "Error") Logger.shared.log("No data in response", type: "Error")
reject.call(withArguments: ["No data"]) reject.call(withArguments: ["No data"])
return return
} }
// Just pass the raw data string and let JavaScript handle it do {
if let text = String(data: data, encoding: .utf8) { let data = try Data(contentsOf: tempFileURL)
resolve.call(withArguments: [text])
} else { // Check response size before processing
Logger.shared.log("Unable to decode data to text", type: "Error") if data.count > 10_000_000 { // Example: 10MB limit
reject.call(withArguments: ["Unable to decode data"]) Logger.shared.log("Response exceeds maximum size", type: "Error")
reject.call(withArguments: ["Response exceeds maximum size"])
return
}
if let text = String(data: data, encoding: .utf8) {
resolve.call(withArguments: [text])
} else {
Logger.shared.log("Unable to decode data to text", type: "Error")
reject.call(withArguments: ["Unable to decode data"])
}
} catch {
Logger.shared.log("Error reading downloaded file: \(error.localizedDescription)", type: "Error")
reject.call(withArguments: ["Error reading downloaded file"])
} }
} }
task.resume() task.resume()
} }
self.setObject(fetchV2NativeFunction, forKeyedSubscript: "fetchV2Native" as NSString) self.setObject(fetchV2NativeFunction, forKeyedSubscript: "fetchV2Native" as NSString)
// Simpler fetchv2 implementation with text() and json() methods
let fetchv2Definition = """ let fetchv2Definition = """
function fetchv2(url, headers) { function fetchv2(url, headers = {}, method = "GET", body = null) {
return new Promise(function(resolve, reject) { if (method === "GET") {
fetchV2Native(url, headers, function(rawText) { return new Promise(function(resolve, reject) {
const responseObj = { fetchV2Native(url, headers, method, null, function(rawText) { // Pass `null` explicitly
_data: rawText, const responseObj = {
text: function() { _data: rawText,
return Promise.resolve(this._data); text: function() {
}, return Promise.resolve(this._data);
json: function() { },
try { json: function() {
return Promise.resolve(JSON.parse(this._data)); try {
} catch (e) { return Promise.resolve(JSON.parse(this._data));
return Promise.reject("JSON parse error: " + e.message); } catch (e) {
} return Promise.reject("JSON parse error: " + e.message);
} }
}; }
resolve(responseObj); };
}, reject); resolve(responseObj);
}); }, reject);
} });
""" }
// Ensure body is properly serialized
const processedBody = body ? JSON.stringify(body) : null;
return new Promise(function(resolve, reject) {
fetchV2Native(url, headers, method, processedBody, function(rawText) {
const responseObj = {
_data: rawText,
text: function() {
return Promise.resolve(this._data);
},
json: function() {
try {
return Promise.resolve(JSON.parse(this._data));
} catch (e) {
return Promise.reject("JSON parse error: " + e.message);
}
}
};
resolve(responseObj);
}, reject);
});
}
"""
self.evaluateScript(fetchv2Definition) self.evaluateScript(fetchv2Definition)
} }