Download & Extend

Ensure it is possible to use AJAX with GET requests

Project:Drupal core
Version:8.x-dev
Component:ajax system
Category:task
Priority:major
Assigned:Unassigned
Status:needs work
Issue tags:Ajax, API addition, Performance

Issue Summary

Problem summary

  • AJAX request size is very large. Out of the box in Drupal core it can be around 5k, on a reasonable site build using some contrib modules I have seen 15k+ HTTP requests. The size of the request is directly related to the number of DOM elements with id attributes on a given page and the original number of css/javascript files for the page (ie, css/js aggregation has no effect).
  • Problem #1: AJAX framework cannot be used with HTTP GET as such a large HTTP request payload requires POST to handle such a large request body. Trying to use GET quickly fails due to URL length limits.
  • Problem #2: This is a performance issue. As described here minimizing HTTP request size is good practice for high performance, and HTTP request sizes are generally talked about in terms of bytes, not kilobytes.

Why is the AJAX request so large?

The changes introduced by #561858: [Tests added] Fix drupal_add_js() and drupal_add_css() to work for AJAX requests too by adding lazy-load to AJAX framework added some killer functionality to the AJAX framework. Unfortunately, it also greatly increasing the size of requests made by the browser back to Drupal.

Currently every AJAX request made back to Drupal contains two pieces of information that can be very large on even a simple Drupal site and are likely to grow very quickly as additional modules and site building is done:

  1. ajax_html_ids is an array of every HTML element's id attribute collected by ajax.js before making the HTTP request. These are used by drupal_html_id() to ensure that when the AJAX response is delivered it contains unique HTML ids and not ones that may conflict with existing ids in the DOM.

  2. ajax_page_state, amongst other things, contains two large arrays -- a full set of css file paths and js file paths that were served with the original page. These are used in ajax_render() to ensure that only new css/js assets are delivered with the AJAX response and not force a client-side reload of every css/js asset. Note that the size of this list is not mitigated by css/js aggregation -- it is intentionally a list of "original" assets even if the page is using an aggregated css or js file.

I ran into this issue when updating Views (see #591302: Rewrite ajax_view.js based on ctools AJAX) and attempting to use HTTP GET with the AJAX framework.

Possible solution

Drop ajax_html_ids and full list of css/js files in ajax_page_state from AJAX requests:

  • Switch drupal_html_id() from using integer increments to a randomized short hash. Makes collision between requests extremely unlikely and drops the need for ajax_html_ids in the request.
  • Generate a page state css hash and js hash for any given array of css/js files. Store it in the cache table. Transfer this in ajax_page_state instead of the full list of CSS/JS files, e.g.

    ajax_page_state.css = 'fj519x9029120x ...'; // Some real hash
    ajax_page_state.js = '9810b0za121jkl ...';  // Some real hash

    Upon receiving an AJAX request, use cached list of css/js files looked up by page state hashes. Eliminates the need for client to send the list of css/js files back to Drupal.

This plan is implemented in the attached patch.

Some numbers

HTTP POST for the <create new book> dropdown on node/add/article

  • D7 HEAD: 6156 bytes
  • With patch: 1003 bytes

HTTP GET using Views AJAX pager on test_view

  • D7 HEAD: 4399 bytes
  • With patch: 421 bytes

Comments

#1

Status:active» needs review
AttachmentSizeStatusTest resultOperations
956186.1.patch22.39 KBIdleFAILED: [[SimpleTest]]: [MySQL] 26,712 pass(es), 3 fail(s), and 0 exception(es).View details | Re-test

#2

Thanks for the work on this. Subscribing, and intend to review next week.

Note that while #561858: [Tests added] Fix drupal_add_js() and drupal_add_css() to work for AJAX requests too by adding lazy-load to AJAX framework introduced the ajax_page_state variables, it was #384992: drupal_html_id does not work correctly in AJAX context with multiple forms on page that originally introduced the ajax_html_ids variables, and that alone prevents using a GET request for AJAX. Also note that ajax.js never supported GET requests out of the box. But all that aside, I agree there's value to reducing the payload both for performance, and to enable contrib to change some AJAX requests from POST to GET if it wants to.

#3

Status:needs review» needs work

The last submitted patch, 956186.1.patch, failed testing.

#4

Status:needs work» needs review

Sub - without HTTP GET AJAX no reverse proxy caching for ajax pagers.

#5

Status:needs review» needs work

Thanks for the good work on this. Subscribing.

#6

Status:needs work» needs review

Updated patch fixes HTML ID test.

AttachmentSizeStatusTest resultOperations
956186.6.patch23.7 KBIdlePASSED: [[SimpleTest]]: [MySQL] 26,750 pass(es).View details | Re-test

#7

Title:Reduce HTTP request size for requests made by AJAX framework» Ensure it is possible for a contrib module to alter AJAXified links to use GET requests
Category:bug report» task
Priority:normal» critical

Sorry I haven't had time to review #6 yet. I would still like to at some point, but RC1 is approaching fast, and I don't know if I'll be able to give this the attention it deserves before then.

My gut feeling is that #6 is too much for D7 core at this late hour. I'm open to being overruled on this though, so I'm leaving it at "needs review".

But, I do think it is critical that a contrib solution be possible. I suspect it already is, between hook_ajax_render_alter(), the ability for JS functions to be overridden, drupal_html_id() using a drupal_static() that can be hacked into from another function, and PHP allowing $_POST to be written to even if it's a GET request. But, it would be great if people familiar with the inner workings of the ajax system could double check the internals to verify that nothing in the system is so hard-coded as to make such a contrib module impossible. @yhahn: if you have time to try your approach out as a contrib module, that would be awesome.

Once we're confident that such a contrib module is possible without hacking core, I think ctools would be the right home for the implementation, and for this issue to move to.

The reason I think this is critical is that the web paradigm is shifting from page centricity to application like UIs, and if Drupal doesn't provide a way for high performance AJAX, then cutting edge developers will look to other frameworks. And that would be a shame, since we'd rather that Drupal be the platform that attracts and retains cutting edge developers.

#8

Some ideas I've had in terms of keeping track of what is inside the aggregated css/js files
http://groups.drupal.org/node/53973#comment-279159

#9

I like this feature, however I am not sure if it qualifies as a critical as it may be able to go in a post 7.0 release of core.

if Drupal doesn't provide a way for high performance AJAX, then cutting edge developers will look to other frameworks.

As I understand this bug is for using the Drupal API to make ajax requests, this provides a very tight integration with Drupal. However using it outside of the FAPI is not straightforward (or well documented).

I don't think this bug would stop somone from making standard ajax requests to a custom callack without the overhead. What may be needed (and can be done in contrib), is a fast_ajax delivery method, for times when the drupal ajax stack is not needed for a request.

I don’t claim to be an expert of the Drupal Ajax innards, but have had some experience of trying to use them.

#10

I like this feature, however I am not sure if it qualifies as a critical as it may be able to go in a post 7.0 release of core.

I think you're right. I'm just not 100% positive.

To re-iterate from #7:

But, I do think it is critical that a contrib solution be possible. I suspect it already is, between hook_ajax_render_alter(), the ability for JS functions to be overridden, drupal_html_id() using a drupal_static() that can be hacked into from another function, and PHP allowing $_POST to be written to even if it's a GET request.

...

Once we're confident that such a contrib module is possible without hacking core, I think ctools would be the right home for the implementation, and for this issue to move to.

In other words, my inclination is to move this issue to the ctools queue, and I'll probably do so in a few days barring further comments. I'm leaving it in the core critical queue for now, just to make sure people have a chance to flag any simple core API change that may be required if my assumption above is wrong.

#11

This doesn't need to be a D7 critical as it's a change that can go in with a point release (e.g. 7.1).

That said, I don't think it makes sense to move into contrib as it touches a very important assumption in drupal_html_id() and there is really no way to get the behavior of this function (which is called widely throughout core, Form API, etc.) to change from a contrib module.

#12

Issue tags:+API change

Switch drupal_html_id() from using integer increments to a randomized short hash. Makes collision between requests extremely unlikely and drops the need for ajax_html_ids in the request.
...
Generate a page state css hash and js hash for any given array of css/js files. Store it in the cache table. Transfer this in ajax_page_state instead of the full list of CSS/JS files [...] Upon receiving an AJAX request, use cached list of css/js files looked up by page state hashes. Eliminates the need for client to send the list of css/js files back to Drupal.

I understand and basically agree with the outlined problem. I especially agree with the idea that the AJAX framework currently prevents to implement true REST callbacks, and also kills proxy/reverse-proxy caching, since every request is a HTTP POST.

However, both solution proposals make the system more fragile:

  1. Only the client knows about the actual HTML IDs on the page.

    We still have lots of theme functions and templates that output arbitrary IDs, sadly. Also, third-party/non-Drupal scripts may inject further HTML IDs that are unknown to Drupal. Lastly, even though it's less likely, a random hash can lead to duplicate IDs.

  2. Relying on an additional page state cache means that we'd need another, non-volatile cache like {cache_form}.

    Right now, the entire system has a single defined state only. The actual client/browser holds and defines that state. Drupal only reacts accordingly to that state, which means that we purposively do not try to synchronize the state information between client and server. Exactly that intentionally missing synchronization is what makes this part of the current AJAX framework rock solid.

    When discussing this problem space, then we also need to take into account that the AJAX framework doesn't provide means to remove loaded files currently. While I couldn't believe it myself, I've heard various rumors that there are some contrib projects for D6, which implement a third-party library that actually supports full unloading of JS and CSS files (it's the JS part that baffled me). Given that (not verified) info, I suspect that a contrib module could relatively easily add an AJAX framework command to unload JS/CSS files from the page. Due to the current design, the AJAX framework would simply send those removed files for "reloading" if they happen to be needed in a later request again.

Food for thought.

If all fails, then we should merely make sure that a contributed module is able to replace resp. plug in to the affected functionality without having to hack core.

#13

Is this going to break any existing Drupal 7 theme that happens to theme by an ID? If so, then how is this D7 material?

#14

All theming by HTML ID was already completely and permanently broken by the rework of drupal_html_id() a very long time ago. So that's not a happy thing, but it did happen like 8 months ago, so any theme that uses ID is already up the creek without a paddle.

#15

If I understand what you are saying then a theme created in the last eight months could use IDs because they were last broken eight months ago?

#16

In Drupal (IMO), CSS cannot target IDs at all, as they are unique (and can be volatile). At least IDs that are generated by drupal_html_id(). So every time AJAX generates some new code it comes in with a new ID. If CSS is targeting IDs, #fail.

#17

Well, then what's the point of using IDs, or having the in markup at all?

#18

Title:Ensure it is possible for a contrib module to alter AJAXified links to use GET requests» Ensure it is possible to use AJAX with GET requests

IDs are the fastest way to select elements in JavaScript, so IDs are still helpful for operations like AJAX. It's true Drupal's auto-generated IDs should not be used for theming - for that sake I already discussed with eff some time ago that we should actually make drupal_html_id() generate much shorter and completely random machine IDs, because the current human-readable output sends the wrong signal and makes people believe it is safe to rely on them.

We already changed lots of CSS and also JS code in D7 to no longer target IDs, but CSS classes instead - and to aid facilitating that, CSS classes have been heavily improved, too.

However, the impact of Drupal 7's HTML IDs on themers is not the point here. Regardless of auto-generated, human-readable, cryptic, or not, the AJAX framework must not generate potentially duplicate IDs. Currently, that is ensured by making the client send all known IDs to the server.

The real problem we're facing here is that AJAX always performs POST requests, which auto-disables all kind of built-in caches. In order to appropriately use GET requests, we need to find a way to decrease the HTML ID and page state information that is sent to the server in order to prevent duplicate IDs and lazy-load asset files.

#19

This is an interesting problem.

ajax_html_ids: Following on sun's point 1 in #12, why not have the client generate the hash/salt, check it and send it with the AJAX request?

If I read the documentation correctly, drupal_html_id() generates example--1, example--2, etc. for $id = 'example'. If the client sent $salt = 'qZ6', then the request could return example--qZ6--1, example--qZ6--2 etc. without risk of collision. On the next request, $salt='54k' or something else. Am I missing something?

ajax_page_state: If the original cache idea will not work per sun's point 2, I don't have any good ideas about this. To reduce the size of the payload, maybe convert:

'a/b/c/d1.css', 'a/b/c/d2.css', 'a/b/c/d/e1.css', 'a/b/c/d/e2.css', 'a/b/f/g.css'

into JSON:

{'a/b': {'c': {'d1.css': 0, 'd2.css': 0, 'd': ['e1.css', 'e2.css']}, 'f/g.css': 0}}

…on the face of it this doesn't look like it saves any space, but since real path components are more than one character each, it would. One could also omit ".css" and ".js" or get creative in other ways.

#20

Some quick notes on Sun's comments:

Only the client knows about the actual HTML IDs on the page. We still have lots of theme functions and templates that output arbitrary IDs, sadly. Also, third-party/non-Drupal scripts may inject further HTML IDs that are unknown to Drupal.

This is true but I'm not sure there is anything core can really do about this. If a contrib module chooses not to use drupal_html_id() for the initial page response it's likely it won't be used for the AJAX response, in which case whether the client sends back all the HTML IDs or not makes no difference. Basically, if you aren't using the core AJAX framework you're on your own (with or without this patch).

Relying on an additional page state cache means that we'd need another, non-volatile cache like {cache_form}.

Yes. A cache for looking up sets of JS/CSS files via hash would be equivalent/similar in many ways to {cache_form}. If we were to establish such a cache I would not be very concerned about fragility - if the site successfully sent the page then it will be able successfully respond via AJAX for that page.

It would be nice to see some discussion on this issue around the actual patch as it does let you test these assertions and behaviors against a real site : )

#21

Priority:critical» major
Issue tags:-API change

I re-read through all the AJAX code related to ajax_html_ids and ajax_page_state, and I agree with #11 that the only thing not easily overridable by a contrib module is the implementation of drupal_html_id(). Everything else is totally straightforward to solve in contrib once the details are worked out. In other words, working out a server-side CSS/JS file list cache along the lines of #6 will still take some work, but once worked out, implementing it in contrib, with existing core hooks, should be possible, because on the JS side, Drupal.ajax.prototype.beforeSerialize() can be overridden, as can the type: 'POST' declaration in Drupal.ajax(), since that's a per-object default that can be changed on a per-element basis pretty much anywhere in the behavior/AJAX pipeline. On the PHP side, we have hook_js_alter() and hook_ajax_render_alter() for changing the used CSS/JS file list from persisted client-side to persisted server-side. And ajax_base_page_theme() can be overridden via hook_menu_alter(), so it hard-coding $_POST is not a problem.

But as per #12, #13, #19, and #20.1, I don't think we should change the base implementation of drupal_html_id() this late in D7, but I do think we need to make it alterable. So, here's a tiny patch to do that.

That's an API addition, not a BC breaking change, so removing the "API Change" tag. For that reason, it can be committed after RC1, so downgrading from critical to major.

AttachmentSizeStatusTest resultOperations
ajax-html-id-956186-21.patch3.02 KBIdleFAILED: [[SimpleTest]]: [MySQL] Unable to apply patch ajax-html-id-956186-21.patch. This may be a -p0 (old style) patch, which is no longer supported by the testbots.View details | Re-test

#22

Status:needs review» reviewed & tested by the community

That's a good move for sure. *everything* needs a hook_alter :D

#23

I'm really not comfortable committing a patch that adds +function hook_html_id_alter(&$id, $original_id, $seen_ids) {. What a gigantic hack on top of a pile of fail. :( (Can't target IDs with CSS? We call ourselves a framework??)

Leaving for Dries to make a call on. IMO, we should attempt to fix this in contrib (I guess? sigh.) and only come back here to add this if this is actually, truly, absolutely necessary.

#24

@webchick: it's certainly within your right to not like this, and to leave it for Dries.

But I'd like to point out that it is already the case that you shouldn't target IDs (except ones you really know to be unique on a page, like ones that are in page.tpl.php) from CSS, and precisely *because* Drupal is a framework. Even the D6 precursor to drupal_html_id(), form_clean_id(), made it so that if you have two form elements on a page, that both would have otherwise had the ID 'foo', that instead the second one is changed to 'foo-2'. It was correct that in D7, we changed the function name from form_clean_id() to drupal_html_id(), and started using it from contexts other than forms.

That we didn't finish the job and still have this in node.tpl.php:

<div id="node-<?php print $node->nid; ?>">
...
</div>

is really a shame, but unaffected by this patch. This *should* be changed to call drupal_html_id(). But until it is, is unaffected by drupal_html_id() potentially returning a different ID than what was passed. In the meantime, what this means is that a page that renders the same node in two different places on the page will fail HTML validation.

So, we have this dilemma. CSS that targets #node-42 currently works, but a page that outputs the same node twice on a page fails validation. If we fix this to use drupal_html_id(), then we fix HTML validation, but the CSS only targets the first one and then fails to target the other ones, since they're changed to "node-42--2", "node-42--3", etc.

All this is true with or without this patch, and with or without AJAX. What AJAX introduces is the idea that "uniqueness on a page" needs to be tracked across page requests.

What the patch introduces is a way for a contrib module to implement uniqueness in some other way than the way done by core, because the way done by core, while working, comes with a performance and caching limitation that a contrib module may want to solve. A well-written contrib module could still implement a strategy by which the first time an ID is used, it is unmodified, so that CSS that targets an ID only breaks precisely in the exact same situation in which it already would have broken anyway even without that contrib module.

So yes, we're a framework: one that allows (and encourages) pieces to be combined in flexible ways. But IDs must be unique per page (blame the W3C for that one). So, the price of this is to not rely on a hard-coded ID of a piece that can appear more than once on a page.

Would more docs in hook_html_id_alter(), saying something like "WARNING: don't break CSS and JS for no good reason: consider the implications of altering Drupal's logic for outputting unique IDs!" help?

#25

This is the best we can do for D7 and for now. It doesn't fix the underlying bug, but it allows contrib to fix it. Without this patch, AJAX GET requests are impossible.

#26

I don't understand how not committing this patch means that AJAX GET requests are impossible. I understand that this is the only part of the rendering chain that's not alterable, but the idea that this needs to happen in order to support GET requests is currently a theory, not a proven rule, since no such code exercising these alters exists. And if it did, we'd be considering it for core inclusion. Or am I mistaken?

#27

Issue tags:+API addition

no such code exercising these alters exists. And if it did, we'd be considering it for core inclusion. Or am I mistaken?

yhahn's #6 patch includes this hunk:

+++ includes/common.inc 29 Oct 2010 14:44:57 -0000
@@ -3667,17 +3665,17 @@ function drupal_html_id($id) {
-  // Ensure IDs are unique by appending a counter after the first occurrence.
-  // The counter needs to be appended with a delimiter that does not exist in
-  // the base ID. Requiring a unique delimiter helps ensure that we really do
-  // return unique IDs and also helps us re-create the $seen_ids array during
-  // AJAX requests.
-  if (isset($seen_ids[$id])) {
-    $id = $id . '--' . ++$seen_ids[$id];
-  }
-  else {
-    $seen_ids[$id] = 1;
+  // Ensure IDs are unique by appending a random short hash. This provides a
+  // reliable method of ensuring uniqueness for AJAX requests where there is not
+  // necessarily a way to compare id's from the original page delivery with the
+  // AJAX response.
+  if (isset($seen_ids[$id]) || isset($_REQUEST['ajax_page_state'])) {
+    while (!isset($hash) || isset($seen_ids[$id . '-'. $hash])) {
+      $hash = substr(md5(uniqid(mt_rand())), 0, 8);
+    }
+    $id = $id .'-'. $hash;
   }
+  $seen_ids[$id] = 1;

This replaces the current drupal_html_id() counter-based suffix with a random suffix. But I don't think it's good for core inclusion this late in D7, since I'm not sure randomizing IDs is the best of all possible solutions.

#19 proposes an alternate approach which is to have the client provide a salt as part of the AJAX request. This is appealing to me, and what I included as the example in #21, though this too may warrant more thought and in-the-wild experience. For example, does requiring the client to provide a salt minimize the effectiveness (i.e., hit ratio) of Varnish caching, which is one of the main benefits we want to get out of using a GET request?

It is also possible that a server-side page state solution can be invented in contrib. This is what I allude to in this comment within drupal_html_id():

    // Ideally, Drupal would provide an API to persist state information about
    // prior page requests in the database, and we'd be able to add this
    // function's $seen_ids static variable to that state information in order
    // to have it properly initialized for this page request. However, no such
    // page state API exists, so instead, ajax.js adds all of the in-use HTML
    // ids to the POST data of AJAX submissions.

I was hoping to have added a page state API to D7 core, but wasn't able to. A precursor to it is the D6 contrib module, AHAH Page Storage, except that module has problems making it unfit for core in its current state. The idea is simple, just like we have a $form_build_id from which the server can recover $form_state, it would be great if we could have a $page_build_id from which the server could recover $page_state, and this $page_state could contain everything the server would need to know about the state of the page, including drupal_html_id()'s $seen_ids static. But, a challenge with implementing this properly is that the database table holding this info would fill up too fast on a busy site. We already run into this with {cache_form}, but that only gets populated for multistep forms, and entries expire every 6 hours. But a {page_state} table would fill up faster, and since the purpose of this issue is to support Varnish caching, 6 hour expiration might be too aggressive.

So, already we have three possible approaches:

  1. A server-side page state implementation that would require no altering of drupal_html_id(), but that exists in theory only, and might not be workable in practice for busy sites.
  2. A client-provided salt approach that would require altering drupal_html_id().
  3. A randomization approach that would require altering drupal_html_id(), but in a different way than the client-provided salt approach.

It's not clear which of these will end up being best, or maybe yet another idea will surface. Adding the alter hook will allow all of these to be explored in contrib and tested in the wild. Then, perhaps, we can implement the best one in D8 core.

#28

Version:7.x-dev» 8.x-dev
Status:reviewed & tested by the community» needs review
Issue tags:+needs backport to D7

Has to go into 8.x first.

#29

#21: ajax-html-id-956186-21.patch queued for re-testing.

#30

Status:needs review» needs work

The last submitted patch, ajax-html-id-956186-21.patch, failed testing.

#31

I'm going to resurrect this issue and attempt to move discussion along a bit, it is still a problem for Drupal 7 and 8.

The issue summary is actually really good, but I'd like to propose some alternative solutions or clarify existing ones:

To solve the unique ID issue, I reckon that the client can simply generate a unique 'salt' and send that to the server, drupal_html_id then just needs to append that salt if it exists. It can do so by suffixing any Drupal ID with say: ':.:SALT' which is still a valid HTML ID I believe, we then disallow the ':.:' from IDs to avoid a collision. This salt can simply be a monotonically incrementing integer, so clients send 1 on the first ajax request they make, and then 2 and three and so on. This way these requests can be cached, and those cache entries will actually get hits, unlike just adding some random strings.

To solve the large arrays of CSS and JS filenames, we really don't want to go down the line of a server side cache really. cache_form is just nasty, and it gets really big, really fast!
All we need to do here is be a bit smarter, we don't need to send the whole file path to the client to have it sent back to the server. What we can do is send an array of hashes of the file paths to the client, and then get them back, and do our checks as before, but hashing at the right moment. Note that we could get away with using a git style six digit hash, rather than a full 40 characters per file.
It should be noted that this array is delivered to the client on every single page request, not just AJAX ones. Go look at the Drupal settings array on your D7 site, I bet it's massive!
We can further optimise this by removing entries in this array that are assured to be delivered to the client on every single request, i.e. those defined in info files.

Actually the biggest problem in both of these issues is that we are sending this data as a massive array, so if you look at the POST request we have the names of our array variables repeated over and over and over. This seems extremely wasteful. We could add a little processing to each side to implode and explode the arrays into strings, thus only sending the name of the variable once. I'm not sure if this suggestion would be good from a security point of view though.

#32

Wow, working on ctools and views that ajax ids and css made me crazy too.

I think it comes from a biais of the "typical Drupal developer", everything in done in PHP. I'd like to talk about CSS files, there is already lots of good ideas about how to handle ids.

From what I understand, css/js files are sent to avoid adding them again if they are already present in the page, and only for this purpose. In ajax.inc there is

      // Ensure that the page doesn't reload what it already has.

Now why is this done on the PHP side? there is already an ajaxPageState variable with what's already there, we should add a couple of ajax command that would load CSS and JS files where we can do this check and forget about posting all CSS and JS files in the request. The diff would have to be made before the commands potentially changing ajaxPageState are processed obviously, that's pretty easy to do.

Actually with a few tweaks it would even be possible to get css files from the head and contents of the aggregated css files directly with a regex targeting a specially formated comment containing the filename, i'm not for this particular solution but just to point out there is a lot more that can be done on the js side of things.

#33

Issue tags:-needs backport to D7

Please read up on #561858: [Tests added] Fix drupal_add_js() and drupal_add_css() to work for AJAX requests too by adding lazy-load to AJAX framework first, which introduced the current AJAX lazy-loading mechanism. Its architectural design was discussed in detail - there have been multiple, entirely different technical implementation approaches, and the current is the one that resolved all needs and edge-cases.

#34

Not sure what you're talking about, in the other issue, the architectural discussion ended at #24 after merlinofchaos said xLazyLoader will not work because it doesn't look for duplicate (to which I said it's our job to worry about that) and it wouldn't work for aggregated CSS files (to which I gave a solution, a bad one, but still), but more importantly I'm not even talking about some kind of loader. The rest of the thread is focused on how to implement merlinofchaos approach best.

The thing is, it's this patch that introduced ajaxPageState, and I'm talking about using precisely that to check for dups. It's a different issue because the context here is different 1 year after. That was an interesting read but that was no architectural discussion.

I'm not saying ajaxPageState should be remove, I'm saying is should only be posted back from PHP not to PHP. Instead of fat ajax requests and responses we'll only have fat ajax responses. Which is not ideal but better and will make it possible to use GET request which is what it's all about here.
To avoid fat responses we'd have to look into aggregated files to know what's going on which is dirty but possible (and I'm not saying we should do that just yet).

#35

Status:needs work» needs review

Here you go, css and js files removed from ajax_page_state during ajax request. And it's still working fine. Does this makes things clearer?

Stuff should be moved around, I don't think the settings command is the best place to do this kind of thing but that's good enough for a proof of concept.

It's only a patch for files, the is nothing to remove ids in this patch. It's probably going to break tests but meh.

AttachmentSizeStatusTest resultOperations
core-remove-files-from-ajax-requests-956186-35.patch3.78 KBIdleFAILED: [[SimpleTest]]: [MySQL] 34,451 pass(es), 3 fail(s), and 0 exception(s).View details | Re-test

#36

Status:needs review» needs work

The last submitted patch, core-remove-files-from-ajax-requests-956186-35.patch, failed testing.

#37

@nod_ https://drupal.org/node/561858#comment-3404404 was the comment that nicely summarises why the current approach is in core.

#38

Thanks for pointing it out, I didn't give enough attention to the linked post it seems. That makes things simpler, the html_id part of this thread which is fixable can be ported to another issue and this one closed as it works as designed. There are a few solutions to limit the impact but nothing will solve this issue properly unless the whole stack is revisited.

To get small ajax http request, you just can't use Drupal AJAX framework. It should be possible to refactor the ajax commands system to be used easily by third party but that's an other issue as well. It depends on what op wanted to do. Or am I once again wrong?

#39

@nod_ I don't see whyt we need to run away to another issue, let's just stay here!

Patches to follow...

#40

Hello @Steven Jones, have you had any progress on this? I am very much for GET ajax calls. That is the architecture of the web, GET to retrieve content (and for caching) and POST to create new content. If Drupal wants to be a player on the modern web it needs to respect the architecture of the web... So a nice skinny GET request would be wonderful!

#41

Sorry I implemented some proof of concepts for my comments in #31 , but nothing further than that really.
There is realtively little code to change though, these are not major refactorings.

#42

This problem is forcing us to do a lot of custom callbacks just so we can use views + ajax + varnish.

It must be rather common, so I wonder if anyone knows of a D7 module or recipe which would allow all views to use cacheable GETs for Ajax in a simple way?

#43

Also we should send ajax_html_ids as string not as array. This will reduce a bit requiest size see #1414510-37: Remove drupal_reset_static for drupal_html_id() when form validation fails

#44

Filed separate issue about serialization of ajax_html_ids #1575060: ajax_html_ids are broken for forms with file element (encoding=multipart/form-data)
Currently this functionality broken for forms with file element

nobody click here