Is it possible to ignore cache-control headers when performing a request/handling the response with AlamoFire?
Currently I am making a request as follows, and the server is returning large cache-control headers, when in fact we need to ignore them.
Alamofire.request(.GET, url).responseJSON { (_, _, result) in // Do something
I know the correct solution is to modify the server response, but this is not feasible at this time.
Also, there are other requests where I do want to honor the cache-control headers, so ideally I would a solution that does not involve changing a global configuration of AlamoFire.
To ignore the cached data, you need to set the cachePolicy on the NSURLRequest before using Alamofire to start it.
let URL = NSURL(string: "https://my_url_path...")!
let URLRequest = NSMutableURLRequest(URL: URL)
URLRequest.cachePolicy = .ReloadIgnoringCacheData
Alamofire.request(URLRequest)
.response { response in
print(response)
}
Setting the cachePolicy on the URL request always overrides the value set on the NSURLSessionConfiguration.
By default, the NSURLSessionConfiguration cache policy is set to .UseProtocolCachePolicy which will honor the Cache-Control header values.
Related
I try to call an API with Go. When using Postman everything is OK. But if I use the Go code from Postman the response is garbled/unclear.
Down below the code I'm using:
func CallAPI() {
url := "https://url"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer Token is normaly here")
req.Header.Add("User-Agent", "PostmanRuntime/7.19.0")
req.Header.Add("Accept", "Accept: application/json")
req.Header.Add("Cache-Control", "no-cache")
req.Header.Add("Postman-Token", "Postman token normaly here")
req.Header.Add("Host", "host normaly here")
req.Header.Add("Accept-Encoding", "gzip, deflate")
req.Header.Add("Connection", "keep-alive")
req.Header.Add("cache-control", "no-cache")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := ioutil.ReadAll(res.Body)
fmt.Println(string(body))
}
The response I get when I use fmt.Println(string(body)) looks like below. I also tried other API's with this code and had the same result.
r�痱�
I also tried to unmarshal the json to a struct and did get the following error
Invalid character '\x1f' looking for beginning of value
I think it's something about decoding. But I don't know what.
You ask the server to send the content compressed (req.Header.Add("Accept-Encoding", "gzip, deflate")), and that's what you get: a gzip response, indicated by the response header: Content-Encoding:[gzip].
Remove that header (don't set Accept-Encoding request header), and you should get plain JSON response. Or decode the gzip response yourself.
Note that if you omit this header, the default transport will still request gzip encoding, but then it will also transparently decode it. Since you request it explicitly, transparent, automatic decoding does not happen. This is documented at Transport.DisableCompression field:
// DisableCompression, if true, prevents the Transport from
// requesting compression with an "Accept-Encoding: gzip"
// request header when the Request contains no existing
// Accept-Encoding value. If the Transport requests gzip on
// its own and gets a gzipped response, it's transparently
// decoded in the Response.Body. However, if the user
// explicitly requested gzip it is not automatically
// uncompressed.
DisableCompression bool
So I've managed to write a bunch of tests and in every feature file I set the same request headers.
For example:
Given url appUrl
And path '/path'
* header Accept = 'application/json'
I'd like to know if there's a way to set a header once so that it is set before each scenario is run. I've read the documentation and tried the callSingle method as follows in karate-config.js:
karate.callSingle('classpath:api/Utilities/Feature/header.feature');
header.feature looks like:
Feature: common routing that sets the headers for all features
Background:
* configure headers = { Accept : 'application/json' }
And example feature where I expect the headers to be preset:
Feature: Header Preset
Scenario: I expect the header to be set
Given url appUrl
And path '/path'
When method get
Then status 200
* print response
#I expect the response to be returned in JSON format
However I'm unable to get this working. I don't think I've understood how the callSingle method works. Some pointers would be helpful. Thanks.
Ignore callSingle for now and focus on configure headers.
I think you are missing one step - which is to ensure that configure headers has been "applied" before each Scenario. If you are 100% sure that this applies "globally", just do this in karate-config.js:
karate.configure('headers', { Accept: 'application/json' });
Else you use the Background (in each feature):
* configure headers = { Accept: 'application/json' }
Typically you have more steps that are common, so you have them in a "common" feature file and call that for every test. Refer: https://github.com/intuit/karate#shared-scope
I have a * configure headers = read('classpath:configure-headers.js') in the Background of each of my feature files.
The configure-header.js looks like:
function() {
var out = {'Some-Header-We-Need': 'value'};
var authToken = karate.get('authToken');
if(authToken) {
out['Authorization'] = 'Bearer ' + authToken;
out['Content-Type'] = 'application/vnd.mycompany+json';
}
return out;
}
These headers always appear where I expect, except that when I'm making a PUT or PATCH or POST, the Content-Type header is being set to application/json. I can get my desired header by setting it before the call, e.g.
Given path myPath
And header Content-Type = 'application/vnd.mycompany+json'
And request read('classpath:requestBody.json')
When method POST
What can I do to not need to rewrite this header everywhere?
Wow, you actually did surface a bug in Karate that went un-detected for a long time. Thanks !
I've opened an issue here, and the fix is in the develop branch: https://github.com/intuit/karate/issues/510
Hopefully you can manage for a little while with the work-around. If urgent we can release a patch version.
I set a header for post a request with application/x-www-form-urlencoded form body;
here's my code
var headers = new Headers();
headers.append('Content-Type','application/x-www-form-urlencoded');
fetch(url, {
method: "POST",
mode:"cors",
header:headers,
body: qs.stringify(params)
})
But Content-type changed autoly in the request
Content-Type text/plain;charset=UTF-8
So that I can't receive this request params correctly.
Any one meet that?
CORS only allows a subset of content types. I lost lots of hours to this one. :)
See this answer. Even though application/x-www-form-urlencoded could be possible in a CORS request, I think it's very likely that your header is being overwritten by setting mode: 'cors' in your fetch call.
I am having problems in retrieving the contents of a http get request in the proper charset.
I tried several pieces of code, such as the following:
HttpClient h = new HttpClient();
//Content-Type: text/html; charset=UTF-8
//p.s. contents are in hebrew.
var resp = h.GetAsync("http://www.wnf.co.il");
var content = resp.Result.Content;
//remove the default Content-Type header
content.Headers.Remove("Content-Type");
content.Headers.Add("Content-Type", "text/html; charset=utf-8");
var res = content.ReadAsStringAsync();
var s = res.Result;
Console.WriteLine(s);
which still does not help, I still get the content in wrong encoding.
This post clarifies that setting the header's request headers charset will not help, it's the response's one that needs to be set. (Besides, you will get an error in trying to add
header "Content-Type" to a request Header.)
But I still could not end up with working retrieval of the content in the proper charset (utf-8).
What am I missing ?
I have been doing similar stuff with hebrew sites for a while, in comparing the response's header in Fiddler from this site and others where I do not have this problem - the only difference I see is indeed this Content-Type header in the response.
The issue is probably due to this bug:
https://connect.microsoft.com/VisualStudio/feedback/details/790174/system-net-http-httpcontent-readasstringasync-does-not-handle-imperfect-content-type-headers
The work-around is to get the response as a byte array and encode it yourself:
var bytes = await content.ReadAsByteArrayAsync();
var s = Encoding.UTF8.GetString(bytes, 0, bytes.Length);
As a side-note, is there a reason you're using .Result instead of await? You are blocking the current thread unnecessarily and setting yourself up for deadlocks.