swiftUI : How I can try to do POST API Call with parameters and headers - swift

class TranslateModel : ObservableObject {
func translateCall() {
guard let url = URL(string: "https://openapi.naver.com/v1/papago/n2mt") else { return }
print(1)
let param = "source=en&target=kr&text=hi"
let paramData = param.data(using: .utf8)
var request = URLRequest(url: url)
print(2)
request.httpMethod = "POST"
request.httpBody = paramData
print(3)
request.addValue("application/x-www-form-urlencoded; charset=UTF-8", forHTTPHeaderField: "Content-Type")
request.addValue("3Bwy8lMkuAgZOyDHm1Z3", forHTTPHeaderField: "X-Naver-Client-Id")
request.addValue("gg391Jc1Ge", forHTTPHeaderField: "X-Naver-Client-Secret")
print(4)
let data = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data else { fatalError() }
print(5)
guard error == nil else { fatalError()}
print(6)
guard let response = response as? HTTPURLResponse, response.statusCode >= 200 && response.statusCode < 300 else {return}
print(7)
print(data)
}
}
}
Firstly, Please check my code and screenshot.
I tried to do POST API with parameters and headers.
However, when I call the method, It's not working.
So, I checked the step of method, And found that the URLsession with request was not working.
But, I don't know what the problem is.
I think maybe parameters or headers faults.
could you let me know how I can solve this?

Related

How to read stream using Openai completion API in Swift - iOS?

I am trying to read the output in stream (as it comes) rather than waiting up for the whole response.
I have used the following code.
func caller() {
let completionAPIURL = URL(string: "https://api.openai.com/v1/completions")!
var request = URLRequest(url: completionAPIURL)
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Accept")
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("<Token>", forHTTPHeaderField: "Authorization")
let requestBody = """
{
"model": "<model>",
"prompt": "<prompt>",
"max_tokens": 200,
"stream": true
}
"""
request.httpBody = requestBody.data(using: .utf8)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
print((response as? HTTPURLResponse)?.statusCode)
guard let httpResponse = response as? HTTPURLResponse,
(200...299).contains(httpResponse.statusCode) else {
print("Error: invalid HTTP response code")
return
}
guard let data = data else {
print("Error: missing response data")
return
}
let eventStreamString = String(data: data, encoding: .utf8)!
let eventStreamLines = eventStreamString.components(separatedBy: "\n")
for event in eventStreamLines {
let eventFields = event.components(separatedBy: ":")
if eventFields.count < 2 {
continue
}
if fieldName == "data" {
if fieldValue == "[DONE]" {
// Stream terminated
break
} else {
// Process event data
print(event)
}
}
}
}
task.resume()
}
The problem is, it still waits till whole response is in place and then prints the data. What I am trying to achieve is to get the data as and how stream is generated, and not after the whole response is in place.
I am comparatively newbie and would expect a detailed help.

How to send post request through swiftUI in iOS 16.0?

Hey guys I am trying to use the face++ API to detect human body in a picture, but I keep getting 400 bad request. I think there is something wrong with my request code, but I am not sure where. For test, I host a picture on a third-party website just want to know how to get the request right. I will delete the api key later in case someone use it improperly.
private func requestFacePlusAPI() {
let url = URL(string: "https://api-cn.faceplusplus.com/humanbodypp/v1/detect")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("multipart/form-data", forHTTPHeaderField: "Content-type")
let api_key = "TpDqYnF1c5xe_iQzaBkVGkAqflqS3aCP"
let api_secret = "JsDx4hiQUOSXuus8MV21WB4F5YzQnB4B"
guard model.ImageData != nil else { return }
let image_base64 = model.ImageData!.base64EncodedData()
print(model.ImageData!)
print(image_base64)
let data = FacePlusData(api_key: api_key, api_secret: api_secret, image_url: "https://i.postimg.cc/prz1VKTY/Wechat-IMG2.jpg")
guard let uploadData = try? JSONEncoder().encode(data) else {
return
}
let task = URLSession.shared.uploadTask(with: request, from: uploadData) { data, response, error in
if let error = error {
print ("error: \(error)")
return
}
guard let response = response as? HTTPURLResponse,
(200...299).contains(response.statusCode) else {
print (response)
print ("server error")
return
}
if let mimeType = response.mimeType,
mimeType == "application/json",
let data = data,
let dataString = String(data: data, encoding: .utf8) {
print ("got data: \(dataString)")
}
}
task.resume()
}
Seeing the documentation and the cURL sample:
curl -X POST "https://api-us.faceplusplus.com/humanbodypp/beta/detect" -F "api_key=<api_key>" \
-F "api_secret=<api_secret>" \
-F "image_file=#image_file.jpg" \
-F "return_attributes=gender"
You need to send parameters in "URL Encoded Form":
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-type")
...
let uploadData = Data("api_key=\(api_key)&api_secret=\(api_secret)&image_url=https://i.postimg.cc/prz1VKTY/Wechat-IMG2.jpg".utf8)

How can I make a POST Request in Swift with parameters using URLSession

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?
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()
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:
https://developers.google.com/nest/device-access/reference/rest/v1/enterprises.devices/executeCommand
In particular: The URL uses gRPC Transcoding syntax. It may be relevant.

how to make get request with Authorization api key value in header Swift

below is my get request code. but getting 403 error ...please help!
func getUser(completion: #escaping(Result<User?, AuthenticationError>)-> Void) {
let loginVM = LoginViewModel()
let token = loginVM.accessToken
guard let url = URL(string: myURL) else {
completion(.failure(.custom(errorMessage: "URL is not correct")))
return
}
var request = URLRequest(url:url)
request.httpMethod = "GET"
request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
URLSession.shared.dataTask(with: request) { (data, response, error) in
guard let data = data, error == nil else {
completion(.failure(.custom(errorMessage: "No data")))
return
}
guard let registerResponse = try? JSONDecoder().decode(User.self, from: data) else{
completion(.failure(.custom(errorMessage: "no response")))
return
}
completion(.success(User))
}.resume()
}
and instruction from my backend guy for this part is this :
I tested on Postman It work as like charm. It must be happen in my request code with Authorization....

How to convert this to a POST call with a JSON serialized Object

I have tried Alamofire, I have tried it with all my heart. It just does not work for me. I finally got http GET working, but I need to get http POST working. Our POST API's take a Request object that has all the necessary data in it. I have requested the backend developers to provide me with a KEY-VALUE pair JSON (no embedded objects/arrays) so that I can use a Dictionary in my swift code convert that to json and send the request. All I need is now to convert the below code to POST.
My earlier questions that did not help much.
NSInvalidArgumentException Invalid type in JSON write DemographicsPojo
Swift 3.0, Alamofire 4.0 Extra argument 'method' in call
I have given up on Alamofire. I want to use Foundation classes. Simple basic and fundamental way of life :).
func callWebService(url : String) {
// Show MBProgressHUD Here
var config :URLSessionConfiguration!
var urlSession :URLSession!
config = URLSessionConfiguration.default
urlSession = URLSession(configuration: config)
// MARK:- HeaderField
let HTTPHeaderField_ContentType = "Content-Type"
// MARK:- ContentType
let ContentType_ApplicationJson = "application/json"
//MARK: HTTPMethod
let HTTPMethod_Get = "GET"
let callURL = URL.init(string: url)
var request = URLRequest.init(url: callURL!)
request.timeoutInterval = 60.0 // TimeoutInterval in Second
request.cachePolicy = URLRequest.CachePolicy.reloadIgnoringLocalCacheData
request.addValue(ContentType_ApplicationJson, forHTTPHeaderField: HTTPHeaderField_ContentType)
request.httpMethod = HTTPMethod_Get
let dataTask = urlSession.dataTask(with: request) { (data,response,error) in
if error != nil{
print("Error **")
return
}
do {
let resultJson = try JSONSerialization.jsonObject(with: data!, options: []) as? [String:AnyObject]
print("Result",resultJson!)
} catch {
print("Error -> \(error)")
}
}
dataTask.resume()
print("..In Background..")
}
Just pass JSON string and the API URL to this function. Complete code for POST.
func POST(api:String,jsonString:String,completionHandler:#escaping (_ success:Bool,_ response:String?,_ httpResponseStatusCode:Int?) -> Void) {
let url = URL(string: api)
var request: URLRequest = URLRequest(url: url!)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField:"Content-Type")
request.timeoutInterval = 60.0
//additional headers
if let token = Helper.readAccessToken() {
request.setValue("\(token)", forHTTPHeaderField: "Authorization")
}
let jsonData = jsonString.data(using: String.Encoding.utf8, allowLossyConversion: true)
request.httpBody = jsonData
let task = URLSession.shared.dataTask(with: request) {
(data: Data?, response: URLResponse?, error: Error?) -> Void in
var responseCode = 0
if let httpResponse = response as? HTTPURLResponse {
responseCode = httpResponse.statusCode
print("responseCode \(httpResponse.statusCode)")
}
if error != nil {
completionHandler(false, error?.localizedDescription,nil)
} else {
let responseString = String(data: data!, encoding: .utf8)
completionHandler(true, responseString, responseCode)
}
}
task.resume()
}