I want to get X-Dem-Auth in a header request with swift to stock that in my app.
See the response :
headers {
"Content-Length" = 95;
"Content-Type" = "application/json; charset=utf-8";
Date = "Fri, 15 Apr 2016 08:01:58 GMT";
Server = "Apache/2.4.18 (Unix)";
"X-Dem-Auth" = null;
"X-Powered-By" = Express;
If the response is type of NSHTTPURLResponse you can get header from response.allHeaderFields
As apple documentation says :
A dictionary containing all the HTTP header fields received as part of the server’s response. By examining this dictionary clients can see the “raw” header information returned by the HTTP server.
The keys in this dictionary are the header field names, as received from the server. See RFC 2616 for a list of commonly used HTTP header fields.
So to get for example a X-Dem-Auth in response header you can access it in that way :
if let httpResponse = response as? NSHTTPURLResponse {
if let xDemAuth = httpResponse.allHeaderFields["X-Dem-Auth"] as? String {
// use X-Dem-Auth here
}
}
UPDATE
Updated due to comment from Evan R
if let httpResponse = response as? HTTPURLResponse {
if let xDemAuth = httpResponse.allHeaderFields["X-Dem-Auth"] as? String {
// use X-Dem-Auth here
}
}
Update for iOS 13 and above.
I suggest if the response is of type HTTPURLResponse and you want get to a specific header value only. Then below is a better approach.
if let httpResponse = response as? HTTPURLResponse {
if let xDemAuth = httpResponse.value(forHTTPHeaderField: "X-Dem-Auth") as? String {
// use X-Dem-Auth here
}
}
Related
I have an object with some text data received from a remote server using a POST request. Each time the page is opened, the application makes a request to the remote server.
How do I do caching?
Here is my code without caching:
import Foundation
struct NewsFeed: Codable {
var status: String = ""
var totalResults: Int = 0
var posts: [PostItem]
}
struct PostItem: Codable {
var id: Int
var title: String
var link: String
var date: String
var category: String
var thumbnail: String
var excerpt: String
var content: String
}
class NewsDecoder: ObservableObject {
#Published var newsFeed: NewsFeed?
#Published var hasContent: Bool = false
init() {
self.getNews()
}
func getNews() {
let urlString = "http://example.com/feed/json_news/all.json"
let url = URL(string: urlString)
guard url != nil else {
return
}
let dataTask = URLSession.shared.dataTask(with: url!) { (data, response, error) in
DispatchQueue.main.async {
if error == nil && data != nil {
let decoder = JSONDecoder()
do {
self.newsFeed = try decoder.decode(NewsFeed.self, from: data!)
self.hasContent = true
} catch {
print("Error: \(error)")
}
}
}
}
dataTask.resume()
}
}
Well, within the HTTP protocol layer, you do not explicitly cache the response. If the backend wishes the client to cache the payload from a POST response which you are later be able to fetch with a GET request, the backend would need to setup the response accordingly by specifying a Content-Location response header and an associated cache control header, according to RFC 7231 4.3.3 POST.
The payload returned has the location specified in the returned URL, and the URL has the same value as the POST's effective request URL. Please read here for more information about this specifically.
If that has been done by the backend and if you have configured your URLSession to use a URLCache on the client, the URLLoading mechanism would cache the payload under the URL returned in the "Content-Location" response header.
If you then issue a GET request with the given URL previously returned in the Content-Location response header, the caching mechanism would take effect.
However, there is no guarantee that POST caching is implemented on the client. When using URLCache it's worth to carefully investigate its behaviour and check if it is working as expected.
i got code error **status code: 400*
URL: https://conversation.8villages.com/1.0/contents/articles?state=published }
{ status code: 400, headers {
Connection = "keep-alive";
"Content-Length" = 2;
"Content-Type" = "application/json";
Date = "Tue, 11 Apr 2017 07:49:13 GMT";
Server = nginx;
} }
2 bytes
SUCCESS
JSON: {
}
my json is result SUCCESS but wht not show my DATA?
actually i get request method Alamofire with Consumer Key, Consumer Secret, Token Key and Token Secret. like this :
let params: HTTPHeaders = ["oauth_consumer_key":"*****",
"oauth_consumer_secret":"*****",
"oauth_token_key":"*****.",
"oauth_token_secret": "*****",
"oauth_signature_method": "HMAC-SHA1",
"oauth_timestamp_key" : "1491366048",
"oauth_version": "1.0"] as [String : Any] as! HTTPHeaders;
Alamofire.request("https://conversation.8villages.com/1.0/contents/articles?state=published", method: .get, headers: params).responseJSON { response in
print("test", response.request!) // original URL request
print("ini responseny", response.response!) // HTTP URL response
print("test", response.data!) // server data
print("test", response.result) // result of response serialization
if let JSON = response.result.value {
print("JSON: \(JSON)")
}
}
how to get my data API ??
Please keep in mind :
400 Bad Request : The server cannot or will not process the request
due to something that is perceived to be a client error (e.g.,
malformed request syntax, invalid request message framing, or
deceptive request routing).
For a better understanding check : this
I read answers in SO and checked the official Alamofire documentation but most of these answers increase the confusion whether the JSON data gets added to the URL parameters or the body.
The HTTP request must contain a parameter key, which is equal to my API key to access the API and the JSON containing the image data and some data related to the API.
the URL with the request parameter looks like this:
https://vision.googleapis.com/v1/images:annotate?key=My_API_Key
and the JSON structure is at This link.
My Swift code looks like this.
import SwiftyJSON
import Alamofire
// all imports are done
func requestAPI(body:JSON) -> JSON {
let APIKey:String = "My_API_KEY"
let header = ["Content-Type":"application/json"]
let url:String = "https://vision.googleapis.com/v1/images:annotate"
let parameters = ["key":APIKey]
var response = Alamofire.request(.POST,url,headers:header,parameters:parameters)
response.validate().responseJSON { response in
switch response.result {
case .Success:
if let value = response.result.value {
let json = JSON(value)
print("JSON: \(json)")
print(response.request)
}
case .Failure(let error):
print(error)
}
}
return body //dummy return
}
I did go through the Alamofire documentation.
From the
POST Request With URL-Encoded Parameters
section of the documentation,
let parameters = [
"foo": "bar",
"baz": ["a", 1],
"qux": [
"x": 1,
"y": 2,
"z": 3
]
]
Alamofire.request(.POST, "https://httpbin.org/post", parameters: parameters)
// HTTP body: foo=bar&baz[]=a&baz[]=1&qux[x]=1&qux[y]=2&qux[z]=3
My understanding of this is that the JSON passed as the parameters argument is added as the parameters to the URL (similar to the key:My_API_Key part of my request) for the HTTp POST request. and using the .JSON as an encoding option adds the parameters argument as a JSON body for the request. How do I do both (A parameter key that is to be URL encoded and the JSON data that is to be added to the HTTP body)? the request method of Alamofire seems to be doing either of the 2 using the same argument.
I tried creating a NSURLMutableRequest and adding the body. but while accessing the rawValue of a SwiftyJSON JSON object, I get the following error.
error: call can throw, but it is not marked with 'try' and the error is not handled
if let bodyData:NSData = body.rawData(){
this is the code.
func requestAPI(body:JSON) -> JSON {
let APIKey:String = "My_API_Key"
let header = ["Content-Type":"application/json"]
let url = NSURL(string:"https://vision.googleapis.com/v1/images:annotate")
let parameters = ["key":APIKey]
var request = NSMutableURLRequest(URL:url!)
request.HTTPMethod = "POST"
if let bodyData:NSData = body.rawData(){
request.HTTPBody = bodyData
}
let encoding = Alamofire.ParameterEncoding.URL
(request, _) = encoding.encode(request, parameters: parameters) // Parameters are added here
var response = Alamofire.request(.POST,url!,headers:header,parameters:parameters)
response.validate().responseJSON { response in
switch response.result {
case .Success:
if let value = response.result.value {
let json = JSON(value)
print("JSON: \(json)")
//return json
print(response.request)
}
case .Failure(let error):
print(error)
}
}
return body //dummy return
}
Where and how do I set both the HTTP body of the request to JsonData and encode the URL with the parameters?
I'm trying to handle a JSON response using Alamofire from an Alamofire request:
Alamofire.request(.POST, dbURL, parameters: ["username": username, "password": password]) .responseJSON { response in ... }
I'm reading the response with
let JSONResponse = response.result.value!
The value of this returns
({ keyOne = 2; keyTwo = 4; keyThree = 2; keyFour = 6;})
And to get data from this,
JSONResponse.valueForKey("exampleKey")
The problem I get is that this doesn't return simple data, it returns this (the responses are all numbers, but I can't use integerForKey because of obvious reasons):
(2)
(4)
(2)
(6)
How can I get, read and/or save the data from this function without the brackets?
I tried brute force-removing the brackets using stringByReplacingOccurencesOfString() but this is ugly and doesn't work in the first place.
If your json is this { "keyOne":2, "keyTwo":4, "keyThree":2, "keyFour":6 }
then this code should return the proper int values for you.
if let jsonURL = NSBundle.mainBundle().URLForResource("sample", withExtension: "json")
{
Alamofire.request(.GET, jsonURL, parameters:nil) .responseJSON {
response in
if let JSONResponse = response.result.value as? [String:Int]
{
print(JSONResponse)
if let val = JSONResponse["keyOne"] {
print ("val = \(val)")
}
}
}
}
I am using Alamofire for networking and SwiftyJSON for parsing server response in my iOS app.
I always get unknown while trying to do this println(JSON(data!))
Here is my request code :
Alamofire.request(.GET, URLString: "http://httpbin.org/get", parameters: ["foo": "bar"])
.response { (request, response, data, error) in
println("request ==== \(request)")
println("response ==== \(response)")
println("error ==== \(error)")
println("json ==== \(JSON(data!))")
println("data ==== \(data)")
}
And here is my console output :
request ==== <NSMutableURLRequest: 0x15e9a4e0> { URL: http://httpbin.org/get?foo=bar }
response ==== Optional(<NSHTTPURLResponse: 0x15ddc910> { URL: http://httpbin.org/get?foo=bar } { status code: 200, headers {
"Access-Control-Allow-Credentials" = true;
"Access-Control-Allow-Origin" = "*";
Connection = "keep-alive";
"Content-Length" = 430;
"Content-Type" = "application/json";
Date = "Wed, 04 Feb 2015 09:12:45 GMT";
Server = nginx;
} })
error ==== nil
json ==== unknown
data ==== Optional(<7b0a2020 22617267 73223a20 7b0a2020 20202266 6f6f223a 20226261 72220a20 207d2c20 0a202022 68656164 65727322 3a207b0a 20202020 22416363 65707422 3a20222a 2f2a222c 200a2020 20202241 63636570 742d456e 636f6469 6e67223a 2022677a 69703b71 3d312e30 2c636f6d 70726573 733b713d 302e3522 2c200a20 20202022 41636365 70742d4c 616e6775 61676522 3a202266 723b713d 312e302c 656e3b71 3d302e39 2c64653b 713d302e 382c7a68 2d48616e 733b713d 302e372c 7a682d48 616e743b 713d302e 362c6a61 3b713d30 2e35222c 200a2020 20202248 6f737422 3a202268 74747062 696e2e6f 7267222c 200a2020 20202255 7365722d 4167656e 74223a20 224f7545 73744d6f 6e43616d 696f6e2f 636f6d2e 50697865 6c734163 6164656d 792e4f75 4573744d 6f6e4361 6d696f6e 2028313b 204f5320 56657273 696f6e20 372e312e 32202842 75696c64 20313144 32353729 29220a20 207d2c20 0a202022 6f726967 696e223a 20223139 372e3134 2e31302e 3234222c 200a2020 2275726c 223a2022 68747470 3a2f2f68 74747062 696e2e6f 72672f67 65743f66 6f6f3d62 6172220a 7d0a>)
Am i doing something wrong?
The unknown value being printed is coming from SwiftyJSON. It appears that you are using the incorrect initializer. Instead you want to try the following.
var parsingError: NSError?
let json = JSON(data: dataFromServer, error: &error)
println(json)
println(parsingError)
This will run NSJSONSerialization.JSONObjectWithData over your NSData that you send into SwiftyJSON. If it succeeds, you'll get a valid JSON object. If it fails, you will still get your unknown type but the parsingError will tell you why parsing failed.
One last tip is that you could try to encode the dataFromServer to be able to visualize it properly. Here's how you could do that.
if let dataFromServer = dataFromServer as? NSData {
if let encodedData = NSString(data: dataFromServer, encoding: NSUTF8StringEncoding) {
println(encodedData)
}
}
Hope that helps!
I think that the problem was relative to the Alamofire library under iOS7. I ended up by working with AFNetworking and parsing web service response with SwiftyJSON without any strange problems.