The Reverse Proxy Module provides the features of Reverse Proxy, and it consists of HTTP Client builder components, Reverse Proxy Command/Chain components, and Reverse Proxy Servlets and Filters.
By using Reverse Proxy Module, you can serve more sophisticated content especially with a custom content rewriter, and you can also allow Cross-Domain Scripting for trusted applications.
If you use Apache Maven in your project, then you can add the following dependency to use this module in your project.
<dependency> <groupId>org.apache.portals.applications</groupId> <artifactId>apa-webcontent2-reverse-proxy</artifactId> <version>${webcontent2.version}</version> </dependency>
For more information on developing/testing, see README file.
A simple Reverse Proxy servlet can be configured in the web.xml like the following example:
<!-- Reverse Proxy Servlet --> <servlet> <servlet-name>ReverseProxyServlet</servlet-name> <servlet-class>org.apache.portals.applications.webcontent2.proxy.servlet.SimpleReverseProxyServlet</servlet-class> <init-param> <param-name>mappings</param-name> <param-value> /WEB-INF/rproxy-mappings.yaml </param-value> </init-param> <init-param> <param-name>ssl-hostname-verifier</param-name> <param-value>ALLOW_ALL_HOSTNAME_VERIFIER</param-value> </init-param> </servlet> <!-- Map /rproxyservlet/* path to the Reverse Proxy Servlet --> <servlet-mapping> <servlet-name>ReverseProxyServlet</servlet-name> <url-pattern>/rproxyservlet/*</url-pattern> </servlet-mapping>
The servlet (org.apache.portals.applications.webcontent2.proxy.servlet.SimpleReverseProxyServlet) can have the following init parameter(s):
Name | Default Value | Example Value | Description |
---|---|---|---|
mappings | /WEB-INF/rproxy-mappings.xml |
YAML Configuration for path mappings and reverse path mappings.
This parameter value can be any of the following:
Note: Variables enclosed by '${' and '}' are expanded by Java System properties. For example, you would get an expanded string, '/home/user1/rproxy-mappings.xml' from '${user.home}/rproxy-mappings.xml' if the user's home directory is '/home/user1'. |
|
ssl-hostname-verifier | BROWSER_COMPATIBLE_HOSTNAME_VERIFIER | ALLOW_ALL_HOSTNAME_VERIFIER | The init parameter can be any of "ALLOW_ALL_HOSTNAME_VERIFIER", "BROWSER_COMPATIBLE_HOSTNAME_VERIFIER" or "STRICT_HOSTNAME_VERIFIER", case-insensitively. |
The Reverse Proxy mapping configuration in the example above can be like the following:
--- !simple local: /portals/applications/ remote: http://portals.apache.org/applications/ contentRewriters: text/html: !!org.apache.portals.applications.webcontent2.proxy.rewriter.DefaultReverseProxyTextLineContentRewriter [] --- !simple local: /portals/bridges/ remote: http://portals.apache.org/bridges/ contentRewriters: text/html: !!org.apache.portals.applications.webcontent2.proxy.rewriter.DefaultReverseProxyTextLineContentRewriter [] --- !simple local: /localhost/examples1/ remote: //localhost:8080/webcontent2/examples1/ contentRewriters: text/html: !!org.apache.portals.applications.webcontent2.proxy.rewriter.DefaultReverseProxyTextLineContentRewriter [] --- !regex localPattern: ^/apache/(\w+)/(.*)$ remoteReplace: http://$1.apache.org/$2 remotePattern: ^http://(\w+)\.apache\.org/(.*)$ localReplace: /apache/$1/$2 contentRewriters: text/html: !!org.apache.portals.applications.webcontent2.proxy.rewriter.DefaultReverseProxyTextLineContentRewriter [] --- !regex localPattern: ^/localhost/examples2/(.*)$ remoteReplace: //localhost:8080/webcontent2/examples2/$1 remotePattern: ^https?://localhost:8080/webcontent2/examples2/(.*)$ localReplace: /localhost/examples2/$1 contentRewriters: text/html: !!org.apache.portals.applications.webcontent2.proxy.rewriter.DefaultReverseProxyTextLineContentRewriter [] --- !simple local: / remote: http://apache.org/ contentRewriters: text/html: !!org.apache.portals.applications.webcontent2.proxy.rewriter.DefaultReverseProxyTextLineContentRewriter []
You can use a servlet filter instead with the same Reverse Proxy Maping configuration like the following example:
<!-- Reverse Proxy Filter --> <filter> <filter-name>ReverseProxyFilter</filter-name> <filter-class>org.apache.portals.applications.webcontent2.proxy.filter.SimpleReverseProxyFilter</filter-class> <init-param> <param-name>filterPath</param-name> <param-value>/rproxyfilter</param-value> </init-param> <init-param> <param-name>mappings</param-name> <param-value> /WEB-INF/rproxy-mappings.yaml </param-value> </init-param> <init-param> <param-name>ssl-hostname-verifier</param-name> <param-value>ALLOW_ALL_HOSTNAME_VERIFIER</param-value> </init-param> </filter> <!-- Map /rproxyfilter/* path to the Reverse Proxy Filter --> <filter-mapping> <filter-name>ReverseProxyFilter</filter-name> <url-pattern>/rproxyfilter/*</url-pattern> <dispatcher>REQUEST</dispatcher> <dispatcher>INCLUDE</dispatcher> <dispatcher>FORWARD</dispatcher> </filter-mapping>
The servlet filter (org.apache.portals.applications.webcontent2.proxy.filter.SimpleReverseProxyFilter) can have the following init parameter(s):
Name | Default Value | Example Value | Description |
---|---|---|---|
mappings | /WEB-INF/rproxy-mappings.xml |
YAML Configuration for path mappings and reverse path mappings.
This parameter value can be any of the following:
Note: Variables enclosed by '${' and '}' are expanded by Java System properties. For example, you would get an expanded string, '/home/user1/rproxy-mappings.xml' from '${user.home}/rproxy-mappings.xml' if the user's home directory is '/home/user1'. |
|
ssl-hostname-verifier | BROWSER_COMPATIBLE_HOSTNAME_VERIFIER | ALLOW_ALL_HOSTNAME_VERIFIER | The init parameter can be any of "ALLOW_ALL_HOSTNAME_VERIFIER", "BROWSER_COMPATIBLE_HOSTNAME_VERIFIER" or "STRICT_HOSTNAME_VERIFIER", case-insensitively. |
In a Reverse Proxy Mappings configuration file, you can list all the (reverse) path mapping configurations in YAML documents format.
At the moment, two built-in mapping configuration types are supported by default:
Note: YAML configurations are internally parsed by using SnakeYAML library. So, the document type hints and constructor hints are handled by SnakeYAML.
Simple mapping allows you to map a local path to a remote URL by replacing the configured local path prefix by the configured remote URL prefix. And a remote URL is mapped to a local path by replacing the configured URL prefix by the configured local path prefix.
Note: A simple mapping should start with the line, '--- !simple', to denote a new YAML document with a built-in document type hint ('simple').
For example, a simple mapping can be configured like the following:
--- !simple local: /portals/applications/ remote: http://portals.apache.org/applications/
In this simple mapping, for example, if the context path is '/webcontent2' and the request context relative path is '/portals/applications/a/b/c.html' (e.g, 'http://localhost:8080/webcontent2/portals/applications/a/b/c.html'), then the resolved remote URL will be 'http://portals.apache.org/applications/a/b/c.html'.
You can also set which content writer components should do rewrite the remote content by setting 'contentRewriters' to a YAML map like the following example:
--- !simple local: /portals/applications/ remote: http://portals.apache.org/applications/ contentRewriters: text/html: !!org.apache.portals.applications.webcontent2.proxy.rewriter.DefaultReverseProxyTextLineContentRewriter []
With the example configuration above, you will create org.apache.portals.applications.webcontent2.proxy.rewriter.DefaultReverseProxyTextLineContentRewriter instance as content rewriter for 'text/html' content type from the remote content.
Note: !!org.apache.portals.applications.webcontent2.proxy.rewriter.DefaultReverseProxyTextLineContentRewriter [] is interpreted by SnakeYAML in a special way: SnakeYAML instantiates org.apache.portals.applications.webcontent2.proxy.rewriter.DefaultReverseProxyTextLineContentRewriter class instance with the default constructor (as specified by '[]'). Please see SnakeYAML homepage for details.
You can also set a scheme-less remote URL prefix like the following example. In this case, the default URL scheme is inferred from the current servlet request (e.g, javax.servlet.ServletRequest#getScheme()).
--- !simple local: /localhost/examples1/ remote: //localhost:8080/webcontent2/examples1/ contentRewriters: text/html: !!org.apache.portals.applications.webcontent2.proxy.rewriter.DefaultReverseProxyTextLineContentRewriter []
Regular Expression based mapping allows you to map a local path to a remote URL by matching a local path by the configured local path pattern ('localPattern') and replacing it with the configured 'remoteReplace' string. And a remote URL is mapped to a local path by matching a remote URL by the configured remote URL pattern ('remotePattern') and replacing it with the configured 'localReplace' string.
Note: A regular expression based mapping should start with the line, '--- !regex', to denote a new YAML document with a built-in document type hint ('regex').
For example, a Regular Expression based mapping can be configured like the following:
--- !regex localPattern: ^/apache/(\w+)/(.*)$ remoteReplace: http://$1.apache.org/$2 remotePattern: ^http://(\w+)\.apache\.org/(.*)$ localReplace: /apache/$1/$2
In this Regular Expression based mapping, for example, if the context path is '/webcontent2' and the request context relative path is '/apache/portals/a/b/c.html' (e.g, 'http://localhost:8080/webcontent2/apache/portals/a/b/c.html'), then the resolved remote URL will be 'http://portals.apache.org/a/b/c.html'.
You can also set which content writer components should do rewrite the remote content by setting 'contentRewriters' to a YAML map as well like the following example:
--- !regex localPattern: ^/apache/(\w+)/(.*)$ remoteReplace: http://$1.apache.org/$2 remotePattern: ^http://(\w+)\.apache\.org/(.*)$ localReplace: /apache/$1/$2 contentRewriters: text/html: !!org.apache.portals.applications.webcontent2.proxy.rewriter.DefaultReverseProxyTextLineContentRewriter []
With the example configuration above, you will create org.apache.portals.applications.webcontent2.proxy.rewriter.DefaultReverseProxyTextLineContentRewriter instance as content rewriter for 'text/html' content type from the remote content.
Note: !!org.apache.portals.applications.webcontent2.proxy.rewriter.DefaultReverseProxyTextLineContentRewriter [] is interpreted by SnakeYAML in a special way: SnakeYAML instantiates org.apache.portals.applications.webcontent2.proxy.rewriter.DefaultReverseProxyTextLineContentRewriter class instance with the default constructor (as specified by '[]'). Please see SnakeYAML homepage for details.
You can also set a scheme-less remote URL prefix like the following example. In this case, the default URL scheme is inferred from the current servlet request (e.g, javax.servlet.ServletRequest#getScheme()).
--- !regex localPattern: ^/localhost/examples2/(.*)$ remoteReplace: //localhost:8080/webcontent2/examples2/$1 remotePattern: ^https?://localhost:8080/webcontent2/examples2/(.*)$ localReplace: /localhost/examples2/$1 contentRewriters: text/html: !!org.apache.portals.applications.webcontent2.proxy.rewriter.DefaultReverseProxyTextLineContentRewriter []
In order to maximize the extensibility, Reverse Proxy Module is implemented with the Chain of Responsibility pattern by using Apache Commons Chains module.
By default, org.apache.portals.applications.webcontent2.proxy.builder.DefaultProxyProcessingChainBuilder initializes and adds all the common commands to the internal reverse proxy service component. However, you can always modify the chains of the commands in your extended servlet/filter/portlet classes.
For example, org.apache.jetspeed.portlets.sso.SSOReverseProxyServlet in j2-admin project extends org.apache.portals.applications.webcontent2.proxy.servlet.SimpleReverseProxyServlet in order to replace the default org.apache.portals.applications.webcontent2.proxy.command.InitHttpRequestCommand by org.apache.jetspeed.portlets.sso.SSOInitHttpRequestCommand. Also, SSOReverseProxyServlet customizes the default HttpClientContextBuilder by a custom one, JetspeedHttpClientContextBuilder, in order to build custom authentication states based on the Jetspeed SSO Site credentials.