Not getting JSON response using content-type appli

2020-06-30 04:13发布

问题:

I have been provided with a REST service from my customer for which I should get JSON response for my iOS code.I am using content-type as "application/json" but somehow it is taken as "text/html" by default. I cross checked this in a REST client in my Mozilla browser using "application/json" for the content-type in header section and I could see the proper response.On using the below code, I am getting a 400 error from the server. I could always see "text/html" as being used as part of the 400 response by default

NSString * strBodyOnlineStart = [NSString stringWithFormat:@"&email=***@***.com&deviceCode=*****&password_value=***"];

      NSURL *urlOnlineStart = [NSURL
                          URLWithString:@"http://local.server/xxxxx"];
        NSMutableURLRequest *requestOnlineStart = [NSMutableURLRequest
                                                   requestWithURL:urlOnlineStart];


        [requestOnlineStart setValue:@"application/json" forHTTPHeaderField:@"Accept"];
        [requestOnlineStart setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];

        [requestOnlineStart setHTTPMethod:@"POST"];
        NSData *requestBodyOnlineStart = [strBodyOnlineStart
                                          dataUsingEncoding:NSUTF8StringEncoding];
        [requestOnlineStart setHTTPBody:requestBodyOnlineStart];

回答1:

I have built many server REST services and many mobile client apps to access them and run into issues like this countless times. So I know your pain, and I've solved these problems with my own set of tools (I like Fiddler on Windows and Charles on Mac) and learned many reasons for failures.

First observation:

Without the full details of a working request & response pair, and a failing request & response pair, finding the official solution isn't possible. But I'm pretty sure if you provided those, the official solution would be simple.

Testing

To test your problem, I installed REST client in Firefox and setup a new service on my development machine. Also, I used Charles Proxy on OS X with the edit request function to customize a raw request.

I cross checked this in a REST client in my Mozilla browser using "application/json" for the content-type in header section and I could see the proper response.

Odd that you say it worked. I tried that and the server failed to parse the body values. The server-side platform I'm using isn't ASP.NET, yet I'm just going on the standard expected behaviour of any platform. Possibly your REST client was not actually submitting the header. I wonder if you switched the header to some arbitrary value like application/notjson and see if it works still (then I'd assume it was the REST client overriding).

Probable cause

As given in the quote above, you give the impression of wanting to receive application/json in the response Content-Type header, and it seems you think you must send the Content-Type header in the request to match that response. That should not be necessary. The server should be able to receive your request in a standard format as application/x-www-form-urlencoded, that is typical of servers, and respond with JSON as you're expecting.

Usually, web servers do not naturally accept json as a request body format, and similarly, they usually do not receive incoming request Content-Type of application/json. But, I've seen cases where they do.

In any case, submitting a request with conflicting Content-Type and body formats is definitely a failing setup.

I found my server test responding with JSON, using your &email=***@***.com&deviceCode=*****&password_value=*** body, after switching the header to application/x-www-form-urlencoded, application/json. Typical goodness.

Code

Try commenting-out the following line:

    [requestOnlineStart setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];

or change it to:

    [requestOnlineStart setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];


回答2:

Let's try (see my comment):

// replace strBodyOnlineStart NSDictionary
// NSString * strBodyOnlineStart = [NSString stringWithFormat:@"&email=***@***.com&deviceCode=*****&password_value=***"];
NSDictionary *requestObj = @{
                             @"email":  your email,
                             @"passwordValue": your password,
                             };

// Can you try jsonRequest with NSJSONSerialization framework (iOS framework default).
NSData *jsonRequest = [NSJSONSerialization dataWithJSONObject:strBodyOnlineStart options:0 error:&error];

// your url has "/" value at the end or not???
NSString *url = @"http://local.server/xxxxx/";
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:url]];
[request setHTTPMethod:@"POST"];
[request setHTTPBody:jsonRequest];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];

//try set value like this
[request setValue:[NSString stringWithFormat:@"%d", [jsonRequest length]] forHTTPHeaderField:@"Content-Length"];

// Hope this format helps you.