Question

What is the difference between using:

 $.ajax({
  type: 'POST',
  url: Drupal.settings.basePath + 'module/get/' + node,
  dataType: 'json',
  data: { 'ajax' : true }
 });

versus:

 $.ajax({
  type: 'POST',
  url: Drupal.settings.basePath + 'module/get',
  dataType: 'json',
  data: { 'ajax' : true, 'node' : node }
 });

In the first case you'd access the node variable as a parameter in the callback function and in the second case you'd access it with $_POST['node'] right? Wouldn't the second method always be better, but I see a lot of people doing it the first way. Not to say that the second way is that secure either. Still looking into form tokens, but trying to figure out this basic bit first.

Also wondering for case 1, assuming this ajax is triggered by a button, how do you stop a person from entering directly into the url, mysite/module/get/20 and activating it? Does simply checking that $_POST['ajax'] == true do that? Or is there still a security hole there?

Was it helpful?

Solution

No real difference at first sight:

Assuming that your 'node' variable is just a node id, there is not much difference between the two. Semantically, both seem to perform a 'get' operation (even though they are technically post requests), as they just retrieve data without changing any state on the server (ok, that's another assumption).

Security wise, there is no relevant difference either - both can be 'forged' easily and the difference boils down to the same as with the 'standard' GET vs. POST debate, that is, no difference except that the first exposes the parameters a wee bit more 'accessible' to the casual observer, as they are in plain sight within the URL.

But a 'convenience' difference within Drupal:

Within Drupal, the first version is often encountered because it can make use of the Wildcard Loader Arguments functionality (introduced in Drupal 6). Let's say your callback URL is defined in hook_menu like so:

$items['module/get/%node'] = array(
'title' => 'Foo',
'type' => MENU_CALLBACK,
'page callback' => 'yourModule_callback',
'page arguments' => array(2),
);

With this, yourModule_callback() will be called with its first parameter already being the fully loaded node obect for the passed in nid, as %node tells Drupal to execute a node_load() on the parameter before handing it over to the callback function. Using the second version of your example, the callback function would have to load the node object itself, after extracting it from the POST data.

So a convenience thing here.

Additionally, a common pattern within Drupal is to use the same callback URL for an AJAX request as for its non javascript 'fallback' alternative. So when yourModule_callback() is invoked, it can do whatever it is intended to do with the passed in node first, basically assembling its result. After that is done, it only checks for $ajax == TRUE within the POST data. If it is there, it knows that the result is intended for an AJAX request, so it might output the result as a JSON. If it is not there, it knows that a full page cycle is going on, and can adjust its output accordingly (e.g. rebuilding a form, regenerating a whole page, whatever ...).

That way, you don't have to register separate URLs for your non AJAX/AJAX callbacks.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow