How to get JSON data with HTTP Post method in swift 3? - ios

I confuse by getting HTTP response in post method. when i check response on postman, then the required response is got and profile updated successfully. But in programmatically i got error notice. What was the problem? how to solve it? please, refer screenshots. Thanks in advance!
Code i have try
override func viewDidLoad() {
super.viewDidLoad()
self.updateDetails()
}
func updateDetails()
{
let postString = "api=update_people&user_id=18&email=rajesh#gmail.com&first_name=Raejsh&phone=456562&age=26&gender=male&blood_group=A"
print(postString)
// let alertMessage = alert()
let url = NSURL(string: "http://kuruthi.in/portal/api/register")
let request = NSMutableURLRequest(url: url as! URL)
request.httpBody = postString.data(using: String.Encoding.utf8)
request.httpMethod = "POST"
request.addValue("123456", forHTTPHeaderField: "X-API-KEY")
request.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
let task = URLSession.shared.dataTask(with: request as URLRequest) { data,response,error in
guard error == nil && data != nil else
{
print("Error:\(error)")
return
}
let httpStatus = response as? HTTPURLResponse
if httpStatus!.statusCode == 200
{
if data?.count != 0
{
let responseString = String(data: data!, encoding: .utf8)
print(responseString)
}
else
{
print("No data got from url!")
}
}
else
{
print("error httpstatus code")
}
}
task.resume()
}
Response in Program output :
Response in postman:

The reason you are getting html code is that you are receiving some error from your web services look at the message "A PHP Error was encountered" in your output log.
The success in postman is because your request is in form-data. Compare the request from postman from Raw with the request you are generating.
You can refer this link for creating a request. But the code is in Objective-Cand you can use this link to convert the code, or you can use Alamofire to create requests and refer this link for creating multipart form-data requests using Alamofire

Related

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()

Is there a different way how to send a HTTP "POST" request without using third party libraries using custom header and body?

I am trying to send a HTTP "POST" request for a web-service that should return a base64 encoded picture. This is an example HTTP request for the service:
I am trying the following:
func fetchPicture(username: String, password: String) {
let url = URL(string: "https://myurl.com/download/bootcamp/image.php")!
var request = URLRequest(url: url)
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.httpMethod = "POST"
request.setValue(password.stringToSHA1Hash(), forHTTPHeaderField: "Authorization")
let postString = "username=\(username)"
request.httpBody = postString.data(using: .utf8)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else { // check for fundamental networking error
print("error=\(error)")
return
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 { // check for http errors
print("statusCode should be 200, but is \(httpStatus.statusCode)")
print("response = \(response)")
}
let responseString = String(data: data, encoding: .utf8)
print("responseString = \(responseString)")
}
task.resume()
}
I am getting an error 401 Unauthorized, I don't actually know whether it is because my request is bad all together or just the login initials. It would be grand if someone could go over the code and tell me if it actually corresponds to the request example shown above.
Thanks!
The first thing I notice is that you aren’t setting the request HTTP Method:
request.httpMethod = “POST”
As it turns out, I was using the CommonCrypto hashing function wrongly, I ended up using this instead:
https://github.com/apple/swift-package-manager/blob/master/Sources/Basic/SHA256.swift
And the SHA256 hash it returned was the correct one I needed, maybe this might help someone in the future.

iOS curl -X POST integration in swift

Hi I want to integrate the Curl POST api in my code I don't have any idea about this could any please guide me how to integrate this in swift language
The below web service call I have integrate in my code, Have tried but didn't get the result
curl -X POST http://stf.rortechnologies.com/api/session.js --data '{"user": {"email":"XXXXXX", "password":"XXXXXX"}}' -H "Content-Type:application/json"
let parameters = ["email":"admin.test#stf.com", "password":"password"]
let header = ["user": parameters]
//create the url with URL
let url = URL(string: "http://stf.rortechnologies.com/api/session.js")! //change the url
//create the session object
let session = URLSession.shared
//now create the URLRequest object using the url object
var request = URLRequest(url: url)
request.httpMethod = "POST" //set http method as POST
do {
request.httpBody = try JSONSerialization.data(withJSONObject: header, options: .prettyPrinted) // pass dictionary to nsdata object and set it as request body
} catch let error {
print(error.localizedDescription)
}
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
//create dataTask using the session object to send data to the server
let task = session.dataTask(with: request as URLRequest, completionHandler: { data, response, error in
guard error == nil else {
return
}
guard let data = data else {
return
}
do {
//create json object from data
if let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String: Any] {
print(json)
// handle json...
}
} catch let error {
print(error.localizedDescription)
}
})
task.resume()
here am getting the null response
App Transport Security (ATS)
You are calling a http url and not a https url. In production always https should be used. This is enforced by iOS.
For testing purposes one can declare exceptions in the info.plist, the documentation can be found here:
https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html#//apple_ref/doc/uid/TP40009251-SW33
JSON Encoding/Decoding
In Swift there is a convenient way to encode/decode JSON with JSONEncode/JSONDecoder. A simple solution might look like the one below.
Define Parameter Structs
struct Login: Encodable {
let user: User
}
struct User: Encodable {
let email: String
let password: String
}
Define Return Struct
struct Result: Decodable {
//add expected JSON fields here
}
Rest Call
private func makeRestCall() {
let login = Login(user: User(email: "admin.test#stf.com", password: "password"))
guard let loginJson = try? JSONEncoder().encode(login) else { return }
let config = URLSessionConfiguration.default
let session = URLSession(configuration: config)
guard let url = URL(string: "<add some valid url here>") else { return }
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Accept")
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = loginJson
let dataTask = session.dataTask(with: request) { (data, response, error) in
if let response = response as? HTTPURLResponse {
if response.statusCode == 200 {
guard let data = data else {
print ("call failed - no data returned")
return
}
guard let result = try? JSONDecoder().decode(Result.self, from: data) else {
print ("json decoding failed")
return
}
print ("call succesfully returned \(result)")
} else {
print ("call failed with status \(response.statusCode)")
}
} else {
print ("call failed: no http response")
}
}
dataTask.resume()
}
Check in a HTTPS Proxy
To make sure that you send the correct data, you could use a HTTPS proxy software. There it would look like this:

Swift POST request sends an empty body

Here's the code:
func makePOSTCall(endpoint: String, languageName: String) {
guard let url = URL(string: endpoint) else {
print("Could not create URL.")
return
}
let requestLang: [String: Any] = ["name": languageName]
let requestBody = try? JSONSerialization.data(withJSONObject: requestLang)
var urlRequest = URLRequest(url: url)
urlRequest.httpBody = requestBody
urlRequest.httpMethod = "POST"
let session = URLSession.shared
let task = session.dataTask(with: urlRequest) {
data, response, error in
guard let data = data, error == nil else {
print(error?.localizedDescription ?? "No data")
return
}
let responseJSON = try? JSONSerialization.jsonObject(with: data, options: [])
if let responseJSON = responseJSON as? [String: Any] {
print(responseJSON)
}
}
task.resume()
}
This sends a {"name": "Go"} JSON dictionary to Flask. Flask is supposed to append the language name to an array and return the full array in the response. Now, this works when I send the request manually, so it's not Flask's error. But when I send the above from iOS, I get request.json == None in the flask console. Clearly, I'm sending an empty body, but I shouldn't be. Any idea where I went wrong?
I call the function as
#IBAction func pressedMakePOSTCall(_ sender: UIButton) {
makePOSTCall(endpoint: "http://127.0.0.1:5000/lang", languageName: "Go")
}
I tried adding a trailing slash, just get a 404 in the console. The only question similar to mine that I've found is this: How to make HTTP Post request with JSON body in Swift and my code is basically identical.
#weissja19 was correct, I needed to set content type to application/json. Adding
urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
urlRequest.setValue("application/json", forHTTPHeaderField: "Accept")
fixed the error. Now the code works as I expected.
P.S. I couldn't catch it because I use the app Paw for testing, which sets content type automatically.
You might want to do it manually:
urlRequest.httpBody = "name=\(languageName)".data(using: .utf8)
Use JSONSerialization will make your POST body like {"name":"abc"} which might not be supported by your server

Swift: Adding Headers to my REST POST Request

I am still learning Swift and I am trying to make a POST request to my web service via my new iOS App written in Swift.
I need to know how to add 2 headers to my already existing code. Also am I adding the parameters correctly?
What I have so far:
let myUrl = NSURL(string: "https://MY-MOBILE-SERVICE.azure-mobile.net/api/login");
let request = NSMutableURLRequest(URL:myUrl!);
request.HTTPMethod = "POST";
// Compose a query string
let postString = "email=myemail#website.com&password=123";
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding);
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
data, response, error in
if error != nil
{
print("error=\(error)")
return
}
print("response = \(response)")
}
task.resume()
Here are the Headers I need to add to this request:
X-ZUMO-APPLICATION: 45634243542434
ACCEPT: application/json
How do I attach these headers to my request?
Have a look at the reference docs:
https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSMutableURLRequest_Class/#//apple_ref/occ/instm/NSMutableURLRequest/setValue:forHTTPHeaderField:
so you would do: request.setValue("ACCEPT" forHTTPHeaderField: "application/json")
if you use alamofire, this should work, it also eases things for you so you choose get or post
var pars2 : Dictionary<String,String> = ["api_key":"value"]
Alamofire.request(.POST, "someURLString" ,parameters: pars2).responseJSON()
{
(request, response, data, error) in
if(data != nil)
{
self.countryIDArray.removeAll(keepCapacity: false)
var status = data!["status"]!! as! String
}
}

Resources