Forums de discussion

Multi-Host -- Single Portal Instance (Company)

thumbnail
Andew Jardine, modifié il y a 9 années.

Multi-Host -- Single Portal Instance (Company)

Liferay Legend Publications: 2416 Date d'inscription: 22/12/10 Publications récentes
Hey Guys,

Appealing to the community for this one. I always seem to get stuck with the doozies emoticon.

Requirement: We need to support multiple hosts for a single portal isntance (company).

Problem: Liferay has a restriction on the VirtualHost table that requires a unique combination of hostname and companyId. That means I can't have more than one virtual host for sharing a single companyId. We can break the constraint, but this is obviously not the proper solution for many many many reasons.

Solution: We think the best way to solve this is to leverage the proxy and use vanity urls. We're using an F5 which has some pretty impressive capabilities for manipulating both inbound and outbound flows. So here is what we are doing.

User (en.domain.com) ------> Proxy (set accept-lang to en, and forward to common.domain.com) -------> Liferay (processes for common.domain.com)
OR
User (fr.domain.com) ------> Proxy (set accept-lang to fr, and forward to common.domain.com) -------> Liferay (processes for common.domain.com)

We use the following properties to tell Liferay to read the language from the header (for guests) and always include it in the URL.

locale.default.request=true
locale.prepend.friendly.url.style=2


which means ultimately
http://en.domain.com/some/url/here ---> http://common.domain.com/en/some/url/here
OR
http://fr.domain.com/some/url/here ---> http://common.domain.com/fr/some/url/here

Now, on the way out, Liferay of course doesn't use relative URLs so we pass the stream through a parsing process and replace --

http://common.domain.com/fr with fr.domain.com and the same for english. In fact, we detect the language from the cookie to determine the language holistically and just replace all common.domain.com with fr.domain.com as well.

This is MOSTLY working. Now, for the PROBLEM!

it seems that urls being created by the portlets are not working -- meaning they are not getting caught. For example, on the default home page that has a navigation portlet and a login portlet. Here is what we get.

+ Sign in link works -- we see fr.domain.com/c/portal/login
+ Banner link works -- we see fr.domain.com
+ Navigation portlet FAILS -- we see common.domain.com/fr
+ Login portlet links (OpenID, Forgot Password etc.) FAILS -- we see common.domain.com/fr


Example of the forgot password link:

http://common.domain.com/fr/home?p_p_id=58&p_p_lifecycle=0&p_p_state=normal&p_p_mode=view&p_p_col_id=column-1&p_p_col_count=1&_58_struts_action=%2Flogin%2Fforgot_password


So I am not really sure at this stage where to look. It looks like, in the case of the forgot password link, that the link is being created based on the header value. THe HTML that the portlet generates is returned in the response for the page of course, so it must be going through the same filters in our F5 on teh way back right? All other links, in the same response, that are layout or theme based appear to be "translated" -- so why not the portlets?

Any ideas?
thumbnail
Jan Geißler, modifié il y a 9 années.

RE: Multi-Host -- Single Portal Instance (Company)

Liferay Master Publications: 735 Date d'inscription: 05/07/11 Publications récentes
That is because Liferay uses the value of the Virtual Host field to generate some (not all) Urls AFAIK. Please try to use a button which is build with the
<aui:button> Tag and see if that works. You might also want to take a look at email send by the portal (like after registering for a new account), I am not sure if the Virtual Host field is used to generate the URL to reply.


Regards
Jan
thumbnail
Andew Jardine, modifié il y a 9 années.

RE: Multi-Host -- Single Portal Instance (Company)

Liferay Legend Publications: 2416 Date d'inscription: 22/12/10 Publications récentes
Hey Jan,

Thanks for answering! The virtual host for my company is set to common.domain.com (for example). So the response body, based on what you are saying would also contain that virtual host for the links right?

I think this is what I want to be honest. The response is passing through a STREAM in the F5, which is configured to do token substitution. So I am looking for common.domain.com and then based on a language variable (I set on the way in, probably this will be changed to reference the GUEST_LANGUAGE_ID cookie value) it determines which host to switch to on the way out.

Looking closer at the login portlet I can see that the links are in fact structs actions. I am wondering if perhaps they are actually generating relative urls which are not being picked up in the stream. Right now the reponse simply passes through the stream -- we don't do anything with the headers. I am wondering if perhaps host value is being populated (in the browser) based on the header value we changed on the way in.

One thing I did change was I changed the style for the locale to never put a language in the URL. Putting the language in was causing a redirect before processing the request and that was breaking the irules set in the f5.

If you have any other ideas, please do share!
thumbnail
Andew Jardine, modifié il y a 9 années.

RE: Multi-Host -- Single Portal Instance (Company)

Liferay Legend Publications: 2416 Date d'inscription: 22/12/10 Publications récentes
Alright -- to close the loop on this on for now, though I am going to open another thread seeking advice on best approach to the solution.

Trying to prevent Liferay from encoding URLs is nearly impossible. More over, it's probably a really bad idea -- I found myself writing a JSP hook to eliminate encoding that is OWASP spec. And really, long term, probably not a viable option for maitenance purposes (there were so many touch points you might as well fork the product and make your own Liferay version).

I did however discover something very plausible as a valid solution.

1. Start with the out of th ebox install.
2. Create an EXT plugin
3. Add a new service.xml definition -- I did this under portal-impl/src/com/liferay/portlet/virtualhostalias that contains the fields required to create an alias for a hostname where the alias is unqiue using companyId, hostname and locale.
4. Update the PortalImpl ** (this is where I will seek some guidance)

.. not for the override, essentially it all comes down to a getPortalURL call with the serverName, serverPort and isSecure flag. What we need in there is the Locale. In my POC I started by trying to find all the places that called that method and passed the Locale to it. This worked for almost everywhere but I had a few stop gaps where I didn't have references to objects in the method that I knew stored the locale. Also, I found that the locale would possibly vary so that didn't seem good. Then I found..


LocaleUtil.getMostRelevantLocale()


.. which uses a ThreadLocal that gets the Locale as stored in the Theme Display -- so we can use this even if there is no Request object handy. For my POC I update the getPortalURL method with some custom logic to get the locale, check a preference for whether or not to use aliases and then hard coded some values -- essentially changing the serverName on the fly. So what I had was, for example --


if ( locale.toString().equals("en_US") ) 
    serverName = english.external.com


... I continued to use the property setting to pull the languge from the Accept-Language Request header, rebuilt the portal source, deployed it and tried it out. Looks like it is working (so far anyway). For the moment it works well enough that it's worth while to go onto the next step to build the actual EXT plugin.

I'll update this thread with a link to that one when I make it.

(here it is: https://www.liferay.com/community/forums/-/message_boards/message/52370739)