NSMutableURLRequest with parameter - cannot parse response
I am trying to create a URL connection that outputs JSON code which is then parsed and processed. My url has a parameter bypass
. The url looks like this:
http://www.getchanged.net/json.asp?bypass=MIGCBgkrBgEEAYI3WAOxxx
I was unable to resolve this issue as it always says Connection failed with error: cannot parse response
NSURL *aUrl = [NSURL URLWithString:@"http://www.getchanged.net/json.asp"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:aUrl cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
[request setHTTPMethod:@"GET"];
NSString *postString = @"bypass=MIGCBgkrBgEEAYI3WAOxxx";
[request setHTTPBody:[postString dataUsingEncoding:NSUTF8StringEncoding]];
Mistake:
2014-10-29 21:43:39.529 TestMap[57987:1931535] Connection failed with error: cannot parse response
What's wrong here?
Please note: I have replaced the bypass bypass because it contains reasonable data. The website runs and prints out the JSON output.
source to share
Apart from the question well covered by Rob, returning JSON from said site does not confirm:
I've tried multiple validators with url and traversal hash (you posted comments) and the JSON is not valid. Typical error:
JSON Content: Invalid JSON at line 26, column 84
Parse error on line 26:
...rtragen", "adresse":"fairtragen - GmbH
-----------------------^
Expecting 'STRING', 'NUMBER', 'NULL', 'TRUE', 'FALSE', '{', '[', got 'undefined'
As explained in json.org any string value can contain
any UNICODE character except "or \ or a control character
So the string value has the following structure:
Note the escape format required for newlines and carriage returns.
With that in mind, and looking at the original output from Charles , you can see that line 26, column 84 contains an x0d
followed by an x0a
(i.e. the old CRLF window style) in the middle of the value.
The server MUST avoid these values ββbefore sending them.
By the way, JSON has a lot of spaces (x 20
) and CRLF outside, outside the array, objects and values ββthat, without affecting JSON, are unnecessary and do not offload data transfer.
source to share
A few observations:
-
The key issue is that you are submitting a request
GET
but providing a parameterbypass
in the body of the request. For requests,POST
parameters must be added to the body, but for requests,GET
it must be added to the url. -
If this key
bypass
may contain reserved characters (eg, spaces&
,+
etc.), you want to interest code has been lost, t21>. If you're guaranteed to be alphanumeric only, you can get away with no percentages by avoiding it, but as a general rule, you should always avoid HTTP parameters. -
While point # 1 is likely to fix this problem, sometimes web services expect certain header fields to be set. For example, the
Content-Type
request header is usually set (for example, it looks like this: thereContent-Type
must be a requestapplication/x-www-form-urlencoded
). -
You say you are getting the error message: "Connection failed with error: Unable to parse response." You didn't show us the code that generates this error, but I'm guessing it was generated when your code tried to parse the response as JSON when it wasn't.
In the future, when diagnosing these problems, I find it helpful to analyze the details of the answer. Notably, the response header will be contained in
NSURLResponse
(which actually will beNSHTTPURLResponse
, which has a numerical valuestatusCode
that can be very illuminated). The response body will often be the string representation of the error (often, when the web service fails, it generates a text or HTML description of the error).Whenever you get errors like this in the future, always look at
statusCode
and the text of what the server was returning, as this will help you determine what is going on. It will be more informative than the general message "I can't make out the answer". -
If you have a web interface that works and an application interface that doesn't, it is sometimes useful to use a tool like Charles to observe the request generated by the web browser and compare it to the request generated by the application. This can be invaluable in diagnosing problems like this.
Also, if you are using something like Charles, it allows you to manually check the status code and textual response of the server, which I assumed you could access programmatically in point 4.
source to share
Change the request HTTPMethod
to POST
, everything will be fine.
@property (copy) NSData * HTTPBody;
@discussion This data is sent as the message body of the request, as
in done in an HTTP POST request.
You can also use GET
this way, set the whole url as the request url and don't set the HTTPBody.
NSString *urlAsString = @"http://www.getchanged.net/json.asp";
urlAsString = [urlAsString stringByAppendingString:@"?bypass=MIGCBgkrBgEEAYI3WAOxxx"];
NSURL *aUrl = [NSURL URLWithString:urlAsString];
This site has confirmed that this is a valid JSON string, however it does "\r\n"
, this code seems to be able to fix the problem by removing "\r\n"
from the string.
NSString* receivedString = [[NSString alloc] initWithData:receivedData encoding:NSASCIIStringEncoding];
receivedString = [receivedString stringByReplacingOccurrencesOfString:@"\r\n" withString:@""];
NSData *data = [receivedString dataUsingEncoding:NSUTF8StringEncoding];
id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
source to share
I think this is what you want:
NSString * bypassId = @"MIGCBgkrBgEEAYI3WAOxxx";
NSURL *aUrl = [NSURL URLWithString:[NSString stringWithFormat:@"http://www.getchanged.net/json.asp?bypass=%@",bypassId]];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:aUrl cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
[[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSString *jsonAsString = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
NSLog(@"string: %@",jsonAsString);
NSDictionary *jsonAsObject = [NSJSONSerialization JSONObjectWithData:data options: NSJSONReadingMutableContainers error: nil];
NSLog(@"dict: %@",jsonAsObject);
}] resume];
This outputs (in the console):
2014-11-06 17:09:21.659 ] string:
{"stores":[
]}
2014-11-06 17:09:21.659 ] dict: {
stores = (
);
}
I am printing data as json string and dictionary because I'm not really sure what you want.
source to share
The following works great:
NSURL *aUrl = [NSURL URLWithString:@"http://www.getchanged.net/json.asp?bypass=MIGCBgkrBgEEAYI3WAOxxx"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:aUrl cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
[request setHTTPMethod:@"GET"];
NSURLResponse *response = nil;
NSError *error = nil;
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
if (!error) {
NSLog(@"Response String : %@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSLog(@"Parsed Data : %@", json);
}
But it may be that, as you mentioned in your note, the hash bypass is changed to hide your sane data, that data might have some special characters or invalid JSON that doesn't do your JSON parsing. If you don't want to share this data, you can edit the original answer with dummy data (do not replace special characters) and share it, which will help everyone debug more.
source to share