I have a post request that I want to make using URLSession.
The post request looks like this:
curl -X POST 'https://smartdevicemanagement.googleapis.com/v1/enterprises/privatekey/devices/devicekey:executeCommand' -H 'Content-Type: application/json' -H 'Authorization: authtoken' --data-raw '{
"command" : "sdm.devices.commands",
"params" : {
"commandName" : "cmdValue"
}
}'
As this is a POST request, I want to only decode if the response is an error message.
Here is the code I currently have:
guard let url = URL(string: "https://smartdevicemanagement.googleapis.com/v1/enterprises/\(project_id)/devices") else {return}
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("token", forHTTPHeaderField: "Authorization")
let cmdParams: [String: String] = ["command":"sdm.devices.commands", "params" : ["commandName": "cmdValue"]]
do {
request.httpBody = try JSONSerialization.data(withJSONObject: cmdParams)
} catch let error {
print(error.localizedDescription)
}
URLSession.shared.dataTask(with: request) { (data, response, error) in
guard error == nil else {print(error!.localizedDescription); return }
guard let data = data else {print("empty data"); return }
The cmdParams are throwing an error, so I'm not sure how to structure the params request properly, a successful POST will result in the API returning {}
an unsuccessful request will return some error.
How can I adjust my code to get this working?
CodePudding user response:
You need to encode the JSON string as data. Then you can add it as the httpBody.
Don't forget to add the token to the request.
// Encode your JSON data
let jsonString = "{ \"command\" : \"sdm.devices.commands\", \"params\" : { \"commandName\" : \"cmdValue\" } }"
guard let jsonData = jsonString.data(using: .utf8) else { return }
// Send request
guard let url = URL(string: "https://smartdevicemanagement.googleapis.com/v1/enterprises/\(project_id)/devices") else {return}
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = jsonData
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue("token", forHTTPHeaderField: "Authorization") // Most likely you want to add some token here
// request.setValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization")
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
if let error = error {
// Handle HTTP request error
} else if let data = data {
// Handle HTTP request response
} else {
// Handle unexpected error
}
}
task.resume()
CodePudding user response:
You could try using "urlencoded" to encode your request body. Here is my test code: (note, since I do not have a paid subscription to this service I cannot fully test my code)
struct ContentView: View {
let project_id = 123 // <-- adjust to your needs
var body: some View {
Text("testing")
.onAppear {
if let url = URL(string: "https://smartdevicemanagement.googleapis.com/v1/enterprises/\(project_id)/devices") {
doPOST(url: url)
}
}
}
func doPOST(url: URL) {
var request = URLRequest(url: url)
request.httpMethod = "POST"
// try urlencoding
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.setValue("token", forHTTPHeaderField: "Authorization") // <-- your api "token" here
var components = URLComponents(url: url, resolvingAgainstBaseURL: false)!
components.queryItems = [
URLQueryItem(name: "command", value: "sdm.devices.commands"),
URLQueryItem(name: "params", value: "{ \"commandName\" : \"cmdValue\" }")
]
if let query = components.url!.query {
print("--> query: \(query)")
request.httpBody = Data(query.utf8)
}
let task = URLSession.shared.dataTask(with: request) { data, response, error in
showResponse(data) // <-- for debuging
guard error == nil else { print("--> error: \(error)"); return }
guard let data = data else { print("empty data"); return }
}
task.resume()
}
func showResponse(_ data: Data?) {
if let data = data, let json = try? JSONSerialization.jsonObject(with: data, options: .mutableContainers), let jsonData = try? JSONSerialization.data(withJSONObject: json, options: .prettyPrinted) {
print("\n---> response: " String(decoding: jsonData, as: UTF8.self))
} else {
print("=========> error")
}
}
}
If this does not work, have a look at this doc:
In particular: The URL uses gRPC Transcoding syntax
. It may be relevant.