swift PUT API Call missing parameters - ios

I Keep getting an Error Code 400: Missing parameters
I believe the problem is the format i am sending the data in
API DOC: http://middleware.idxbroker.com/docs/api/methods/index.html#api-Leads-putLead
I believe the required data the call needs is the First Name, Last Name, and email, do I need to send the other field as nil or can i leave them blank?
API Call
/// Send Lead to IDX Broker
///
/// - Parameter lead: new Lead data fields
/// - Returns: configs for URL Session
class func putLead(lead: String) -> URLRequest {
let urlString = "https://api.idxbroker.com/leads/lead"
let url = NSURL(string: urlString)
var downloadTask = URLRequest(url: (url as URL?)!, cachePolicy: URLRequest.CachePolicy.reloadIgnoringCacheData, timeoutInterval: 20)
/******************** Add Headers required for API CALL *************************************/
downloadTask.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
downloadTask.setValue(APICalls.getAccessKey(), forHTTPHeaderField: "accesskey")
downloadTask.setValue("json", forHTTPHeaderField: "outputtype")
downloadTask.httpMethod = "PUT"
downloadTask.httpBody = lead.data(using: .utf8)
/******************** End Headers required for API CALL *************************************/
return downloadTask
}
Data Sent to Function
/// Create lead from text fields
let postString = "lead(firstName=\(String(describing: firstName.text!))&lastName=\(String(describing: lastName.text!))&=email=\(String(describing: Email.text!)))"
/// URL Encoding for put API
let escapedString = postString.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)
print(escapedString!)
print(escapedString?.data(using: .utf8) ?? "Error")
/// API Call with passing json String
let downloadTask = APICalls.putLead(lead: escapedString!)
URLSession.shared.dataTask(with: downloadTask, completionHandler: {(data, response, error) -> Void in
/// Status Returned from API CALL
if let httpResponse = response as? HTTPURLResponse {
print("statusCode: \(httpResponse.statusCode)")
}
}).resume()
/******** End URL Session **********/

400 means the API is not getting on or more of the parameters you are passing. If the API received firstName then it would respond with an error stating that lastName was not received. If fist and last are passed then it would respond with email not received.
Testing your code I was able to get the expected string when I didn't use lead() in postString.

Related

How to specify the type of Data being sent in URLRequest in Swift?

I am trying to understand how to specify the type of data sent in a URLRequest
using the URLRequest.addvalue() method in Swift.
For example I have learned that
URLRequest.addValue("applications/json", forHTTPHeaderField: "Content-Type")
specifies json data to be send.
If for instance I need to send in xml, how should I go about that?
Any resources will also be helpful!
Here we can't assign header field to URLRequest class directly. So make a variable of URLRequest first.
// create post request
let url = URL(string: "http://www.myserver.com")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
// set header field
request.addValue("application/xml", forHTTPHeaderField: "Content-Type")
// insert xml data to the request
let stringParams : String = "<msg id=\"123123\" reqTime=\"123123\">" +
"<params class=\"API\">" +
"<param name=\"param1\">123213</param>" +
"<param name=\"param2\">1232131</param>" +
"</params>" +
"</msg>"
request.httpBody = stringParams.data(using: String.Encoding.utf8, allowLossyConversion: true)
// api call
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else {
print(error?.localizedDescription ?? "No data")
return
}
// process with data
print(data)
}
task.resume()

Sending HTTP POST request with Swift to Discord Webhook results in Response Error

I'm trying to create a URL Request in Swift to send an HTTP POST request to a Discord Webhook, and the request completes in a failure defined as 'responseProblem'. I'm not sure where the response problem is originating from.
Discord should technically be able to accept HTTP requests, and a bunch of research into the issue has led me nowhere. I've worked with Discord webhooks before, but I've never played around with this kind of stuff before, so I'm kinda stuck for what I should do now.
import Foundation
enum APIError:Error {
case responseProblem
case decodingProblem
case encodingProblem
}
struct APIRequest {
let resourceURL: URL
init(endpoint: String) {
let resourceString = "<discord-webhook-url-removed-for-privacy>"
guard let resourceURL = URL(string: resourceString) else {fatalError()}
self.resourceURL = resourceURL
}
func save (_ messageToSave:Message, completion: #escaping(Result<Message, APIError>) -> Void ) {
do {
var urlRequest = URLRequest(url: resourceURL)
urlRequest.httpMethod = "POST"
urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
urlRequest.httpBody = try JSONEncoder().encode(messageToSave)
let dataTask = URLSession.shared.dataTask(with: urlRequest) { data, response, _ in
guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200, let
jsonData = data else {
completion(.failure(.responseProblem)) // <<< 'responseProblem' is outputted in console as the error
return
}
do {
let messageData = try JSONDecoder().decode(Message.self, from: jsonData)
completion(.success(messageData))
} catch {
completion(.failure(.decodingProblem))
}
}
dataTask.resume()
} catch {
completion(.failure(.encodingProblem))
}
}
}
When I run this Swift program, I expected it to send a request to the Discord Webhook to send a message into it's designated channel. However, the only error outputted into the console is responseProblem. Please let me know if there is anything further I need to add to get the root cause of the problem (I'm still semi-fresh to Swift, and I normally work with JavaScript, so I'm not sure how to properly debug in Swift and Xcode.)
Swift app is built in iOS 12.2 because Xcode doesn't like this stuff in iOS 13
This is a simplified version of how I post to a Discord webhook with Swift. From your post I can't see how you're converting your custom Message struct into a JSON dictionary, but you need at least the key/value pair for "content" to successfully post a Discord Webhook. And of course the posts can be customized in many other ways (with a custom "username" etc.).
var messageString: String = ""
guard let url = URL(string: "your-full-discord-webhook-url") else { return }
let messageJson: [String: Any] = ["content": messageString]
let jsonData = try? JSONSerialization.data(withJSONObject: messageJson)
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "content-type")
request.httpBody = jsonData
let task = URLSession.shared.dataTask(with: request)
task.resume()

iOS - HTTP Method not making POST Request but instead making GET

I'm trying to make a POST call in my app using URLSession (and AlamoFire) no luck with either, I'm checking the network call on Charles Proxy and it's always being sent as a GET call even though I've specified the HTTPMethod to be "POST" or .post in both.
Weirdest part is updating the call to "DELETE" or "PUT" will work...just not "POST" or .post
I've tried just building the request from ground up in URLSession instead of using AlamoFire, tried changing the HTTPMethod (which works, just not for POST)
let session = URLSession.shared
let url = URL(string: endpointURL)!
var request = URLRequest(url: url)
request.httpMethod = "POST"
let jsonData: Data = try! requestProto.serializedData()
let task = session.uploadTask(with: request, from: jsonData) { data, response, error in
print("request made")
}
task.resume()
Expected: Charles records a POST call
Actual: Charles is recording GET call for both GET and POST calls, but DELETE and PUT are working fine.
Try this with URLSession
// create a `URLRequest` because post are urlRequest used with urlSession.shared.uploadTask
var request = URLRequest(url: url)
// here pass in data format the body of the request
request.httpBody = body
// the request method.
request.httpMethod = "post"
// required when send a json type in request
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
URLSession.shared.uploadTask(with: request, from: nil) { (data, response, error) in
let response = (response as? HTTPURLResponse)?.statusCode
if (response! == 500 ){
print("error")
}
print("request made")
}.resume()
I don't know why, but make sure that you are sending https request (not http).

iOS9 + Swift: How To Set The Body of A Post Request Using a JSON Value?

I am trying to make an HTTP Post request to a development server with self signed certificate. This is the function making the POST call:
func makeHTTPPostRequest(path: String, body: JSON, onCompletion: (JSON?, NSError?) -> Void) {
let request = NSMutableURLRequest(URL: NSURL(string: path)!)
request.HTTPMethod = "POST"
// I am using SwiftyJSON
do {
request.HTTPBody = try body.rawData()
} catch _ { }
let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
let session = NSURLSession(configuration: configuration, delegate: self, delegateQueue:NSOperationQueue.mainQueue())
let task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
var json: JSON?
if let _data = data {
json = JSON(data: _data)
}
onCompletion(json, error)
})
task.resume()
}
When I make a POST request, the server returns me "Empty fields" error even though I have properly set the HTTPBody of the request:
PS: The route is working fine when I call it from Postman.
The request.HTTPBody property must be a NSData object. If you want to send JSON, the data object should contain a sequence of Unicode characters (preferable UTF-8) which is your serialised JSON representation.
Additionally, you should also set the Content-Type header accordingly to application/json.

Making HTTP Request with header in Swift

I am trying to make an HTTP request to the Imgur API. I am trying to retrieve all images associated with the tag "cats." The url, according to the Imgur API is: https://api.imgur.com/3/gallery/t/cats
the Imgur API states the following about the authorization needed to make get requests:
For public read-only and anonymous resources, such as getting image
info, looking up user comments, etc. all you need to do is send an
authorization header with your client_id in your requests. This also
works if you'd like to upload images anonymously (without the image
being tied to an account), or if you'd like to create an anonymous
album. This lets us know which application is accessing the API.
Authorization: Client-ID YOUR_CLIENT_ID
I've looked at the following questions and tried things suggested there, but none of them have helped.
JSON NSURLRequest with credentials
Swift GET request with parameters
How to make a Http get and set httpHeader in Swift?
My current code is this:
let string = "https://api.imgur.com/3/gallery/t/cats"
let url = NSURL(string: string)
let request = NSMutableURLRequest(URL: url!)
request.setValue("clientIDhere", forHTTPHeaderField: "Authorization")
//request.addValue("clientIDhere", forHTTPHeaderField: "Authorization")
request.HTTPMethod = "GET"
let session = NSURLSession.sharedSession()
let tache = session.dataTaskWithRequest(request) { (data, response, error) -> Void in
if let antwort = response as? NSHTTPURLResponse {
let code = antwort.statusCode
print(code)
}
}
tache.resume()
But I continually get a status code of 403, meaning authorization is required. What am I doing wrong?
I think you need to prepend Client-ID string to your actual client ID as for the header value:
request.setValue("Client-ID <your_client_id>", forHTTPHeaderField: "Authorization")
Updated for swift 4 :
func fetchPhotoRequest(YOUR_CLIENT_ID: String) {
let string = "https://photoslibrary.googleapis.com/v1/albums"
let url = NSURL(string: string)
let request = NSMutableURLRequest(url: url! as URL)
request.setValue(YOUR_CLIENT_ID, forHTTPHeaderField: "Authorization") //**
request.httpMethod = "GET"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
let session = URLSession.shared
let mData = session.dataTask(with: request as URLRequest) { (data, response, error) -> Void in
if let res = response as? HTTPURLResponse {
print("res: \(String(describing: res))")
print("Response: \(String(describing: response))")
}else{
print("Error: \(String(describing: error))")
}
}
mData.resume()
}

Resources