S R Nayak S R Nayak - 4 months ago 28
JSON Question

JSON data is not coming in response Headers in iOS

I am using

CocoaHTTPServer
for my server connection. In my html page (web client) have some JSON data, but when I am getting response I am not getting the JSON data in header file.

Below is my code :

HTML Page :

endAPSession: function (success, fail) {
this.endApSessionIssued = true;
console.log('endAPSession.');
this.proxyAjax({
url: 'http://192.168.123.1/stw-cgi-rest/network/wifi/connect',
username: this.username,
password: this.password,
method: 'PUT',
data: JSON.stringify(data),
contentType: 'application/json'
})
.done( function ( data, textStatus, jqXHR ) {
device.endApSessionIssued = false;
console.log("endAPSession success:", arguments);
return success(jqXHR);
})
.fail( function ( jqXHR, textStatus, errorThrown ) {
device.endApSessionIssued = false;
console.log("endAPSession fail:", jqXHR);
return fail(jqXHR);
})
},

var data = {
SSID: network.name,
Password: password,
SecurityMode: network.security
};


I am adding this Headers :

-(void) addHeaders:(HTTPMessage *)response {
[response setHeaderField:@"Access-Control-Allow-Origin" value:@"*"];
[response setHeaderField:@"Access-Control-Allow-Headers" value:@"accept,x-forwarded-url, authorization, content-type,username,password, camera-data"];
[response setHeaderField:@"Access-Control-Allow-Methods" value:@"HEAD,GET,PUT,DELETE,OPTIONS,POST"];
[response setHeaderField:@"Access-Control-Max-Age" value:@"86400"];
[response setHeaderField:@"Access-Control-Expose-Headers" value:@"content-type, content-length, connection, date, server, x-www-authenticate"];
}


I am getting below Response :

Accept = "*/*";
"Accept-Encoding" = "gzip, deflate";
"Accept-Language" = "en-us";
Authorization = "Digest username=\"admin\",realm=\"iPolis\",nonce=\"2f65566a6c6239a1358732f8bfe08909\",uri=\"/stw-cgi-rest/network/wifi/connect\",qop=auth,nc=00000001,cnonce=\"7007d989\",response=\"dae876901c002f20b3baa100580a1634\"";
Connection = "keep-alive";
"Content-Length" = 63;
"Content-Type" = "application/json";
Host = "127.0.0.1:8090";
Origin = "http://localhost:8090";
Referer = "http://localhost:8090/";
"User-Agent" = "Mozilla/5.0 (iPhone; CPU iPhone OS 9_3_2 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Mobile/13F69";
password = "";
username = admin;
"x-forwarded-url" = "http://192.168.123.1/stw-cgi-rest/network/wifi/connect";


Here I am not getting the JSON response. Here
Content-Length
is coming 63. It means data is there. But its not coming.

JSON should be like this :

"camera-data" = "{\"SSID\":\"HomeNetwork\",\"Password\":\"1234567\",\"SecurityMode\":\"PSK\"}";


If I am adding below code in my html page the above JSON is coming in my response, but I don't want to change my HTML page.

if(proxyOpts.data != null) {
proxyOpts.headers['camera-data'] = proxyOpts.data;
}


So please guide me how can I get JSON in response header ? How can I get
camera-data
in my response.

Answer

To summarize, to be sure I'm getting this correctly, you have a web client containing some HTML & JavaScript code. Using this JavaScript code, you're sending a request to a web server you're hosting with CocoaHTTPServer. Within this request, you're sending JSON data with data: JSON.stringify(data). You want to get and use this data on the server side. Is that correct ?

If that's correct, on the server side, you'll have a custom subclass of HTTPConnection for all incoming connections within CocoaHTTPServer:

[httpServer setConnectionClass:[YourConnectionClass class]];

Then, you'll have in this subclass your custom implementation of (NSObject<HTTPResponse> *)httpResponseForMethod:(NSString *)method URI:(NSString *)path. This method will be called to get a response for every requests. In this method, you'll be able to check for example if the method of the request is PUT like you specified in your JavaScript code, to get the body of your request which contains your data, etc.

- (NSObject<HTTPResponse> *)httpResponseForMethod:(NSString *)method URI:(NSString *)path {
    // Check if the method is PUT.
    if ([method isEqual:@"PUT"]) {
        // Get the data sent in this request.
        NSData *requestData = [request body];

        // Transform the data into usable JSON.
        NSError *error;
        NSDictionary *jsonData = [NSJSONSerialization JSONObjectWithData:requestData options:kNilOptions error:&error];

        // At this point, you have your json data send in the request, you can do anything with it.
        // ...
        // ...
    } 

    // ...
    // Return a proper response depending on the request.
    // ...
}

You also need to be sure to allow the different methods you'll be using, PUT obviously and OPTIONS to avoid CORS issues.

- (BOOL)supportsMethod:(NSString *)method atPath:(NSString *)path
{
  if ([method isEqualToString:@"PUT"])
    return YES;

  if ([method isEqualToString:@"OPTIONS"])
    return YES;

  return [super supportsMethod:method atPath:path];
}

Since the PUT method send data, we also need to handle this data on the server-side too using the processBodyData method which by default is empty and needs to be overridden.

- (void)processBodyData:(NSData *)postDataChunk
{
    [request appendData:postDataChunk];
}

With these 3 methods in my HTTPConnection subclass, I can use a similar JavaScript code to the one in the question:

var data = { name: "HiDeo", location: "Internet", other: "test" };

$( document ).ready(function() {
 $.ajax({
   method: "PUT",
   url: "http://localhost:12345/",
   data: data,
   username: "testUsername",
   password: "testPassword",
   data: JSON.stringify(data),
   contentType: 'application/json'
 })
 .done(function( msg ) {
   console.log(msg)
 });

});

If I NSLog(jsonData); on the server-side, I'll get the following output:

{
    location = Internet;
    name = HiDeo;
    other = test;
}