Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support for variables in 'param-value' from properties file without depending on any 3rd party libs #106

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 41 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ HTTP POST. Other application parameters can be in your POSTed url-encoded-form s
proxyArgs.

Build & Installation
------------
--------------------

Simply build the jar using "mvn package" at the command line.
The jar is built to "target/smiley-http-proxy-servlet-VERSION.jar".
Expand All @@ -49,7 +49,7 @@ add this to your dependencies in your pom like so:
<dependency>
<groupId>org.mitre.dsmiley.httpproxy</groupId>
<artifactId>smiley-http-proxy-servlet</artifactId>
<version>1.7</version>
<version>1.9.1</version>
</dependency>

Ivy and other dependency managers can be used as well.
Expand Down Expand Up @@ -136,4 +136,43 @@ proxy:
solr:
servlet_url: /solr/*
target_url: http://solrserver:8983/solr
```

Here is an example of using the proxy with an externalized properties file `http-proxy.properties` and / or `http-proxy-override.properties` which would be plugged into the `web.xml` if it is available in the classpath:

```xml
...
<servlet>
<servlet-name>solr</servlet-name>
<servlet-class>org.mitre.dsmiley.httpproxy.ProxyServlet</servlet-class>
<init-param>
<param-name>targetUri</param-name>
<param-value>${some-url}</param-value>
</init-param>
<init-param>
<param-name>log</param-name>
<param-value>true</param-value>
</init-param>
</servlet>
...
```

make sure you put **${**some-url**}** is used if you want to pickup values from the properties file.

The properties file could be:

**http-proxy.properties**:

```properties
some-url=http://www.cisco.com/{x-some-parameter}/someEndpoint
```

Assuming `x-some-parameter` is a custom header parameter.

If this property needs to be overridden for some reason for a different environment for example, then the override properties file could be:

**http-proxy-override.properties**

```properties
some-url=http://www.cisco.com/someContext/someEndpoint
```
4 changes: 2 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

<groupId>org.mitre.dsmiley.httpproxy</groupId>
<artifactId>smiley-http-proxy-servlet</artifactId>
<version>1.9-SNAPSHOT</version>
<version>1.9.1</version>
<packaging>jar</packaging>

<name>Smiley's HTTP Proxy Servlet</name>
Expand Down Expand Up @@ -35,7 +35,7 @@
<url>https://github.com/dsmiley/HTTP-Proxy-Servlet</url>
<connection>scm:git:https://[email protected]/dsmiley/HTTP-Proxy-Servlet.git</connection>
<developerConnection>scm:git:[email protected]:dsmiley/HTTP-Proxy-Servlet.git</developerConnection>
<tag>HEAD</tag>
<tag>smiley-http-proxy-servlet-1.9</tag>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm; I'm not sure what the implication of this change is... but I see it's something to maintain between versions :-/

</scm>

<properties>
Expand Down
99 changes: 93 additions & 6 deletions src/main/java/org/mitre/dsmiley/httpproxy/ProxyServlet.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,13 @@
import org.apache.http.message.BasicHttpRequest;
import org.apache.http.message.HeaderGroup;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.HttpParams;
import org.apache.http.util.EntityUtils;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Constructor;
import java.net.HttpCookie;
Expand All @@ -54,6 +51,13 @@
import java.util.Enumeration;
import java.util.Formatter;
import java.util.List;
import java.util.Properties;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
* An HTTP reverse proxy/gateway servlet. It is designed to be extended for customization
Expand Down Expand Up @@ -112,6 +116,8 @@ public class ProxyServlet extends HttpServlet {

private HttpClient proxyClient;

private Properties configurationProperties = null;

@Override
public String getServletInfo() {
return "A proxy servlet by David Smiley, [email protected]";
Expand All @@ -129,9 +135,80 @@ protected HttpHost getTargetHost(HttpServletRequest servletRequest) {
/**
* Reads a configuration parameter. By default it reads servlet init parameters but
* it can be overridden.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think these javadocs are now missing info about the ${} syntax you added and properties files.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Java docs added to the method

* In case if you are using an externalized properties file http-proxy.properties and / or
* http-proxy-override.properties which would be plugged into the web.xml if it is available in the classpath:
*
* ...
* &lt;servlet&gt;
* &lt;servlet-name&gt;solr&lt;/servlet-name&gt;
* &lt;servlet-class&gt;org.mitre.dsmiley.httpproxy.ProxyServlet&lt;/servlet-class&gt;
* &lt;init-param&gt;
* &lt;param-name&gt;targetUri&lt;/param-name&gt;
* &lt;param-value&gt;${some-url}&lt;/param-value&gt;
* &lt;/init-param&gt;
* &lt;init-param&gt;
* &lt;param-name&gt;log&lt;/param-name&gt;
* &lt;param-value&gt;true&lt;/param-value&gt;
* &lt;/init-param&gt;
* &lt;/servlet&gt;
* ...
*
* make sure you put ${some-url} is used if you want to pickup values from the properties file.
*
* The properties file could be:
*
* http-proxy.properties:
*
* some-url=http://www.cisco.com/{x-some-parameter}/someEndpoint
*
* Assuming x-some-parameter is a custom header parameter.
*
* If this property needs to be overridden for some reason for a different environment for example, then the override properties file could be:
*
* http-proxy-override.properties
*
* some-url=http://www.cisco.com/someContext/someEndpoint
*/

protected String getConfigParam(String key) {
return getServletConfig().getInitParameter(key);
if(configurationProperties == null) {
configurationProperties = getConfigurationProperties();
}
return getValue(configurationProperties, getServletConfig().getInitParameter(key));
}

protected String getValue(Properties configurationProperties, String value){
if(value == null){
return value;
}
if(value.startsWith("${") && value.endsWith("}")){
String key = value.replaceAll("\\$\\{(.*)\\}", "$1");
return (String) configurationProperties.get(key);
}
return value;
}
protected Properties getConfigurationProperties()
{
Properties configurationProperties = new Properties();
try
{
InputStream proxyPropertiesResource = Thread.currentThread().getContextClassLoader().getResourceAsStream("http-proxy.properties");
if (proxyPropertiesResource != null) {
configurationProperties.load(proxyPropertiesResource);
}
}
catch (IOException e) {}
Properties proxyOverrideProperties = new Properties();
try
{
InputStream proxyOverridePropertiesResource = Thread.currentThread().getContextClassLoader().getResourceAsStream("http-proxy-override.properties");
if (proxyOverridePropertiesResource != null) {
proxyOverrideProperties.load(proxyOverridePropertiesResource);
}
}
catch (IOException e) {}
configurationProperties.putAll(proxyOverrideProperties);
return configurationProperties;
}

@Override
Expand Down Expand Up @@ -161,6 +238,12 @@ public void init() throws ServletException {
hcParams.setParameter(ClientPNames.COOKIE_POLICY, CookiePolicy.IGNORE_COOKIES);
hcParams.setBooleanParameter(ClientPNames.HANDLE_REDIRECTS, false); // See #70
readConfigParam(hcParams, ClientPNames.HANDLE_REDIRECTS, Boolean.class);
readConfigParam(hcParams, ClientPNames.ALLOW_CIRCULAR_REDIRECTS, Boolean.class);
readConfigParam(hcParams, "http.conn-manager.timeout", Integer.class);
readConfigParam(hcParams, ClientPNames.MAX_REDIRECTS, Integer.class);
readConfigParam(hcParams, CoreConnectionPNames.CONNECTION_TIMEOUT, Integer.class);
readConfigParam(hcParams, CoreConnectionPNames.SO_TIMEOUT, Integer.class);
readConfigParam(hcParams, CoreConnectionPNames.STALE_CONNECTION_CHECK, Boolean.class);
proxyClient = createHttpClient(hcParams);
}

Expand Down Expand Up @@ -650,6 +733,10 @@ protected static CharSequence encodeUriQuery(CharSequence in) {
formatter.format("%%%02X",(int)c);//TODO
}
}

if(formatter!= null){
formatter.close();
}
return outBuf != null ? outBuf : in;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,6 @@
import org.apache.http.client.utils.URIUtils;
import org.apache.http.client.utils.URLEncodedUtils;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
Expand All @@ -32,6 +29,10 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
* A proxy servlet in which the target URI is templated from incoming request parameters. The
* format adheres to the <a href="http://tools.ietf.org/html/rfc6570">URI Template RFC</a>, "Level
Expand All @@ -55,7 +56,7 @@ public class URITemplateProxyServlet extends ProxyServlet {
* But that's not how the spec works. So for now we will require a proxy arg to be present
* if defined for this proxy URL.
*/
protected static final Pattern TEMPLATE_PATTERN = Pattern.compile("\\{([a-zA-Z0-9_%.]+)\\}");
protected static final Pattern TEMPLATE_PATTERN = Pattern.compile("\\{(.+?)\\}");
private static final String ATTR_QUERY_STRING =
URITemplateProxyServlet.class.getSimpleName() + ".queryString";

Expand Down Expand Up @@ -107,7 +108,10 @@ protected void service(HttpServletRequest servletRequest, HttpServletResponse se
String arg = matcher.group(1);
String replacement = params.remove(arg);//note we remove
if (replacement == null) {
throw new ServletException("Missing HTTP parameter "+arg+" to fill the template");
replacement = servletRequest.getHeader(arg) ;
if (replacement == null) {
throw new ServletException("Missing HTTP parameter " + arg + " to fill the template");
}
}
matcher.appendReplacement(urlBuf, replacement);
}
Expand Down Expand Up @@ -140,4 +144,5 @@ protected void service(HttpServletRequest servletRequest, HttpServletResponse se
protected String rewriteQueryStringFromRequest(HttpServletRequest servletRequest, String queryString) {
return (String) servletRequest.getAttribute(ATTR_QUERY_STRING);
}

}