0

I have a form set up that will take some input from the user and post it to a URL via jQuery's .ajax() function. The URL is on a separate sub-domain but I have set up CORS and everything that side is working fine.

What happens server side is the form is validated and, if an error is detected (error as in the form is completed incorrectly), I pass back the following JSON:

{"success": "false", "error": "Whatever the error is"}

This is working for me so I know the general set up is correct.

When the form is valid I perform a database query to retrieve the details of a bunch of files, receive this as an array, and pass all this back as JSON along with a success message. The JSON for this scenario is along the lines of:

{"success": "true", "files": [{"id":"4","file_name":"data_zones_scotland_2001.csv","nice_name":"Data Zone - Scotland","description":"","type":"1","coverage":"Scotland","distribution":"public","pack_type":"LSOAs, MSOAs, Data Zones, Intermediate Zones","link":"https:\/\/s3-eu-west-1.amazonaws.com\/data_zones_scotland_2001.csv?Expires=1396528176&Signature=V8ojfXhoH5eggIjwix265KGbr0M%3D"},{"id":"8","file_name":"intermediate_zones_scotland_2001.csv","nice_name":"Intermediate Zone - Scotland","description":"","type":"1","coverage":"Scotland","distribution":"public","pack_type":"LSOAs, MSOAs, Data Zones, Intermediate Zones","link":"https:\/\/s3-eu-west-1.amazonaws.com\/intermediate_zones_scotland_2001.csv?Expires=1396528176&Signature=ieaZYnZCz%2BpnJmWLeq5ygpJ9zNM%3D"}]}

Apologies for the long string but I wanted to get it all in there in case I missed something.

The problem I'm having is when I pass this back, I get a No 'Access-Control-Allow-Origin' header is present on the requested resource error. I know this to not be the case and I have tested the headers are set using curl -i http://url.... Taking out the files array and just returning {"success": "true"} works fine which suggests to me that the JSON within the files array is malformed, however passing that string through JSONLint tells me that the JSON is valid.

I'm running out of ideas as to where to turn to next as everything I am doing appears to be correct. The jQuery code handling the POST is as follows:

$.ajax({
    url: "http://domain.com/api/download-request",
    type: "POST",
    data: postData,
    dataType: 'json'
})
.done( function(data){
    console.log(data);
}); 

I'd appreciate any clues as to where to turn to next.

* UPDATE * In an attempt to solve this, I started by filtering the data received from the database, thinking there was something in a string that was breaking the output. I got to a point where I seemed to have narrowed it down to a specific record by limiting the amount of records returned until it broke. After retrieving just this record though it worked again. I persevered and then noticed that the error would generate when the JSON string hit a certain length (around 600 characters).

I've been into the php.ini to try and find a limit in there and once I increased the size of the output_buffering from 4096 to 8192 (doubled) the entire thing started working. I should mention that the output from the DB was without the URLs, considerably shortening the string length, so once I added these back in the application broke again until I increased the the buffer to 16384 (double again).

Now the application works but this is clearly not the best way of doing things. Is there a way that I can manage to output_buffering dynamically or change the way the echo is working so that PHP doesn't run out of buffer?

Matt Asbury
  • 5,644
  • 2
  • 21
  • 29
  • Sounds like a cross domain ajax call issue. Try setting the `Access-Control-Allow-Origin` header in your php file that writes the JSON. Personally, to determine whether if something went wrong with an ajax call, I set different status code. 4XX and 5XX codes makes you end up in the `error`/`fail` callback in your `$.ajax` call. – Johan Apr 03 '14 at 11:45
  • In case of success, you return a piece of Json that includes a full url. I suspect the problem is not in receiving and parsing this Json, but in getting the actual file, because it is on a different domain. – GolezTrol Apr 03 '14 at 11:47
  • Thanks @Johan but the `Access-Control-Allow-Origin` headers are set there already and everything goes through ok as long as I don't return the files array within the JSON. – Matt Asbury Apr 03 '14 at 11:49
  • @MattAsbury Have you tried `crossDomain: true` as an ajax option? – Johan Apr 03 '14 at 11:49
  • @Johan I've just tried it and it came back with the same error. – Matt Asbury Apr 03 '14 at 11:51
  • Another idea is to urlencode the urls in your property values. – Johan Apr 03 '14 at 11:52
  • @GolezTrol could you expand on that a little please? I'm not returning the actual files themselves, just a URL to the file. The intention eventually is to output the link to the page, not to force a download or anything. – Matt Asbury Apr 03 '14 at 11:52
  • @Johan just tried that as well, same error. – Matt Asbury Apr 03 '14 at 11:55

2 Answers2

0

Use JsonP instead of json.

$.ajax({
 url:"testserver.php",
 dataType: 'jsonp', // Notice! JSONP <-- P (lowercase)
 success:function(json){
     // do stuff with json (in this case an array)
     alert("Success");
 },
 error:function(){
     alert("Error");
 }      
});

At the same time you may need to wrap the data with a callback function, just to represent jsonp data. check this link for more info on how to do so:allow cross domain ajax requests

REF:

Happy Coding :)

Community
  • 1
  • 1
dreamweiver
  • 6,002
  • 2
  • 24
  • 39
  • His server is returning a JSON string, not wrapped in a function. Thus, `jsonp` won't help. Also, he can comminucate with the server just fine, so there is no need to change the type. – Johan Apr 03 '14 at 11:57
  • I was also under the impression that jsonp and POST were not compatible? – Matt Asbury Apr 03 '14 at 11:59
  • @Johan: Over a cross domain, you really cant communicate with server with json data, you need to use jsonp type data transfer.to enable cross domain access on the server, there are couple of things, like enabling headers like `header('Access-Control-Allow-Origin: *'); header('Access-Control-Allow-Methods: GET, POST');` and also in need to wrap the return data with a callback. – dreamweiver Apr 03 '14 at 12:02
  • @MattAsbury: yes its not same.jsonp actually contains a callback function compared to normal json data. – dreamweiver Apr 03 '14 at 12:05
  • 1
    Well, OP can pass smaller objects just fine. So even though the error sounds like a CORS issue, it sounds to me like the problem lies elsewhere. – Johan Apr 03 '14 at 12:07
0

The issue was the output buffer becoming full. Increasing the size of the buffer or turning the buffer off solved this problem.

Matt Asbury
  • 5,644
  • 2
  • 21
  • 29