Send Alamofire request with parameters in swift - ios

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 .

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

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

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";
}

How to send a request with alamofire with xml Body

I installed Alamofire in my project and now here is what I have done.
I installed postman and I put my url and inside body a xml object and I got my result.
Here is a picture of what I exactly have done with postman
How can I now use Alamofire or SWXMLHash to send it as I send it with postman
Thanks in advance!
EDIT
I tried this from another question:
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
return (mutableRequest, nil)
}))
.responseJSON { response in
print(response.response)
print(response.result)
}
}
But it didn't send anything
This is the log:
Optional( { URL:
https://something.com } { status code: 200, headers {
Connection = "keep-alive";
"Content-Length" = 349;
"Content-Type" = "application/xml";
Date = "Wed, 02 Nov 2016 21:13:32 GMT";
Server = nginx;
"Strict-Transport-Security" = "max-age=31536000; includeSubDomains"; } })
FAILURE
EDIT
NEVER FORGET TO PASS parameters if you don't have simple add this , parameters: Dictionary()
Using Swift 3 and Alamofire 4
let stringParams : String = "<msg id=\"123123\" reqTime=\"123123\">" +
"<params class=\"API\">" +
"<param name=\"param1\">123213</param>" +
"<param name=\"param2\">1232131</param>" +
"</params>" +
"</msg>"
let url = URL(string:"<#URL#>")
var xmlRequest = URLRequest(url: url!)
xmlRequest.httpBody = stringParams.data(using: String.Encoding.utf8, allowLossyConversion: true)
xmlRequest.httpMethod = "POST"
xmlRequest.addValue("application/xml", forHTTPHeaderField: "Content-Type")
Alamofire.request(xmlRequest)
.responseData { (response) in
let stringResponse: String = String(data: response.data!, encoding: String.Encoding.utf8) as String!
debugPrint(stringResponse)
}
With Swift 3 and Alamofire 4 you would create a custom ParameterEncoding. As with any other XML encoded body, SOAP messages can use this parameter encoding as in the following example. Other XML body encodings can be created similarly (check the line where it says urlRequest.httpBody = ...):
struct SOAPEncoding: ParameterEncoding {
let service: String
let action: String
func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest {
var urlRequest = try urlRequest.asURLRequest()
guard let parameters = parameters else { return urlRequest }
if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil {
urlRequest.setValue("text/xml", forHTTPHeaderField: "Content-Type")
}
if urlRequest.value(forHTTPHeaderField: "SOAPACTION") == nil {
urlRequest.setValue("\(service)#\(action)", forHTTPHeaderField: "SOAPACTION")
}
let soapArguments = parameters.map({key, value in "<\(key)>\(value)</\(key)>"}).joined(separator: "")
let soapMessage =
"<s:Envelope xmlns:s='http://schemas.xmlsoap.org/soap/envelope/' s:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>" +
"<s:Body>" +
"<u:\(action) xmlns:u='\(service)'>" +
soapArguments +
"</u:\(action)>" +
"</s:Body>" +
"</s:Envelope>"
urlRequest.httpBody = soapMessage.data(using: String.Encoding.utf8)
return urlRequest
}
}
And then use it like that:
Alamofire.request(url, method: .post, parameters: ["parameter" : "value"], encoding: SOAPEncoding(service: "service", action: "action"))
Assuming you that you're missing valid HTTP headers in your request, the updated request could look like:
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)
}
}
So, basically you should add one line
mutableRequest.setValue("application/x-www-form-urlencoded; charset=utf-8", forHTTPHeaderField: "Content-Type")
Update:
Try same, but use responseData or responseString instead of responseJSON because it is possible that your response is not JSON

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