I need response headers of the request URL that I need to recieve and process in UIWebview Delegate method webViewDidFinishLoad: ? But I don't understand how to achieve it. Please note that I don't need request headers but response headers.
One idea is to create a NSUrlConnection and fire the request again to recieve it in completion block but I don't want to make two calls. There must be some way that it is handled by UIWebView and response headers can be retrieved . I just don't know how to go about it. Any ideas are welcome.
Try this:
NSCachedURLResponse *resp = [[NSURLCache sharedURLCache] cachedResponseForRequest:webView.request];
But this only works for cacheable urls!
Related
NSURLCache is some kind of a dark art magic that is neither documented properly, nor behaves as expected.
I am using AFNetworking's AFHTTPSessionManager to utilise NSURLSession. I am using this mocking service to create custom HTTP responses.
I am setting the NSURLCache with disk capacity and all the cache policies.
Then in the URLSession:task:didCompleteWithError method of NSURLSessionTaskDelegate, I am doing this:
NSURLRequest *request = task.currentRequest;
NSCachedURLResponse *cachedResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:request];
The documentation states about the cachedResponseForRequest:
#result The NSCachedURLResponse stored in the cache with the given
request, or nil if there is no NSCachedURLResponse stored with the
given request.
AFNetworking's FAQ states:
So long as your NSURLRequest objects have the correct cache policy,
and your server response contains a valid Cache-Control header,
responses will be automatically cached for subsequent requests.
After all this my assumption is that the value of the the cachedResponse variable will be nil if the Cache-Control is NOT set properly. However, whatever I have tried to do so far - setting it to 'private', 'no-cache' or whatever - the cachedResponse ALWAYS contains the cached response. How can I verify that the caching mechanism works as expected ? Is there anything that I am missing from the setup ?
I have been doing my tests by firstly making the request online, then switching off the internet on my computer. XCode 7.0 beta iOS 9.0.
Any help is appreciated.
How can I get all the headers that are set for the RKObjectRequestOperation. I need to view the headers as there is something strange happening after a user has logged out, and want to view all headers before the operation starts.
Also is restkit caching authorization headers? I've tried setting the value in the manual request to an empty string and used [[RKObjectManager sharedManager].HTTPClient clearAuthorizationHeader]; to try clearing them, but the server is still receiving the Authorization header.
You can print defaultHeaders to check what is actually set in headers.
[[[RKObjectManager sharedManager] HTTPClient] defaultHeaders]
I have a UIWebview in my iOS app that needs to monitor the response headers for each page it goes to, I have tried to look for it on
webViewDidFinishLoad
and
shouldStartLoadWithRequest
but have not gotten far, further research has lead me to
didReceiveResponse
for NSURLConnection, but my understanding is that this can only get the first response, and can not get the second, or further responses.
If it would help any, I'm using Rubymotion to implement this.
It's not possible, I'm afraid. You can get the current web URL using JavaScript:
https://stackoverflow.com/a/2494051/204044
(or anything else that JS can access, for that matter)...but you're not able to get the headers. This is a security thing.
If you have control over the web server, you could pass in information that you need in a javascript object like this:
// In your webserver's code, assuming it's PHP:
<script type="text/javascript">
window.customDataString = "<?= $custom_data ?>";
</script>
// In Objective-C
NSString *customDataString = [webView stringByEvaluatingJavaScriptFromString:#"window.customDataString"];
I do something similar by using AFNetworking.
I use webView:shouldStartLoadWithRequest:navigationType: to capture all the link clicked by users. I return NO at shouldStartLoadWithRequest so the UIWebview will stay idle. Then, I get the NSURLRequest and get everything I need including HTML source by AFNetworking.
At last, I put HTML string back to UIWebView by loadHTMLString:baseURL:.
User just appear to surf webpage as usual. They don't know I bypass UIWebview and just use UIWebview to display HTML.
In delegate, register your custom NSURLProtocol subclass, then you can monitor responses with:
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
I'm loading certain images from a certain server asynchronously. I'm firing a number of requests at once using NSURLConnection connectionWithRequest method and receive the data using NSURLConnectionDelegate didReceiveData.
At didReceiveData, how do I know which request this data matches? At didReceiveResponse I can use the URL method of the response given as a parameter, but in didReceiveData I only have the received data.
It seemed like the perfect answer would be to use NSURLConnection sendAsynchronousRequest, as the completion handler has all the required parameters: (NSURLResponse*, NSData*, NSError*). I can use [response URL] to make a match to the original request... except in one case: not all the images I try to download exist. In that case, the request is redirected to a generic error page and the URL of that generic page is received, so I can't match the response to a request I've made. This I could handle with connectionWithRequest, but I can't get the best of both worlds.
In
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
you can use
NSURLRequest *request = [connection originalRequest];
to get the request that the connection was started with.
(This method is available since iOS 5.0, but I could not find it in my Xcode iOS 5.1 Library. You find it in the iOS 6 Library, in the header file NSURLConnection.h or here: http://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Classes/NSURLConnection_Class/Reference/Reference.html#//apple_ref/occ/instm/NSURLConnection/originalRequest).
More methods to manage multiple connections can be found in this thread: Managing multiple asynchronous NSURLConnection connections.
If you use sendAsynchronousRequest:queue:completionHandler: then you can just use the request parameter in the completion block.
At connection:didReceiveData: the first parameter is the NSURLConnection instance. So I don't understand where the problem is. You create a connection, then you send a request to that connection and the delegate receive the connection:didReceiveData with the connection value.
If you are using the same delegate for all the request you have to check the connection so you can say which request is associated to.
Perhaps you have to maintain a table of connection/request pairs.
My request is
request_ = [[ASIFormDataRequest requestWithURL:requestUrl] retain];
[request_ setDelegate:self];
[request_ setRequestMethod:#"GET"];
[request_ setTimeOutSeconds:HTTP_TIME_OUT];
[request_ startAsynchronous];
But the response from the server is
HTTP Status 405 - Request method 'GET' not supported. The specified HTTP method is not allowed for the requested resource (Request method 'GET' not supported).
Please note that the url doesn't have any "GET" parameters along with it even though it is a get request. The thing is I am getting the proper response from the server when simply I take the request URL in a browser or when I call it using "HttpRequester"(a Firefox add-on to test http requests - well I'm sure you know that). What could have went wrong?
Thanks in advance.
Balu
For GET requests, use ASIHTTPRequest.
ASIFormDataRequest is for POST requests.
However, if all you need is a simple GET request, why bother with ASI? You can do this in a dispatch_async block:
dispatch_async(<some_queue>, ^{
NSError * error = nil;
NSString * response = [NSString stringWithContentsOfURL: stringWithContentsOfURL: requestUrl error: &error];
[self performSelectorOnMainThread: #selector(processResult:) withObject: response waitUntilDone: NO];
});
Solved it. It was because of the absence of the header parameter "Accept" in requests that have been made. Once it was added, everything worked like a charm.
Also replaced ASIFormDataRequest with ASIHTTPRequest(that one was a silly mistake).
Seems it is a server side issue. Please verify if all the header parameters as required by the server are there in request.
why you create a ASIFormDataRequest aka POSTRequest and set the RequestMethod to GET?
If you want to make a GET Request use ASIHTTPRequest instead.