How to send a JSON body in a get request with Alamofire - ios

I'm facing a problem since 3 weeks now, I'm using an API pretty particular which need a JSON object as body in a GET request. And I think that it's the main problem
I tried to custom my encoding with ParameterEncoding thanks the Alamofire documentation and all the help provide in Stack Overflow and still no success.
When I make my request with Postman or with curl in my terminal, there is no problem but when I develop in swift with Alamofire, I get an internal error 500 or nothing passed in my response (when I set my parameter in my request function with the keyword encoding : JSONEncoding.default).
Here is the curl exemple :
curl -X GET https://blih.epitech.eu/user/repositories
-H 'Content-Type: application/json'
-d '{"user": account, "signature": password}'
Here is the sample of my code :
/// swift 5
let userString = #"{"user":"\#(account)","signature":"\#(signaturePassword)"}"#
let urlString = "https://blih.epitech.eu/repositories"
Alamofire.request(urlString, method: .get, parameters: [:], encoding: JSONStringArrayEncoding.init(string: userString), headers: nil)
.responseJSON { (response) in
debugPrint(response)
}
The 'JSONStringArrayEncoding' is a structure with my Custom Encoding :
struct JSONStringArrayEncoding: ParameterEncoding {
private let myString: String
init(string: String) {
self.myString = string
}
func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest {
var urlRequest = try urlRequest.asURLRequest()
let data = Data(myString.utf8)
if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil {
urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
}
urlRequest.httpBody = data
return urlRequest
}
}
I expect to have a json Array when the request is successsful :
{
"message": "Listing successful",
"repositories": {
"aaaa": {
"uuid": "e3a6bea1-c581-5fde-a3a8",
"url": "https://blih.epitech.eu/repository/aaa"
}
}
}
But I get an internal error 500.
Thank you in advance for your help.

Just replace JSON.encoding -> URLEncoding
Alamofire.request(path,method: .get, parameters: params, encoding: URLEncoding.default, headers: nil)

As you have mentioned that, your request is working using postman or curl in terminal. Below is the result I'm getting
As pointed by #Glenn, result of visiting browser with url blih.epitech.eu/user/repositories show result like below
I believe, there is something wrong with the url you're requesting to.
EDITED:
See the below image to see the why it is working with curl
Try your request as post once and add content-type = application/x-www-form-urlencoded I am not sure but it might help.

Try this:
let url = "https://blih.epitech.eu/user/repositories"
let param = ["user":"asdfdsf",
"signature":"password"]
if let jsonData = try? JSONEncoder().encode(param) {
var request = URLRequest(url: URL(string: url)!)
request.httpMethod = HTTPMethod.post.rawValue
request.setValue("application/json; charset=UTF-8", forHTTPHeaderField: "Content-Type")
request.httpBody = jsonData
Alamofire.request(request).responseJSON {
(response) in
debugPrint(response)
}
}
OUTPUT:
{
error = "Bad token";
}

Related

Convert httpBody for x-www-urlencoded

I'm doing a POST call to server but Alamofire always send the body as a JSON and not as a Form URL Encoded, I do know that in oder to encode the body I have to insert data(using: .utf8, allowLossyConversion: false), but I don't know where.
How can I fix my code?
This is my actual code:
func asURLRequest() throws -> URLRequest {
let url = try DBank.StagingServer.baseUrl.asURL()
var urlRequest = URLRequest(url: url.appendingPathComponent(path))
// HTTP Method
urlRequest.httpMethod = method.rawValue
// Common Headers
headers.forEach { (field, value) in
urlRequest.setValue(value, forHTTPHeaderField: field)
}
// Parameters
if let parameters = parameters {
do {
urlRequest.httpBody = try JSONSerialization.data(withJSONObject: parameters, options: [])
} catch {
throw AFError.parameterEncodingFailed(reason: .jsonEncodingFailed(error: error))
}
}
I'm guessing you have response handler like below:
Alamofire.request(url, method: .post, parameters: params, encoding: URLEncoding(destination: .queryString), headers: headers)
.validate(statusCode: 200..<300)
.responseString { response in
//response.result.value will contain http response from your post call
}
With the result from this response you would set:
UserDefaults.standard.set("<result>", forKey: "<token>")

Send Alamofire request with parameters in swift

I want to send a request with some parameters in swift.
body has XML content also.
http://example.com/POST
Body is : xml = "<root>abc</root>"
user : "admin"
ID : "21User"
I found Alamofire code which has responseJSON, but my response will not be JSON.
It'll be XML. So how to use it ?
The Alamofire request could look like this:
Alamofire.request(.POST, "https://something.com", parameters: Dictionary() , encoding: .Custom({
(convertible, params) in
let mutableRequest = convertible.URLRequest.copy() as! NSMutableURLRequest
let data = (self.testString as NSString).dataUsingEncoding(NSUTF8StringEncoding)
mutableRequest.HTTPBody = data
mutableRequest.setValue("application/x-www-form-urlencoded; charset=utf-8", forHTTPHeaderField: "Content-Type")
return (mutableRequest, nil)
}))
.responseJSON { response in
print(response.response)
print(response.result)
}
}
Try same, but use responseData or responseString instead of responseJSON .

Send Array of Request Body in an Alamofire Request

I have to send an array of request body and following is the request body that i have to send
[{
"user": "abc",
"id": "demo"
}]
What i've tried?
var requestArray = [[String: String]]()
let params = [
"user": "abc",
"id": "demo"
]
requestArray.append(params)
var request = URLRequest(url: URL.init(string: myUrl)!)
request.httpMethod = ".post"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try! JSONSerialization.data(withJSONObject: requestArray)
Alamofire.request(request)
.response{
response in
print("Request Body:- \(response.request)")
print(response)
}
Problems that i am facing
URL works flawlessly in both Postman and an Android App
Above solution is not working for me. My web service returns me 400 error code (Bad Request)
I am new to iOS development so any help will be appreciated.
Guys i have fixed the issue. I was playing around with some of the solutions from you guys and suddenly it worked!
So what was the main problem?
I changed the request.httpMethod = ".post" to request.httpMethod = "post".
Initially this did not work when i commented back to #NiravD but after some time when i did the changes below, i was able to see the output
Additional changes to view the response on console
Replaced .response to .responseJSON
Thanks a lot to everyone who helped :)
First of all Alamofire requires Parameter to be of type [String: Any], and the second you don't need to make a post request like that. No need for JSONSerialization. Try this and it will be ok.
let params: [String: Any] = [
"user": "abc",
"id": "demo"
]
Alamofire.request(URL.init(string: myUrl)!, method: .post, parameters: params)
.validate()
.responseString {
(response) in
print(response)
}
May be you are missing headers. Can you try it adding the headers that you can see n postman?
Please try this
// this should accompaign your required work [[String:Any]]
var requestArray = [AnyObject] // => Array to conatin dictionaries of type [String: Any]
var dictionaryObject = [String: AnyObject] // => to create some dictionary to append in requestArray
dictionaryObject["user"] = "abc"
dictionaryObject["id"] = "demo"
requestArray.append(dictionaryObject)
Alamofire.request(URL.init(string: myUrl)!, method: .post, parameters: requestArray).validate().responseString { (response) in
print(response)
}
You must pass your requestArray from Alamofire.request instead of request
Alamofire.request(requestArray)
manager.request(url, method: .get, headers: AUTH_HEADER).responseJSON { response in
switch response.result {
case .success:
//whatever you want to do in succes
case .failure(let error):
if let del = self.delegate {
//do what you want
}
print(error)
}
}

Why Authorization header gets removed in iOS PATCH requests?

there. I got a very strange problem. The thing is that when i'm trying to send PATCH requests server says that no Authorization header contains token. The same for PUT request.Tried to sniff and found out that no Authorization header is sent at all. While any other types of request contain Authorization header. First thought its Alamofire framework specific problem, but using NSURLConnection requests and NSURLSession tasks gave me the same: NO AUTHORIZATION HEADER IS SENT!
Here is my code used for Alamofire:
Alamofire.request(.PATCH, path, parameters: ["email":"new#mail.com"], encoding: .JSON, headers: ["Authorization":"token \ ((User.sharedUser().token)!)"]).validate().responseJSON { (response) in
if response.response?.statusCode == 200{
print("success")
}else{
print("Error")
}
}
and here is code with NSURLConnection:
let request:NSMutableURLRequest = NSMutableURLRequest(URL:url)
request.HTTPMethod = "PATCH"
request.addValue("\(token)", forHTTPHeaderField: "authorization")
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
do{
let bodyData = try NSJSONSerialization.dataWithJSONObject(["email":"nuv#gmail.com"], options: [])
request.HTTPBody = bodyData
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue())
{
(response, data, error) in
if let mdata = data {
let contents = NSString(data:data, encoding:NSUTF8StringEncoding)
print(contents)
} else {
print(error?.localizedDescription)
}
}
}catch{
print("failed serialization")
}
IIRC, the Authorization header is one of those headers that NSURLSession reserves for its own purposes, and may overwrite with its own values—particularly if you're sending something that looks like normal HTTP authentication.
Can you send an X-Authorization header instead?
Anyone who is looking for Alamofire 5(AF 5) solution here's the solution:
let headers: [String:String] = [...]
let params: [String: Any] = [...]
let url = URL(...)
let redirector = Redirector(behavior: Redirector.Behavior.modify({ (task, urlRequest, resp) in
var urlRequest = urlRequest
headers.forEach { header in
urlRequest.addValue(header.value, forHTTPHeaderField: header.key)
}
return urlRequest
}))
//use desired request func of alamofire and your desired enconding
AF.request(url, method: .post, parameters: params, encoding: JSONEncoding.default, headers: headers)
.responseJSON { response in
//handleDataResponse...
}.redirect(using: redirector)

Alamofire NSURLRequest via POST method doesn't work

I'm new to swift and iOS and trying to use Alamofire and router for them, which returns NSMutableURLRequest, but my code didn't work. So I just made one NSURLRequest for test, and requested it but results was same.
Here is my code. I'm currently using Alamofire and SwiftyJSON.
let params = ["Id": "1234567", "Token": "something"]
let url = NSURL(string: "myurl")
var request = NSMutableURLRequest(URL: url!)
request.HTTPMethod = Alamofire.Method.POST.rawValue
let encoding = Alamofire.ParameterEncoding.JSON
(request, _) = encoding.encode(request, parameters: params)
Alamofire.request(request)
.validate()
.responseJSON { response in
switch response.result {
case .Success:
if let value = response.result.value {
let json = JSON(value)
let token = json["token"].stringValue
let error = json["error"].stringValue
print("token : \(token), error : \(error)")
}
case .Failure(let error):
// TODO:
print(error)
}
}
Above code sends request without parameters. Are there any errors on my code?
I've checked your code and before executing encode function your request.HTTPBody is empty, but after it has some data like
Optional<NSData>
- Some:<7b22546f 6b656e22 3a22736f 6d657468 696e6722 2c224964 223a2231 32333435 3637227d>
When I call print(response.request?.HTTPBody) in Alamofire response block, I get the parameters as NSData and the HTTPBody includes the same data as before sending the request so it works.
Try also change the response from responseJSON to responseString, because if your response can't be parsed to JSON you get Failure.
I think you should check on your URL site if you get correct data.
Instead of your solution I use
Alamofire.request(method, url, parameters: parameters, encoding: .JSON) .responseString{ response in}
is the same but shorter and everything is as parameters.

Resources