There is certain behavior when we use Domain Source module in a project with Domain Access module.

Following are the points which can describe the scenario:

  1. Action Links for nodes in Content overview page contains selected Domain source as Base url instead of active Domain url. This is fine since it is mentioned earlier that in Drupal8 links/route are based on canonical URL.

  2. On adding comments on a node http://domain-2/test-node which has accesses on both "Domain-1" & "Domain-2" but having domain source on http:/domain-1/test-node,

    redirecting to a URL with Domain-1 as base URL: http:/domain-1/test-node#comment-1 giving below error:

    Redirects to external URLs are not allowed by default, use \Drupal\Core\Routing\TrustedRedirectResponse for it

    • If a Node is opened on a Domain other than its source domain then actions like adding comment on the node should lead to active domain as base source URL not the Domain source URL
    • Even though on adding all the domain records in "settings.php" as trusted hosts this error is not going.
  3. On editing the same node on "Domain-2" other than its domain source ("Domain-1") does not lead to successful ajax requests, by giving below error:
    jquery.min.js:4 POST http://init.local:8888/vznrw-develop/en/node/547/edit?ajax_form=1&_wrapper_format=drupal_ajax 403 (Forbidden)
    
    VM428 edit:1 XMLHttpRequest cannot load http://init.local:8888/vznrw-develop/en/node/547/edit?ajax_form=1&_wrapper_format=drupal_ajax. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8888' is therefore not allowed access. The response had HTTP status code 403.
    
    ajax.js:965 Uncaught 
    Drupal.AjaxError {message: "↵An AJAX HTTP request terminated abnormally.↵Debug…=1↵StatusText: error↵ResponseText: ↵ReadyState: 0", name: "AjaxError"}
    
    message
    An AJAX HTTP request terminated abnormally.↵Debugging information follows.↵Path: http://init.local:8888/vznrw-develop/en/node/547/edit?ajax_form=1↵StatusText: error
    
    Error at http://localhost:8888/vznrw-develop/core/misc/ajax.js?v=8.3.2:181:32 at http://localhost:8888/vznrw-develop/core/misc/ajax.js?v=8.3.2:13
    

    where,
    Domain-1 = "http://init.local:8888"
    Domain-2 = "http://localhost:8888"

    this happens on just clicking "Add another item" button for any multi-value field. If a node has given access on domains other than its source domain then at least editing should work with in its all.

So all these scenarios has puzzled me a little bit. That should we use Domain Source module or not.

What is required in our project =>

  1. Nodes can be assigned to Domain Source so that we have canonical URLs for SEO
  2. But if a node is assigning access and edit on other domains then links for that node at all places like views, actions, including Content Overview page should be with its active domain as base url not the domain source.
  3. Editing and actions like post comment save redirection should also lead to its accessible active domain not the Domain Source.

Does above all could be provided without using Domain Source module?
What is the scope or usage of Domain Source module ? When to use and when not?

A README.txt might be helpful in this case.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

nghai created an issue. See original summary.

nghai’s picture

Issue summary: View changes
nghai’s picture

Assigned: nghai » Unassigned
agentrickard’s picture

There is a lot to unpack here. Let's start with a description of what the module is designed to do.

Core features:

* Allows nodes to be assigned to a 'canonical' domain.
* This canonical domain is used to rewrite all links to defined node paths, as declared by the Node entity type.
* Ensures that form submissions for those nodes are routed to the proper canonical URL.

Techniques:

* The module uses a standard entity reference field for the assignment of the canonical domain.
* The DomainSourcePathProcessor service extends core's OutboundPathProcessor service to rewrite links.
* Links are rewritten using the same technique as language-based domain handling, by setting the 'base_url' property of the url options.

Assumptions (which may not be true):

* All paths registered to a Node should point to the canonical URL.
* External URL handling is handled by core.
* JS should be loaded from the active domain, which may require setting a global 'url.site' cache context.

This issue is problematic, because you're dealing with about 4 separate issues and behaviors.

1. The behavior you describe is the desired behavior. Domain Source should force links to the canonical URL.

If we want to change this behavior, we would need to make the routes in DomainSourcePathProcessor::ProcessOutbound() configurable. (Or you would write a custom module to replace that service.)

2. The module doesn't handle comments at all. Ideally, a node should never be opened on it's non-canonical domain.

I don't really understand this error, because we only issue redirects on form submit, and those redirects (in domain_source_form_submit()) do use TrustedRedirect Response.

Ideally, we need to add the Comment URLs to the list of rewrites and we need tests for this behavior.

3. This problem is a JS cache issue that is entirely outside our control. Perhaps adding the 'url.site' cache context will fix it. This also sounds like you are using Inline Entity Form (or similar), which would require collaboration with that module to fix.

Again, however, you should be editing on the canonical domain. It may also be a problem caused by the fact that your hostnames don't share a common route (e.g. example.com). Using *.local:8888 for all domains may solve this issue.

4. I think your requirements run counter to the module design. I particularly disagree with item 2. That is the default behavior without using Domain Source. I also disagree with item 3. By design, the canonical URL should _always_ be used.

Why fight against the use of canonical URLs for all links?

As to the README, contributions are welcome. I simply haven't had time.

nghai’s picture

Issue summary: View changes
nghai’s picture

FileSize
3.04 KB

Hi Ken,

Thanks for all the clarifications and giving better understanding of the module.

Please find the Readme.txt for the Domain source module.

I took support from Drupal 7 version of the module and adjusted accordingly. Kindly correct the things where ever is needed.

----

This is now very much clear that this "Domain Source" module should be used if you need following,

  • Allows nodes to be assigned to a 'canonical' domain.
  • This canonical domain is used to rewrite all links to defined node paths, as declared by the Node entity type.
  • Ensures that form submissions for those nodes are routed to the proper canonical UR

To which I totally agreed and which is so contradict to my project requirements. This means that we should not use this module.
But what my different perspective on this module is as following:

  • Lets provide a canonical domain to all nodes
  • This canonical domain will be used to provide reachable source link from SEO (So that there are no too many source links for same node)
  • The same nodes should be completely editable from other assigned domains (For which suitable permissions are defined and working well in Drupal7)
  • Actions like after posting comments should not redirect to canonical domain of the nodes instead should stay on active assigned domain (Logically which is also correct because actions are performed on the node with accessible active domain)

Here, by canonical domain I meant by just only having for SEO or for the Open search to reach the desired content.

Now,

1) Non-working Ajax calls:

  • In drupal 7 there is no such problem. I have tested it.
  • In Drupal 8 Ajax calls for autocomplete is working absolutely fine, why => because those calls are defined using routing.yml where calls are using relative paths. Example:
system.entity_autocomplete:
  path: '/entity_reference_autocomplete/{target_type}/{selection_handler}/{selection_settings_key}'
  defaults:
    _controller: '\Drupal\system\Controller\EntityAutocompleteController::handleAutocomplete'
  requirements:
    _access: 'TRUE'


in system.routing.yml
  • But not working for internal core ajax calls, e.g. addMoreAjax from any core widget say for a multiple-value field widget.
    When we click "Add another item" => it triggers addMoreAjax using form actions & may be using canonical domain as base url which is overridden by the Domain Source module. Not completely sure but definitely need a fix for it.

    Core file: "/core/lib/Drupal/Core/Field/WidgetBase.php" line 291 version D8.3.2

  • 2) Integration of SEO sitemap links
    Could we have SEO integration without using Domain Source module? Where we will define one canonical domain for all nodes and that will be used as source to reach from open internet search to our content.

    I know this requirement up-to some extend is achievable with using Domain Source module. But when someone does not need other core features of this module rather only the one: SEO. Then there is only one option currently available that is the custom module.

    Perhaps I would like to propose a new feature in the "Domain Source" module where user would have two options to choose:

    1) Rewrite "everywhere" all nodes links with canonical domains
    2) Rewrite "only for SEO" all nodes links with canonical domains.

    What is your opinion on this?

    agentrickard’s picture

    I think the SEO optimization you're talking about is more like what Global Redirect does: issue a server-level redirect rather than write the links.

    It shouldn't be too hard to write a module that does that, using similar principles to Domain Source.

    As to that core JS issue -- does having common base hostname (e.g. example.com, one.example.com, two.example.com) fix it?

    nghai’s picture

    No, even on having common base hostname (e.g. example.com, one.example.com, two.example.com) does not fix the error.

    Anonymous’s picture

    I am running into a similar issue with the Javascript. I think this is a real bug with domain, but the other points in this thread are unrelated so I'll be making another issue.

    Our use case is:

    1 domain for US
    1 domain for CA

    Both domains have multilingual enabled and Paragraphs. Using the Paragraphs classic widget, you can see when its Ajax fires on our CA domain it showing a 403 and sometimes CORS issues.

    To solve this I configured CORS per here https://www.drupal.org/node/2715637 but it didn't fully solve it. It seems the AJAX was trying to fire from the US domain when the URL showed the CA domain.

    Anonymous’s picture

    Anonymous’s picture

    Anonymous’s picture

    @nghai I have linked a couple related issues that are unboxed from a few of the things you mentioned.

    agentrickard’s picture

    I wonder if we can fix the JS issue by only changing the VIew link to canonical.

    We could also make it configurable, so that only certain routes get rewritten.

    agentrickard’s picture

    Confirned the comment / reply bug.

    agentrickard’s picture

    Confirmed the AJAX error.

    agentrickard’s picture

    This quick fix corrects the AJAX issue by making the path rewrite only match the canonical route.

    agentrickard’s picture

    Here's a proof of concept patch that incorporates @vilepickle's work on #2894904: \Drupal\Core\Routing\TrustedRedirectResponse error is thrown excessively, especially with multilingual enabled to correct the Comment bug.

    agentrickard’s picture

    Category: Support request » Bug report
    Status: Active » Needs review
    agentrickard’s picture

    That new RedirectResponse subscriber should be moved to Domain Source, since Domain itself doesn't issue redirects except in the case of inactive domains.

    agentrickard’s picture

    I don't thi8nk we have to rewrite the entire RedirectSubscriber.

    It looks like the key component is in the URLHelper::externalIsLocal() method. If we can extend or override that, we should be fine and with less code.

    agentrickard’s picture

    OK. Here's a big patch for review that covers both issues.

    What I ended up doing is swapping in our own Redirect handler when Domain Source is in use. This in turns calls a new DomainRedirectResponse class that overrides two core Drupal classes that are hardcoded.

    It seems an elegant solution to the issue.

    This still needs tests, and I need to know if it actually solves the reported issues.

    agentrickard’s picture

    This patch has gotten large, but seems to fix the following issues:

    * Redirects when translations are enabled. #2894691: Domain source does not correctly rewrite URLs created with the UrlGenerator core class
    * Redirects from comments to canonical domain (original report)
    * AJAX errors from editing forms and cross-domain requests (original report)

    These still need tests, but the current behavior is as follows:

    * Domain Source will only rewrite the canonical link for nodes (/node/1) and not sub-links (/node/1/edit and so on).
    ** This change fixes the AJAX issue on editing forms.
    * Domain Source now validates Redirects against registered domains and aliases, replacing the core behavior of internal path checking.
    ** This change _might_ open a security hole, since open redirects would be allows by any alias matching path. We might need to restrict matches by environment to prevent exposure in cases where someone registers an alias like *.com.
    * Language-based source differences are now respected.

    agentrickard’s picture

    With the CORS solution in core, I don't know that we need to fix the AJAX issue via brute force. https://www.drupal.org/node/2715637

    We could certainly make the link rewrites configurable.

    I'd also like to offer a "security mode" which restricts redirects / rewrites to domains in the $trusted_host_settings.

    agentrickard’s picture

    Status: Needs review » Fixed

    This has been corrected and tests provided. See also the new README that comes with Domain Source -- https://github.com/agentrickard/domain/tree/8.x-1.x/domain_source

    See https://github.com/agentrickard/domain/pull/361

    agentrickard’s picture

    Note that you may need to disable link rewriting for the 'edit-form' route, which can be done in the new configuration. See the documentation.

    Anonymous’s picture

    I was trying this yesterday, perhaps you can give me some enlightenment.

    So I pulled the latest HEAD yesterday into my project. I have a need for domain_locale, so I have a custom implementation of it running right now which provides an event subscriber. This event subscriber does some things checking for which languages should be enabled on which domains which works pretty well.

    What I was seeing with the latest HEAD and https://www.drupal.org/files/issues/2880112-domain_source-path-fix-22.patch (this issue) applied is this:

    My setup:
    1. Default domain is example.com (set as default domain), langcode en-us should be allowed ONLY
    2. Domain I am visiting is example.ca, langcodes en-ca and fr-ca are OK, but en-us is NOT. User should not be able to see example.com/en-ca or example.ca/en-us for example.

    Prior to my event subscriber, domain seems to now be redirecting over to the default domain first, so if I visit example.ca/en-ca/node/123, it would first put me at example.com/en-ca/node/123. My domain_locale code freaks out and causes a redirect loop at that point since it detects the invalid langcode for my .com domain. Previously I have been using domain at commit f7b9cfe1c89c6fe10ddebdfe970596dcce90623c with these patches I contributed back and this was working OK:
    https://www.drupal.org/files/issues/domain_source-url_generator-2894691_...
    https://www.drupal.org/files/issues/2894904_domain-external-redirect-err...

    Any idea what has changed since then? I can look through all of the commits but I suppose you might know off hand :)

    agentrickard’s picture

    If you are not submitting an edit form, Domain would only be issuing a redirect if you are trying to access an inactive domain without permission.

    That code hasn't really changed -- it's in the DomainSubscriber. The only thing that code is doing that's new is ensuring that the redirect is to a trusted host.

    There is nothing else in the code that would issue a redirect on a node view page. The only other change affects how Redirects are handled in cases where nodes are being saved that have a different canonical URL.

    Now, if your custom module is issuing a redirect, it might be getting routed through DomainSourceRedirectResponseSubscriber. If that were redirecting you to the default domain, I would also expect it to return an error.

    agentrickard’s picture

    See also what we're testing for in the following:

    * Functional\DomainSourceLanguageTest
    * Functional\DomainSourceTrustedHostTest
    * Functional\DomainSourceUrlTest
    * DomainInactiveTest

    You should be able to come up with a test case that duplicates the issue.

    agentrickard’s picture

    For reference -- this patch went in -- https://www.drupal.org/files/issues/2894904_domain-external-redirect-err... -- but was modified because LocalRedirectResponse wasn't working properly and needed additional context.

    This patch did not -- https://www.drupal.org/files/issues/domain_source-url_generator-2894691_... -- because the test cases that I have (see the list above) don't show a need for it.

    agentrickard’s picture

    I've been hanging out in Drupal Slack @agentrickard, too. But will likely be offline for a few days.

    agentrickard’s picture

    [Wrong issue]

    agentrickard’s picture

    It is also possible that you're seeing behavior change based on #2896434: Multiple hooks no longer work with domain_config in some cases. There were documented cases where hook_domain_request_alter() was not firing when using modules that implement HTTPMiddleware (e.g. Shield module).

    In that case, it could be that multiple modules are now issuing alias-based redirects, which is the other case in which the resolver might issue a redirect.

    Anonymous’s picture

    Cool, thanks for the insight. Will unbox some of this when I get to updating to latest HEAD on my project soon.

    agentrickard’s picture

    OK. If you run across anything actionable, please open a new ticket.

    Status: Fixed » Closed (fixed)

    Automatically closed - issue fixed for 2 weeks with no activity.