Use friendly URLs without state information
Overview
By default, WebSphere Portal URLs include navigational state information. If we configure pages for friendly URLs, the portal appends the state information to the friendly URLs. Some scenarios require short and fully human readable URLs that omit the state information. For such scenarios, we can configure friendly URLs so the portal does not show that state information.
The state information is an encoded aggregation of the navigational state of the portal, the page, and its components, for example...
- page selection
- expansions
- label mapping
- action targets
- render parameters
- window state
- portlet mode
The representation of the navigational state within the URL enables characteristics of dynamic websites, such as usage of bookmarks or the Back button. For example, users can bookmark a page and later return to the exact same state of that page.
Some scenarios require short and fully human readable URLs that omit the state information. Examples:
- We do not want the URL to make the impression that it references dynamic content.
- You want the URL to contain only information that a human person can read and interpret.
- You want the URL to easily fit into the address field of the web browser.
- Internet search engines expect static URLs that reference only one resource or web page for the time the page exists
- Internet search engines prefer short and friendly URLs.
For such scenarios we configure WebSphere Portal as follows:
- Themes always display only short friendly URLs without the encoded navigational state.
- Pages use theme to display friendly URLs.
The configuration applies to pages using the theme, and configured to display friendly URLs.
If we configure the portal to show stateless friendly URLs, we gain improved URL readability at the cost of losing the state functionality...
- Portal URLs always point to the default state of a page, as they do not contain the state information.
- If a user clicks the Back button, or refreshes a page by clicking the Refresh button or the page title, the page moves back into the default View mode.
- If a user views a page, and then creates a bookmark, clicking the bookmark later opens the page in the default View mode.
- Stateless friendly URLs do not contain the usual information about the language of the page. To determine the language for the page, first, the portal looks for the user preference. If not set, portal looks for the preferred language set in the browser. If the page is a public page, the user is an anonymous user. The portal also looks for the preferred language set in the browser.
- If the portal cannot determine a preferred language setting for the portal or the browser, it applies the default language defined for the portal.
Use friendly URLs without state information
- From the WAS Console, for resource provider WP ConfigService, set..
friendly.redirect.enabled = false
- Use xmlaccess.sh to update the theme for short stateless URLs. Here is an example XML script:
<?xml version="1.0" encoding="UTF-8"?> <request xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="PortalConfig_8.5.0.xsd" type="update"> <!-- Set the hasBaseURL Tag in the Portal 8.5 Theme. --> <portal action="locate"> <theme action="update" uniquename="ibm.portal.85Theme" > <parameter name="com.ibm.portal.theme.hasBaseURL type="string" update="set">true</parameter> </theme> </portal> </request>
- Enable these init-params in portlet.xml to fix any conflicts with the theme metadata setting...
<init-param> <name>com.ibm.portal.state.url.allowrelative</name> <value>true</value> </init-param> <init-param> <name>wps.enforce.redirect</name> <value>true</value> </init-param>
- Change navigation.jsp...
- In the default theme, go to both...
- PORTAL_HOME/theme/wp.theme.themes/default85/installedApps/DefaultTheme85.ear/DefaultTheme85.war/themes/html/dynamicSpots
- PORTAL_HOME/theme/wp.theme.modules/webapp/installedApps/ThemeModules.ear/ThemeModules.war/themes/html/dynamicSpots
..and edit each copy of file navigation.jsp in those folders.
- Search for the string...
<a href="?uri=nm:oid:${wp.identification[node]}" class="wpthemeLeft${titleClass}">
...and change it to the following code snippet...
<portal-navigation:urlGeneration contentNode="${wp.identification[node]}" keepNavigationalState="false"> <a href="<%wpsURL.write(out);%>" class="wpthemeLeft${titleClass}">
- Locate the first </a> tag after the updated string...
<a href="<%wpsURL.write(out);%>"
...and change it to the following code snippet:
</a> </portal-navigation:urlGeneration>
- Change sideNavigation.jsp...
- Run...
cd PORTAL_HOME/theme/wp.theme.themes/default85/installedApps/DefaultTheme85.ear/DefaultTheme85.war/themes/html/dynamicSpots
- Edit sideNavigation.jsp
- Search for the string
<a href="?uri=nm:oid:${wp.identification[node]}" class="<c:if test="${isSelectedNode}"> wpthemeSelected</c:if>${titleClass}">
...and change it to the following code snippet...
<portal-navigation:urlGeneration contentNode="${wp.identification[node]}" keepNavigationalState="false"> <a href="<%wpsURL.write(out);%>" class="<c:if test="${isSelectedNode}" >wpthemeSelected</c:if>${titleClass}">
- Locate the first </a> tag after the updated string...
<a href="<%wpsURL.write(out);%>"
...and change it to the following code snippet
</a> </portal-navigation:urlGeneration>
- Edit the mobileNavigation.jsp file...
- cd PORTAL_HOME/theme/wp.theme.themes/default85/installedApps/DefaultTheme85.ear/DefaultTheme85.war/themes/html/dynamicSpots
- Edit mobileNavigation.jsp
- Search for the string...
<a href="?uri=nm:oid:${nodeID}">
...and change it to the following code snippet:
<portal-navigation:urlGeneration contentNode="${nodeID}" keepNavigationalState="false"> <a href="<%wpsURL.write(out);%>"
- Locate the first </a> tag after the updated string...
<a href="<%wpsURL.write(out);%>"
...and change it to the following code snippet...
</a> </portal-navigation:urlGeneration>
- Optional: To have the WCM Rendering portlet display the friendly and stateless URLs, implement a plug-in that translates the WCM URLs into the required custom format.
- Define friendly URL names for pages as required.
- Optional. To present language-specific portal pages with stateless friendly URLs to the site visitors.
In this case, structure the portal site to reflect which pages or pages are targeted for specific countries or regions. For example, we can create a node for a specific page, and then create language-specific child pages under that node. Example: In the node home, we create pages in English, French, and German. We can then give the site visitors the appropriate one of the following friendly URLs...
http://www.myco.com/wps/home/en/shop
http://www.myco.com/wps/home/fr/shop
http://www.myco.com/wps/home/de/shop
Action URLs
If a Portlet posts to an Action URL, which sets render parameters to set the state, and then the user subsequently uses the back button, the browser may try to POST again, giving "Document Expired" or a related message in the browser.
To fix we can enable init-params in portlet.xml...
<init-param> <name>com.ibm.portal.state.url.allowrelative</name> <value>true</value> </init-param> <init-param> <name>wps.enforce.redirect</name> <value>true</value> </init-param>
Web search results
For web search results, setting the the following disables the "replay" protection for ActionURLs.
<init-param> <name>wps.multiple.action.execution</name> <value>true</value> </init-param>
This opens up the possibility of cross-site-forgery attacks which was the reason for the replay protection in the first place. Only set this if your ActionURL is not used to post anything sensitive or anything that shouldn't be posted twice, for example, backend transactions.
Results
The portal now no longer displays the state information with the URLs.
Parent Use friendly URLs
Related information
Web Content Manager - Example 2: Generate a friendly URL for web content