I have a simple cURL request which inserts data into Firestore database. This works, and no authentication is needed. I need to use cURL as no Firestore library is available for watchOS.
curl -X POST -H "Content-Type: application/json" -d '
{
"fields": {
"Field1": {
"stringValue": "'"$var12"'"
},
"Field2": {
"stringValue": "'"$var22"'"
},
"Field3": {
"stringValue": "$var32"
}
}
}' "https://firestore.googleapis.com/v1/projects/project-a9c7/databases/(default)/documents/TestRuns/3001/MyRuns"
However, when I try to rewrite the request using URLRequest
to use it in watchOS SwiftUI App, the app returns an error.
The previous answer did not help me.
ERROR: The code is 404 not found, but the same URL works from terminal.
statusCode should be 2xx, but is 404
response = <NSHTTPURLResponse: 0x6000021482c0> { URL: https://firestore.googleapis.com/v1/projects/runny-a9c7/databases/(default)/documents/TestRuns/3001/MyRuns } { Status Code: 404, Headers {
"Alt-Svc" = ( ...
If I use PATCH
instead of PUT
as suggested, the response is 400, and the code still doesn't create new record in database.
The URLRequest
call, which I tried running from SwiftUI Playground and also watchOS App:
import Foundation
// CREDIT: https://stackoverflow.com/questions/63530589/using-post-and-auth-with-firebase-database-and-swift
extension Dictionary {
func percentEncoded() -> Data? {
return map { key, value in
let escapedKey = "\(key)".addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed) ?? ""
let escapedValue = "\(value)".addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed) ?? ""
return escapedKey + "=" + escapedValue
}
.joined(separator: "&")
.data(using: .utf8)
}
func percentEncodedString() -> String? {
return map { key, value in
let escapedKey = "\(key)".addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed) ?? ""
let escapedValue = "\(value)".addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed) ?? ""
return escapedKey + "=" + escapedValue
}
.joined(separator: "&")
}
}
class Body: Codable {
var name: String
init(name: String){
self.name = name
}
}
extension CharacterSet {
static let urlQueryValueAllowed: CharacterSet = {
let generalDelimitersToEncode = ":#[]@" // does not include "?" or "/" due to RFC 3986 - Section 3.4
let subDelimitersToEncode = "!$&'()*+,;="
var allowed = CharacterSet.urlQueryAllowed
allowed.remove(charactersIn: "\(generalDelimitersToEncode)\(subDelimitersToEncode)")
return allowed
}()
}
let url = "https://firestore.googleapis.com/v1/projects/runny-a9c7/databases/(default)/documents/TestRuns/3001/MyRuns"
var request = URLRequest(url: URL(string: url)!)
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpMethod = "PUT"
let parameters: [String: Any] = [
"field1": "A",
"field2": "B"
]
request.httpBody = parameters.percentEncoded()
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data,
let response = response as? HTTPURLResponse,
error == nil else { // check for fundamental networking error
print("App error", error ?? "Unknown error")
return
}
guard (200 ... 299) ~= response.statusCode else { // check for http errors
print("statusCode should be 2xx, but is \(response.statusCode)")
print("response = \(response)")
return
}
let responseString = String(data: data, encoding: .utf8)
print("responseString = \(String(describing: responseString))")
}
task.resume()
Do you have any idea, when went wrong here, and how to fix the problem? Thanks for any help.
I needed to use the POST method:
request.httpMethod = "POST"
Then , I adjusted the parameters:
let parameters: [String:[String:[String: String]]] = [
"fields": ["Field1": ["stringValue": "val"]]
]
Finally, I sent the JSON data using the JSONSerialization
class.
request.httpBody = try? JSONSerialization.data(withJSONObject: parameters)
The data got successfully written to Firestore database.
Thanks so much Larme!.