Hi I want to read from a server the whole html not only the request like
"HTTP/1.1 200 OK"
I mean the html code too.
But I dont know how.
I am using the Asyncsocket library from "https://github.com/roustem/AsyncSocket"
have someone an idea how can i handle this?
i used the funktion
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
but the data is to short and show me only the http request.
Thanks
I would guess that you are calling readDataToData:timeout:tag: using CRLF as the delimiter. That will return you one line of data. What you want is to read enough headers to tell how long the response data ought to be and then call readDataToLength:timeout:tag:, or else wait for the connection to be closed and call unreadData to get everything the server sent up to when it closed the connection.
The HTTP spec describes how to determine the length of the message: https://www.rfc-editor.org/rfc/rfc2616#section-4.4
A better answer might be to use NSURLConnection to make the request and interpret the response for you.
Related
I am working on iOS application and facing one strange issue. I am using AFNetworking framework to communicate with server (HTTPS communication). I am retrieving student data from server by using "getStudentData" web service API. It is post request. It works for all user ids except one. It fails when we have a data for more than 450 students. Below are the error details,
Error Domain=NSURLErrorDomain Code=-1017 "cannot parse response" UserInfo=0x7bf9c7d0 {NSErrorFailingURLStringKey=https://www.fdmobileservices.com/mAccountsWeb/services/speedpass/rpc, _kCFStreamErrorCodeKey=-1, NSErrorFailingURLKey=https://www.fdmobileservices.com/mAccountsWeb/services/speedpass/rpc, NSLocalizedDescription=cannot parse response, _kCFStreamErrorDomainKey=4, NSUnderlyingError=0x7bf9a380 "cannot parse response"}
As per error description, It tells "Could Not parse", so I think it may be due to server is returning "nil" or some data other than JSON format.
But I am not able to trace it since from application side it directly goes into below method,
- (void)connection:(NSURLConnection __unused *)connection
didFailWithError:(NSError *)error
Is there any way from application side to trace root cause? This method works for other user login except one.
I tried using web client to access this service by same user login, it works well and return data of 450 students. I think due to some reason iOS network layer rejects this. I am trying to find out.
Thanks in advance.
As you can see here, kCFURLErrorCannotParseResponse = -1017. So probably this is saying that there is something wrong in the parameters.
If You're using AFNetworking 2.0, I suggest You to deep debug your response flow with severals breakpoints.
Specifically try to set a breakpoint on AFURLResponseSerialization.m at the start of the method:
- (id)responseObjectForResponse:(NSURLResponse *)response
data:(NSData *)data
error:(NSError *__autoreleasing *)error;
Inside the method, if the below condition is true, probably there is something wrong (but you can step into validateResponse:data:error: to better understand what's wrong):
if (![self validateResponse:(NSHTTPURLResponse *)response data:data error:error])
If the above condition is false you can then check about the generated responseString:
NSString *responseString = [[NSString alloc] initWithData:data encoding:stringEncoding];
If you're expecting json data, check that responseString is not nil and data data is valid, maybe also the stringEncoding.
Also ensure that the contentType that you're receiving is the one you're expecting.
net web service that returns true or false but i don't know how to catch that response in my IOS App.
My service updates data in a database and i know it works the data gets updated it's catch the response that is the problem, i like to know so i can tell the user if something went wrong.
For those of you that know c# its a bool method, just simple try catch and return true or false.
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
//What to write here to catch my true or false
if(response) {
//true
} else {
//false
}
}
Thank you for your help
You should implementconnection:didReceiveData: to get and save NSData and – connectionDidFinishLoading: where you can interpret received data as BOOL.
basically didReceiveResponse: only get to you know about server response to your request not the entire answer.
You should check the response's HTTP status code, e.g.:
NSInteger statusCode = [(NSHTTPURLResponse*)response statusCode];
The status code for a successful request uses the range [200..299].
For example a successful GET request would be indicated with a 200 (OK).
A successful POST request will be indicated with a 201 (Created).
A successful DELET request will be indicated with a 204 (No Content)..
See also: wiki List of HTTP status codes.
Furthermore, you need to check the kind of data the server sent to you:
NSString* mimeType = [response MIMEType];
The mime type has been sent by the server in the Content-Type header of the response.
See also wiki MIME Internet Media Type
What you actually get fully depends on your request AND the server.
For example, the server may always answer with a JSON as content type. In this case, the header Content-Type of the response would be application/json. The actual JSON which represents the answer, will be related to the status code as well.
In order to provide a nice human readable message to the user, you need to consult the web service API and figure out how it is specified. Certain web service APIs may have a considerable large API. Unfortunately, some web services lack a comprehensive documentation.
I'm working with an API that sends back HTTP 406's for many different errors, along with a custom message (reason phrase). It may look something like:
406 Not Acceptable: User is already logged in
406 Not Acceptable: Missing password field
406 Not Acceptable: Node does not exist.
I can get the 406 status code and the standard "Not Acceptable" string using:
NSHTTPURLResponse *HTTPResponse = (NSHTTPURLResponse *)response;
NSInteger statusCode = [HTTPResponse statusCode];
[NSHTTPURLResponse localizedStringForStatusCode:HTTPResponse.statusCode];
However I really require the reason phrase message to know how to handle the response. How can I get it, preferably using the standard iOS SDK?
I really require the reason phrase message to know how to handle the response.
Then the API is broken. The reason phrase is a debugging aid only. It's not meant to inform client behaviour.
From RFC 2616 § 6.1.1:
The Status-Code is intended for use by automata and the Reason-Phrase is intended for the human user. The client is not required to examine or display the Reason- Phrase.
If there is information about the response that cannot be conveyed by the status code alone, the proper place for it is as a header or in the response body. The reason phrase is not a correct place to put information necessary for a client to use.
Status code 406 means that the server cannot respond with the accept-header specified in the request.
406 Not Acceptable The requested resource is only capable of generating content not acceptable according to the Accept headers sent in the request.
These error codes are not iOS-specific. If you want to display different messages based on different occurrence reasons, I suppose you should check it with your API/web server, and use conditions in your code to display your custom messages for each of them.
Ultimately, you can get the reason phrase using the ASIHTTPRequest library.
http://allseeing-i.com/ASIHTTPRequest/
It was just as simple to use in my case as AFNetworking and NSURLSession.
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.
How to delete UIWebView cache only if necessary, e.g. when response status code is 304? I use:
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
from NSURLConnectionDelegate to get status code from the response:
int code = [(NSHTTPURLResponse*)response statusCode];
But the code is always 200 (OK). How to get code 304 (not changed) to know when I need to clear cache?
Thanks in advance.
How to get code 304.but code is always 200 (OK)
I don't understand your question - it is the server that sends http codes, are you asking how to change the server so that it sends 304?
Regardless of that, what is the connection between your UIWebView and the NSURLConnection.
Are you using a NSURLConnection inside of shouldStartLoadWithRequest: for some reason?