Problem/Motivation
The code in \Drupal\Core\Routing\UrlGenerator::processPath() doesn't use the (potentially) altered query string from the path processor processOutbound() call:
$path = '/' . $this->pathProcessor->processOutbound(trim($actual_path, '/'), $options, $this->requestStack->getCurrentRequest(), $cacheable_metadata);
$path .= $query_string;
Note, $options['query'] can be changed by any of the outbound path processors.
Proposed resolution
Instead of appending the already-set $query_string, the string should be generated after the outbound processors have had a chance to alter it.
Remaining tasks
- Fix
- Figure out what should be done with all the core code that is passing
$options['query'] as a string instead of an array
User interface changes
API changes
Comments
Comment #1
jhedstromNote, this appears to only be an issue when
UrlGenerator::generateFromRoute()is used.UrlGenerator::generateFromPatheventually uses the correct query parameters.Comment #2
jhedstromThis test illustrates the failure. Fixing it seems non-trivial though as I think there are some outbound path processors already in place that do not fully expect the query string to be appended globally. Simply making
generateFromRoutebehave likegenerateFromPathbreaks the batch process, and reworkingprocessPathto use the query string defined by$options['query']results in this odd exception:Comment #4
jhedstromThis gets the test to pass, let's see about the rest of our tests.
Comment #7
jhedstromThe query parameters already attached to the path (from route parameters such as
_format) need to be pushed into the$options['query']array.Comment #9
jhedstromOn the
PathAliasTestfails, this alias:/- ._~!$'"()*@[]?&+%#,;=:%23%25%26%2B%2F%3Féøïвβ中國書۞is being double-escaped (on the
%23%25%26%2B%2F%3Fpart).Comment #10
jhedstromThis fixes a few tests.
Comment #12
jhedstromThis fixes the issue with the alter test failing on sites running in a subdirectory. Still need to figure out the path alias double-escaping issue.
Comment #13
jhedstromThis should address the apparent double-escaping. Since the alias test had a '?' in it, that was parsed out as the query string, and then escaped in
UrlHelper::buildQuery().Comment #15
jhedstromUploading the test-only patch since it has changed slightly since #4.
Comment #18
jhedstromI added a helper method to merge query strings that may already be attached to the path, with ones specified in the options array. I also needed to update
RedirectDestination::get()to properly set$options['query']to an array instead of a string (not sure if that should be a separate issue, but if it is, this one would depend on that fix).Comment #20
jhedstromThis should fix the exceptions. The fatal errors were due to a bunch of core code passing
$options['query']as a string. I added a@todoand update the IS. We can either fix here, or in a follow-up.Comment #22
jhedstromUsing
DiffArrayactually does a strict comparison, soajax_form=TRUEandajax_form=1caused that parameter to be appended to the url twice, which caused the fails in #20.Comment #24
jhedstromThe unit test
RedirectDestinationTesthad an assumption that$options['query']would be a string.Comment #25
jhedstromBumping to major since this is clearly a regression from Drupal 7.
Comment #26
dawehnerCould we also do something like this?
Why do we need to check for the array bit? It seems to be a clear developer error when query is not an array. What about adding an assertion for that?
OH I see, meh
Comment #28
dawehnerFixed the failures.
Comment #30
dawehnerMeh
Comment #31
hchonovThis issue is a blocker for #1810394: Site configuration with domain based language negotiation results in redirecting authenticated users to a different domain when accessing a content entity route for translation language different from the interface language where we define a new outbound processor and have to manually alter the path instead of only adding a new query parameter in the options array.
Comment #34
hchonovre-rolling patch.
Comment #35
dawehnerNote: We can remove this entirely
Comment #36
hchonov@dawehner:
Done.
Comment #37
dawehnerCool, thank you. Asked @pwolanin for a review.
Comment #38
pwolanin commentedThis looks wrong:
The query should always be an array until the final rendering.
This method name doesn't make much sense to me - what's it supposed to be doing?
Comment #39
pwolanin commentedIt looks like fixing this bug properly requires more rewriting of the internals of the generator. In particular, this method call should change and not pass in the query params and should get back out any extra parameters somehow to add to them.
Comment #40
dawehnerDrupal sucks, see issue summary.
Comment #41
pwolanin commentedSo, we should try to fix this properly. In the worst case, we need a BC shim to check the result of outbound processing for a "?" to see if some crufty code appending a string query that needs to be merged with the array data.
Comment #42
jhedstromComment #43
jhedstromThis patch forces query parameters to an array--this change used to break the batch process itself, but in local testing doesn't appear to, so let's see where else this is still a string.
Comment #45
jhedstromIt looks like
$options['query'] = NULLshould be supported. This fixes some of the fails above.Comment #47
jhedstromNot sure how this
usestatement wasn't present.Comment #48
hchonovRerolling, because the patch couldn't be applied anymore as changes in UrlGenerator have been commited.
Comment #50
hchonovWhy this patch here is failing is better explained in #2618510: Add test ensuring LanguageNegotiationContentEntity is correctly processing the query options.
Comment #51
hchonovComment #53
hchonovComment #54
tim.plunkettThe issue that was blocked on this is closed.
Comment #56
napche commentedI added a small patch that partially fixes this issue, as this does not seem fixed in 8.1.2.Disregard..
Comment #57
napche commentedComment #59
hchonovSetting back to "needs review" as only the patch from #51 is to be considered.
Comment #62
dawehner@hchonov Does #51 still apply?
Comment #63
hchonov@dawehner: no, will work on the reroll.
Comment #64
mpp commentedSubscribing as OutboundPathProcessorInterface currently doesn't allow to change the url query.
Needs a reroll.
Comment #65
mpp commentedComment #66
dawehnerTried to reroll and simplify the patch a bit
Comment #67
dawehnerOne bugfix
Comment #70
dawehnerThis issue will be fixed as part of #2809789: UrlGenerator fails to urlencode aliases, incorrectly encodes "system" path
Comment #71
ruloweb commentedI'm working with 8.2.x and confirm that patch in #2809789-40: UrlGenerator fails to urlencode aliases, incorrectly encodes "system" path fix this issue, and it was committed to 8.3.x in #2809789-46: UrlGenerator fails to urlencode aliases, incorrectly encodes "system" path so maybe we should mark this as it wont fix.
Comment #73
pwolanin commentedok, so we can mark this as fixed since it was resolved in the other issue
Comment #74
xjmThanks @pwolanin! I think duplicate makes the most sense here.