Problem/Motivation
We're still relying on global headers instead of using the request/response objects in places like page cache handling. This needs to be fixed before release, so here's a start on it.
Related Issues
Working on cleaning up global variable calls such as $_SERVER in code #1998638: [Meta] Refactor raw PHP variables (e.g $_SERVER, $_REQUEST, $_GET, $_POST) with Symfony Request object.
Not the appropriate place to discuss #1855260-39: Make sure page caching works with accept header-based routing.
Proposed resolution
Update drupal_add_http_header() so relying on Symfony to send headers patch: reqrep-1984766-9.patch result: "FAILED: [[SimpleTest]]: [MySQL] 55,672 pass(es), 29 fail(s), and 0 exception(s)." details.
Remaining tasks
- drupal_set_page_cache() and drupal_serve_page_from_cache() need clean-up.
- drupal_add_http_header() still being used in install.core.inc and cannot be removed yet.
- Update or add new patch to use symfony to send headers.
Comment | File | Size | Author |
---|
Comments
Comment #1
Crell CreditAttribution: Crell commentedThis doesn't really do anything other than remove some global functions in favor of their new object equivalents. That is, it's a Good Thing(tm) on its face.
If the bot's happy, I am.
Comment #3
effulgentsia CreditAttribution: effulgentsia commentedPer #1855260-39: Page caching broken by accept header-based routing, would this be the appropriate issue in which to discuss HalSubscriber and AjaxSubscriber calling
$request->setFormat()
within a KernelEvents::REQUEST event? Since all setFormat() does is set a static mimetype map, would it make sense to do it pre-kernel, so that the cache layer can benefit from it?Comment #4
Crell CreditAttribution: Crell commenteduse_http_objects_for_cache.patch queued for re-testing.
Comment #6
sdboyer CreditAttribution: sdboyer commented@effulgentsia - this doesn't feel quite like the right place for that - thus far what we've been discussion is really just cleaning ways in which we dodge around request/response by busting encapsulation in one way or another.
Crell, msonnabaum and i chatted about this a fair bit today. i'm gonna take a stab at cleaning up & consolidating the crazy shit we do with headers, and msonnabaum will have a swing at some of our other global violations - asking $_SERVER, and such.
Comment #7
Anonymous (not verified) CreditAttribution: Anonymous commentedkimb0 started working on the $_SERVER stuff here: #1998638: Replace almost all remaining superglobals ($_GET, $_POST, etc.) with Symfony Request object.
Comment #8
dcam CreditAttribution: dcam commentedhttp://drupal.org/node/1427826 contains instructions for updating the issue summary with the summary template.
The summary may need to be updated with information from comments.
Comment #9
sdboyer CreditAttribution: sdboyer commentedthis still has quite a few failures locally, but the important thing is that i've castrated
drupal_add_http_header()
so that it no longer callsdrupal_send_headers()
; it simply builds up a bunch of headers, which later get attached to the response object. so we're finally relying on symfony to actually send our headers. woot.i would have completely removed
drupal_send_headers()
, but it's still being used in install.core.inc. that's on the short list for removal.generally, this is progress, but the separation of
drupal_set_page_cache()
anddrupal_serve_page_from_cache()
is pretty awkward, and merits some refactoring in the context of a situation where we're entirely deferring the sending of headers, and simply queueing them up on the response. but, once we get this green, we could easily deal with that in a followup.Comment #12
klausiThis looks great so far!
Do not use the fully qualified namespace here, use use statements instead
same here and in a couple of other places.
So the session and page caching tests are failing, which worries me a bit whether this works at all.
Comment #13
sdboyer CreditAttribution: sdboyer commentedthis patch:
Comment #14
msonnabaum CreditAttribution: msonnabaum commentedComment #16
sdboyer CreditAttribution: sdboyer commentedthis patch fixes all the PageCacheTest test failures. however, there are still outstanding issues.
drupal_add_http_header()
was castrated and turned into a passive header store. imo, as with pretty much all of our other drupal_add*() globals, this was a shit API in the first place and should not be considered a regression. however, it should be addressed clearly in the followup that takes care of refactoring the caching process to be sane and make sense (i.e., #1597696: Consider whether HttpCache offers any significant benefit over the existing page cache).Vary: Accept-Encoding
got sent. these tests do NOT setsystem.performance.response.gzip = 1
, and as that's the *only* time we set the Accept-Encoding header, i have no idea how this logic even worked before. we don't seem to be seeing the gzinflate exceptions with testbot, though, so i'm imagining that it's being taken care of transparently by the testbot's webserver configuration, the tests are wrong, and we're not actually testing the right thing there. in any case, i've made it explicit.Vary: Accept-Encoding
ought to already be expressing this information effectively to the client, and it need not be explicitly included in the etag. though of course, #1573064: Remove unique ETag hack as it is no longer necessary hopefully indicates we can remove all this etag nonsense and save it for when it's actually appropriate to use...WebTestBase::assertHeader()
method that does the somewhat grunty work of a) allowing partial assertions (e.g., will be true if one does something like$this->assertHeader('Vary', 'Cookie')
), and b) keeps a correct catalogue of what header field names and values are specified to be case insensitive/sensitive according to RFC 2616, and performs string comparisons accordingly. at least some of this would, i suspect, be eased by using Guzzle...but eh.the other major step involved here, apart from fixing some of these other test failures, is passing a Request into
drupal_serve_page_from_cache()
and using it, instead of superglobals, to get request header information.the patch also includes #2004908: Allow tests to specify that response headers should be dumped in verbose mode, without which it is utterly fucking impossible to work on this, so i've just left it in for now as a convenience to others :) that should go in presently, and we can remove it from here when it does.
Comment #17
sdboyer CreditAttribution: sdboyer commentedComment #19
Crell CreditAttribution: Crell commentedGiven that this is just step one, and we're planning to change/refactor a lot of the code anyway as soon as this lands, I am totally OK if we address "weird and hard to debug tests that don't make sense" by removing them outright rather than rewriting them. I suspect a lot will become redundant anyway once we start using a wrapping kernel for caching, or be so different that they might as well, so I'm all for making our lives easier.
Comment #20
sdboyer CreditAttribution: sdboyer commentedwell i'd try that...cept i don't know which tests are failing, since testbot is choking and not telling us (jthorson said we're hitting #1931574: Update PIFR to use config to set simpletest verbose for D8 tests.). and it was all green locally :( i'm not really sure how to resolve it.
meanwhile, i'll see if we can nail the other two failures. and, we still need to refactor out the $_SERVER calls, swapping in the request object. i wouldn't cry if someone else wanted to take that on :)
Comment #21
Crell CreditAttribution: Crell commented@deprecated should include a statement of, at minimum, what to use instead.
The comment is a bit unclear, as it almost implies at a glance that not setting max-age > 0 is what allows it to be cached by external proxies, which is the opposite of what's intended. I'd suggest:
"Thus, do not set a max-age > 0 (which would imply that the page may be cached by external proxies), when a session cookie is..."
Why DrupalDateTime here but DateTime elsewhere? And shouldn't it be \DrupalDateTime?
Comment #22
sdboyer CreditAttribution: sdboyer commentedupdated patch. i'm incredibly dumb, and missed the fact that i was trying to fix install.core.inc, and the actual problem was in the UPDATE system. god dammit - that's two days burned. now with any luck, we'll actually get testbot to tell us why the page cache test is failing.
@Crell - re: @deprecated - there is no substitute for drupal_get_http_header(), because we haven't designed it yet. but i've added a note saying that all headers are set directly on the response object.
I agree, the comment is unclear. It's also what's already in core :) it's just moved from above in the function. i'm not touching it, and we should not care about it as it will likely go away with a more proper refactor.
the
DrupalDateTime
is from msonnabaum's original patch. i don't really know how to use it, so i just usedDateTime
elsewhere because it's what Symfony's Response object explicitly type-hints for. if we just want to get this in with the expectation that we're (immediately) going to be shifting the responsibility outside of the kernel, this seems like a nit not worth mucking with.i've also included a version of the patch that excludes the header-dumping logic that's over in #2004908: Allow tests to specify that response headers should be dumped in verbose mode.
Comment #23
sdboyer CreditAttribution: sdboyer commentedComment #25
Niklas Fiekas CreditAttribution: Niklas Fiekas commentedWith regards to test failures this one should do it: Normalize casing of Vary headers.
Comment #26
Niklas Fiekas CreditAttribution: Niklas Fiekas commented(Or at least if I would upload the complete patch.)
Comment #27
sdboyer CreditAttribution: sdboyer commentedok, that's weird. i can't imagine why header casing would vary between my environment and testbot's, especially since that's under symfony's control. and we should maybe consider changing that test to conform to RFC2616, which specifies that both those field names and values should be case-insensitive.
but for now...who cares, it's green! thanks!
so now, just need to do a bit more tweaking to only use a Request, instead of directly accessing the $_SERVER globals in
drupal_serve_page_from_cache()
. then this should be ready for proper review, and committing. i'll do that now...Comment #28
sdboyer CreditAttribution: sdboyer commentedok, refactored to use request, instead.
this was somewhat awkward in
_drupal_bootstrap_page_cache()
, as it occurs before the request has been put into the container, thus making it impossible to retrieve via any of our global methods. this shouldn't be surprising to anyone, as this it's the problem we've been discussing at length about the degree of encapsulation and ordering of operations in our bootstrap process.to solve it, i simply dropped a
Request::createFromGlobals()
into_drupal_bootstrap_page_cache()
. this is the same thing we do just a little later to create the request object that's actually used, and is a read-only operation, so should be good enough.also, i changed PageCacheTest to perform case-insensitive tests in appropriate places on header content. while the fix from #25 did make testbot happy, it broke on my local, and the fact that the RFC dictates that *either* casing approach is valid means that we should not be calling failure in either case. i had previously left it case-sensitive after an internal debate where i landed on the notion that "it's OK for Drupal to perform case-sensitive tests here as what we're testing is not RFC compliance, but 'common form' compliance" (see RFC 2616, section 14.44, "Vary"). however, if we're seeing variations in the actual output across environments, i take that as a strong indicator that we should be testing nothing more than RFC compliance.
i'd say this is now ready for PROPER review, and committing.
Comment #29
msonnabaum CreditAttribution: msonnabaum commentedComment #30
Crell CreditAttribution: Crell commentedWhat happens with the empty return? We're setting stuff on a response object and then not returning it? That doesn't seem right.
Comment #31
msonnabaum CreditAttribution: msonnabaum commentedIsn't the response a reference to the one that gets sent? If the 304 test is passing, I'm assuming that change works.
The rest of this looks like a nice step forward. Would RTBC if it wasn't my original patch.
Comment #32
sdboyer CreditAttribution: sdboyer commentedyes, the response object on which the 304 is being set is the same one passed in as a parameter to that way-too-long function. as @msonnabaum points out, the 304 tests would be failing if that didn't work. changing the structure of
drupal_serve_page_from_cache()
to have it return a response would, imo, constitute a change in the API that is beyond the scope of what we're trying to do here.Comment #33
Anonymous (not verified) CreditAttribution: Anonymous commentedthis looks good to me.
one thing that needs fixing is returning a cache-control with max-age on a 304 response, so that clients don't keep asking. apart from that, i think this is ready.
Comment #34
sdboyer CreditAttribution: sdboyer commented@beejeebus pointed out that, with the current logic flow, we can't set cache-control headers on a 304. that's wrong. i now can't remember why i originally moved that logic into the second half of the function (though i have a sinking feeling it was after observing oddities in flow owing to what headers we throw into the 'page' cache bin), but it certainly doesn't seem to belong there.
so if there are immediately obvious issues, hopefully our tests will catch them. if not, then it'll be better to solve those issues with a broader refactor.
Comment #35
Anonymous (not verified) CreditAttribution: Anonymous commentedyay, i think this is ready to fly.
Comment #36
sdboyer CreditAttribution: sdboyer commentednote that this is kinda dependent on #2004908: Allow tests to specify that response headers should be dumped in verbose mode, at least for full, proper debugging output. it'd be great if we could get that in (incidentally, it's also RTBC!) as well...
Comment #37
Crell CreditAttribution: Crell commentedThis has a +1 from me as well.
Comment #38
catchIs there an issue for this?
This just got marked deprecated, although I guess it's a step less deprecated than calling header() directly..
current_path() and getQueryString() aren't remotely equivalent - why the change? If the change was on purpose then this should be called something other than path. The system path is available here so not sure why it's not using that logic.
Why not do it here? Would prefer an issue to the @todo if there's some reason not to change it now.
Comment #44
sdboyer CreditAttribution: sdboyer commented@catch - follow-up re: criminality is, i'd say, #1597696: Consider whether HttpCache offers any significant benefit over the existing page cache. at least, that's how we've all been talking about it - this patch paves the way for us separating out caching into something that's situated outside(-ish) of the kernel. that's the best way to address the ordering problem.
deprecation of
drupal_add_http_header()
- right, this is the patch that marks it deprecated. while it sucks to have to keep using it, and we want to refactor those things out, fully removing it falls largely under the heading of the first issue - write a saner system that wraps-ish the kernel, and we remove the need for those deprecated functions. in the meantime, however, we're relying ondrupal_add_http_header()
as the way for "anything" to add headers at anytime without actually sending them - actually making it behave a lot more like the other global drupal_add*() functions. at the end of request processing (in FinishResponseSubscriber), we then deque them onto the response object. this is all because Response is designed to not send any headers at all if they've already been sent, so we have to use this deferring method to avoid calls toheader()
from our own code.current_path() and getQueryString() - that's from @msonnabaum's original patch, i'm gonna defer to him on that. though i will anecdotally say that, from what i've observed being dumped into the page cache table with and without this patch...the two look pretty similar.
re: setLastModified() - ahh yes, thanks for catching that, i think i just forgot to finish it off in one of my earlier patches when i was getting frustrated by DateTime. new patch fixes that.
Comment #45
sdboyer CreditAttribution: sdboyer commentedComment #47
msonnabaum CreditAttribution: msonnabaum commentedAddressed 3 from #38. Good catch-catch.
Comment #48
Anonymous (not verified) CreditAttribution: Anonymous commentedoh hai bot.
Comment #50
sdboyer CreditAttribution: sdboyer commentedfix the error, it was the relic of a poor rebase after #2004908: Allow tests to specify that response headers should be dumped in verbose mode went in. incorporates #47, and the interdiff is against that.
Comment #51
Anonymous (not verified) CreditAttribution: Anonymous commented#50 looks good, RTBC time again.
Comment #52
alexpottThese changes in #50 look unintended to me... perhaps we still have some "relics from a poor rebase"
Comment #53
sdboyer CreditAttribution: sdboyer commentedugh...yes. thank you, sorry. should be taken care of now.
Comment #54
Crell CreditAttribution: Crell commentedOne more time. :-)
Comment #55
alexpottCommitted 6941c5b and pushed to 8.x. Thanks!
Comment #56
catchJust moving to task so I don't think there's been a regression.
Comment #57
vijaycs85Going to write API change notification.
Comment #58
vijaycs85Here is the draft of change notice:
As discussed over IRC, we might need to wait for other issues to get in to right change notice:
Drupal 7
Drupal 8
Drupal 7
Drupal 8
Drupal 7
Drupal 8
Drupal 7
Drupal 8
Comment #59
Crell CreditAttribution: Crell commentedMost of #58 isn't really API-facing. The API-facing change here is "if you want to mess with the headers, use kernel.response. Don't use the functions, because they're gone/will be gone."
Comment #60
catch#2083415: [META] Write up all outstanding change notices before release
Comment #60.0
catchAdded summary of patches made and results also list of cleanup tasks using issue summary template.
Comment #61
vijaycs85Added change record as per #59
Comment #62
ianthomas_ukWhat is the future of drupal_*_header()? They are marked deprecated, but I can't find any issues to remove them.
Comment #63
Crell CreditAttribution: Crell commentedHeader manipulation needs to happen on the Response object directly, in the RESPONSE event. Setting headers arbitrarily is no longer supported.
Comment #64
ianthomas_ukI have filed #2184907: Remove uses of drupal_add_http_header and related functions to remove these functions.
Comment #65
martin107 CreditAttribution: martin107 commented53: reqresp-1984766-53.patch queued for re-testing.
Comment #67
martin107 CreditAttribution: martin107 commentedComment #68
ianthomas_ukThis doesn't need reroll - it doesn't apply because it's already been committed! Please read the comments beyond a patch before queuing it for retesting or marking the patch as needs work.
This is still open because the change record needs to be completed. The holdup there is that it's not exactly clear what the change record should say. If you were previously calling drupal_add_http_header(), how should you change your code now? There's a relevant discussion on #2184907-10: Remove uses of drupal_add_http_header and related functions onwards. Leaving as needs work, because we still need a change record.
Comment #69
dawehnerWe no longer have those globals.