You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@struts.apache.org by sd...@apache.org on 2017/03/29 09:56:57 UTC

[08/16] struts-extras git commit: renamed https offloading to the more widely used ssl offloading

renamed https offloading to the more widely used ssl offloading


Project: http://git-wip-us.apache.org/repos/asf/struts-extras/repo
Commit: http://git-wip-us.apache.org/repos/asf/struts-extras/commit/b3ce14c9
Tree: http://git-wip-us.apache.org/repos/asf/struts-extras/tree/b3ce14c9
Diff: http://git-wip-us.apache.org/repos/asf/struts-extras/diff/b3ce14c9

Branch: refs/heads/master
Commit: b3ce14c9e744ca713373b358f71f0659bfb35803
Parents: ba12972
Author: Stefaan Dutry <st...@gmail.com>
Authored: Tue Mar 28 16:25:06 2017 +0200
Committer: Stefaan Dutry <st...@gmail.com>
Committed: Tue Mar 28 16:25:06 2017 +0200

----------------------------------------------------------------------
 ...OffloadAwareServletActionRedirectResult.java | 123 ------------
 .../HttpsOffloadAwareServletRedirectResult.java | 188 -------------------
 ...OffloadAwareServletActionRedirectResult.java | 123 ++++++++++++
 .../SslOffloadAwareServletRedirectResult.java   | 188 +++++++++++++++++++
 4 files changed, 311 insertions(+), 311 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/struts-extras/blob/b3ce14c9/struts2-custom-results-plugin/src/main/java/org/apache/struts2/result/HttpsOffloadAwareServletActionRedirectResult.java
----------------------------------------------------------------------
diff --git a/struts2-custom-results-plugin/src/main/java/org/apache/struts2/result/HttpsOffloadAwareServletActionRedirectResult.java b/struts2-custom-results-plugin/src/main/java/org/apache/struts2/result/HttpsOffloadAwareServletActionRedirectResult.java
deleted file mode 100644
index 0cd1390..0000000
--- a/struts2-custom-results-plugin/src/main/java/org/apache/struts2/result/HttpsOffloadAwareServletActionRedirectResult.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * $Id$
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.struts2.result;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-import org.apache.struts2.ServletActionContext;
-import org.apache.struts2.dispatcher.mapper.ActionMapping;
-import org.apache.struts2.dispatcher.Dispatcher;
-import org.apache.struts2.result.ServletRedirectResult;
-import org.apache.struts2.views.util.UrlHelper;
-
-import com.opensymphony.xwork2.ActionContext;
-import com.opensymphony.xwork2.ActionInvocation;
-import com.opensymphony.xwork2.config.entities.ResultConfig;
-import com.opensymphony.xwork2.inject.Inject;
-
-public class HttpsOffloadAwareServletActionRedirectResult extends HttpsOffloadAwareServletRedirectResult {
-    /* The default parameter */
-    public static final String DEFAULT_PARAM = "actionName";
-
-    protected String actionName;
-    protected String namespace;
-    protected String method;
-
-    public HttpsOffloadAwareServletActionRedirectResult() {}
-
-    public HttpsOffloadAwareServletActionRedirectResult(String actionName) {
-        this(null, actionName, null, null);
-    }
-
-    public HttpsOffloadAwareServletActionRedirectResult(String actionName, String method) {
-        this(null, actionName, method, null);
-    }
-
-    public HttpsOffloadAwareServletActionRedirectResult(String namespace, String actionName, String method) {
-        this(namespace, actionName, method, null);
-    }
-
-    public HttpsOffloadAwareServletActionRedirectResult(String namespace, String actionName, String method, String anchor) {
-        super(null, anchor);
-        this.namespace = namespace;
-        this.actionName = actionName;
-        this.method = method;
-    }
-
-    /**
-     * @see com.opensymphony.xwork2.Result#execute(com.opensymphony.xwork2.ActionInvocation)
-     */
-    public void execute(ActionInvocation invocation) throws Exception {
-        actionName = conditionalParse(actionName, invocation);
-        if (namespace == null) {
-            namespace = invocation.getProxy().getNamespace();
-        } else {
-            namespace = conditionalParse(namespace, invocation);
-        }
-        if (method == null) {
-            method = "";
-        } else {
-            method = conditionalParse(method, invocation);
-        }
-
-        String tmpLocation = actionMapper.getUriFromActionMapping(new ActionMapping(actionName, namespace, method, null));
-
-        setLocation(tmpLocation);
-
-        super.execute(invocation);
-    }
-
-    /**
-     * Sets the action name
-     *
-     * @param actionName The name
-     */
-    public void setActionName(String actionName) {
-        this.actionName = actionName;
-    }
-
-    /**
-     * Sets the namespace
-     *
-     * @param namespace The namespace
-     */
-    public void setNamespace(String namespace) {
-        this.namespace = namespace;
-    }
-
-    /**
-     * Sets the method
-     *
-     * @param method The method
-     */
-    public void setMethod(String method) {
-        this.method = method;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/struts-extras/blob/b3ce14c9/struts2-custom-results-plugin/src/main/java/org/apache/struts2/result/HttpsOffloadAwareServletRedirectResult.java
----------------------------------------------------------------------
diff --git a/struts2-custom-results-plugin/src/main/java/org/apache/struts2/result/HttpsOffloadAwareServletRedirectResult.java b/struts2-custom-results-plugin/src/main/java/org/apache/struts2/result/HttpsOffloadAwareServletRedirectResult.java
deleted file mode 100644
index 3431467..0000000
--- a/struts2-custom-results-plugin/src/main/java/org/apache/struts2/result/HttpsOffloadAwareServletRedirectResult.java
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * $Id$
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.struts2.result;
-
-import java.util.Collection;
-import java.util.Enumeration;
-import java.util.List;
-import java.util.Map;
-import java.util.regex.Pattern;
-import java.util.regex.Matcher;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-import org.apache.struts2.ServletActionContext;
-import org.apache.struts2.dispatcher.mapper.ActionMapping;
-import org.apache.struts2.dispatcher.Dispatcher;
-import org.apache.struts2.result.ServletRedirectResult;
-import org.apache.struts2.views.util.UrlHelper;
-
-import com.opensymphony.xwork2.ActionContext;
-import com.opensymphony.xwork2.ActionInvocation;
-import com.opensymphony.xwork2.config.entities.ResultConfig;
-import com.opensymphony.xwork2.inject.Inject;
-
-public class HttpsOffloadAwareServletRedirectResult extends ServletRedirectResult {
-    private static final long serialVersionUID = -5384946213381645549L;
-    private static final Logger LOG = LogManager.getLogger(HttpsOffloadAwareServletRedirectResult.class);
-    private static final Pattern FORWARDED_PROTO_PARAM_HTTPS = Pattern.compile("[^;]proto=https[$;]");
-
-    private UrlHelper urlHelper;
-
-    @Inject
-    public void setUrlHelper(UrlHelper urlHelper) {
-        this.urlHelper = urlHelper;
-    }
-
-    public HttpsOffloadAwareServletRedirectResult() {
-        super();
-    }
-
-    public HttpsOffloadAwareServletRedirectResult(String location) {
-        this(location, null);
-    }
-
-    public HttpsOffloadAwareServletRedirectResult(String location, String anchor) {
-        super(location, anchor);
-    }
-
-    /**
-     * Redirects to the location specified by calling
-     * {@link HttpServletResponse#sendRedirect(String)}.
-     * 
-     * @param finalLocation
-     *            the location to redirect to.
-     * @param invocation
-     *            an encapsulation of the action execution state.
-     * @throws Exception
-     *             if an error occurs when redirecting.
-     */
-    protected void doExecute(String finalLocation, ActionInvocation invocation) throws Exception {
-        ActionContext ctx = invocation.getInvocationContext();
-        HttpServletRequest request = (HttpServletRequest) ctx.get(ServletActionContext.HTTP_REQUEST);
-        HttpServletResponse response = (HttpServletResponse) ctx.get(ServletActionContext.HTTP_RESPONSE);
-
-        if (isPathUrl(finalLocation)) {
-            if (!finalLocation.startsWith("/")) {
-                ActionMapping mapping = actionMapper.getMapping(request, Dispatcher.getInstance().getConfigurationManager());
-                String namespace = null;
-                if (mapping != null) {
-                    namespace = mapping.getNamespace();
-                }
-
-                if ((namespace != null) && (namespace.length() > 0) && (!"/".equals(namespace))) {
-                    finalLocation = namespace + "/" + finalLocation;
-                } else {
-                    finalLocation = "/" + finalLocation;
-                }
-            }
-
-            // if the URL's are relative to the servlet context, append the
-            // servlet context path
-            if (prependServletContext && (request.getContextPath() != null)
-                    && (request.getContextPath().length() > 0)) {
-                finalLocation = request.getContextPath() + finalLocation;
-            }
-
-            finalLocation = fixSchemeIfNeeded(finalLocation, request);
-        }
-        ResultConfig resultConfig = invocation.getProxy().getConfig().getResults().get(invocation.getResultCode());
-        if (resultConfig != null) {
-            Map<String, String> resultConfigParams = resultConfig.getParams();
-
-            List<String> prohibitedResultParams = getProhibitedResultParams();
-            for (Map.Entry<String, String> e : resultConfigParams.entrySet()) {
-                if (!prohibitedResultParams.contains(e.getKey())) {
-                    Collection<String> values = conditionalParseCollection(e.getValue(), invocation,
-                            suppressEmptyParameters);
-                    if (!suppressEmptyParameters || !values.isEmpty()) {
-                        requestParameters.put(e.getKey(), values);
-                    }
-                }
-            }
-        }
-
-        StringBuilder tmpLocation = new StringBuilder(finalLocation);
-        urlHelper.buildParametersString(requestParameters, tmpLocation, "&");
-
-        // add the anchor
-        if (anchor != null) {
-            tmpLocation.append('#').append(anchor);
-        }
-
-        finalLocation = response.encodeRedirectURL(tmpLocation.toString());
-
-        LOG.debug("Redirecting to finalLocation: {}", finalLocation);
-
-        sendRedirect(response, finalLocation);
-    }
-
-    protected String fixSchemeIfNeeded(String location, HttpServletRequest request) {
-        if (shouldFixScheme(request)) {
-            LOG.debug("https offloading happened, fixing redirectlocation");
-            StringBuilder fixedLocation = new StringBuilder();
-            fixedLocation.append("https");
-            fixedLocation.append("://");
-            fixedLocation.append(request.getServerName());
-            if (request.getServerPort() != 80) {
-                fixedLocation.append(':');
-                fixedLocation.append(request.getServerPort());
-            }
-            fixedLocation.append(location);
-
-            return fixedLocation.toString();
-        } else {
-            return location;
-        }
-    }
-
-    protected boolean shouldFixScheme(HttpServletRequest request) {
-        return "https".equals(request.getHeader("X-Forwarded-Proto")) || hasForwardedHeaderWithProtoParamHttps(request);
-    }
-
-    private boolean hasForwardedHeaderWithProtoParamHttps(HttpServletRequest request) {
-        Enumeration<String> forwardedHeaders = request.getHeaders("Forwarded");
-
-        if (forwardedHeaders == null) {
-            return false;
-        }
-
-        while (forwardedHeaders.hasMoreElements()) {
-            String forwardedHeader = forwardedHeaders.nextElement();
-            String[] forwardedHeaderElements = forwardedHeader.split(",");
-            
-            for (String forwardedHeaderElement : forwardedHeaderElements) {
-                Matcher matcher = FORWARDED_PROTO_PARAM_HTTPS.matcher(forwardedHeaderElement.trim());
-
-                if (matcher.matches()) {
-                    return true;
-                }
-            }
-        }
-
-        return false;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/struts-extras/blob/b3ce14c9/struts2-custom-results-plugin/src/main/java/org/apache/struts2/result/SslOffloadAwareServletActionRedirectResult.java
----------------------------------------------------------------------
diff --git a/struts2-custom-results-plugin/src/main/java/org/apache/struts2/result/SslOffloadAwareServletActionRedirectResult.java b/struts2-custom-results-plugin/src/main/java/org/apache/struts2/result/SslOffloadAwareServletActionRedirectResult.java
new file mode 100644
index 0000000..7c812f4
--- /dev/null
+++ b/struts2-custom-results-plugin/src/main/java/org/apache/struts2/result/SslOffloadAwareServletActionRedirectResult.java
@@ -0,0 +1,123 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.struts2.result;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.struts2.ServletActionContext;
+import org.apache.struts2.dispatcher.mapper.ActionMapping;
+import org.apache.struts2.dispatcher.Dispatcher;
+import org.apache.struts2.result.ServletRedirectResult;
+import org.apache.struts2.views.util.UrlHelper;
+
+import com.opensymphony.xwork2.ActionContext;
+import com.opensymphony.xwork2.ActionInvocation;
+import com.opensymphony.xwork2.config.entities.ResultConfig;
+import com.opensymphony.xwork2.inject.Inject;
+
+public class SslOffloadAwareServletActionRedirectResult extends SslOffloadAwareServletRedirectResult {
+    /* The default parameter */
+    public static final String DEFAULT_PARAM = "actionName";
+
+    protected String actionName;
+    protected String namespace;
+    protected String method;
+
+    public SslOffloadAwareServletActionRedirectResult() {}
+
+    public SslOffloadAwareServletActionRedirectResult(String actionName) {
+        this(null, actionName, null, null);
+    }
+
+    public SslOffloadAwareServletActionRedirectResult(String actionName, String method) {
+        this(null, actionName, method, null);
+    }
+
+    public SslOffloadAwareServletActionRedirectResult(String namespace, String actionName, String method) {
+        this(namespace, actionName, method, null);
+    }
+
+    public SslOffloadAwareServletActionRedirectResult(String namespace, String actionName, String method, String anchor) {
+        super(null, anchor);
+        this.namespace = namespace;
+        this.actionName = actionName;
+        this.method = method;
+    }
+
+    /**
+     * @see com.opensymphony.xwork2.Result#execute(com.opensymphony.xwork2.ActionInvocation)
+     */
+    public void execute(ActionInvocation invocation) throws Exception {
+        actionName = conditionalParse(actionName, invocation);
+        if (namespace == null) {
+            namespace = invocation.getProxy().getNamespace();
+        } else {
+            namespace = conditionalParse(namespace, invocation);
+        }
+        if (method == null) {
+            method = "";
+        } else {
+            method = conditionalParse(method, invocation);
+        }
+
+        String tmpLocation = actionMapper.getUriFromActionMapping(new ActionMapping(actionName, namespace, method, null));
+
+        setLocation(tmpLocation);
+
+        super.execute(invocation);
+    }
+
+    /**
+     * Sets the action name
+     *
+     * @param actionName The name
+     */
+    public void setActionName(String actionName) {
+        this.actionName = actionName;
+    }
+
+    /**
+     * Sets the namespace
+     *
+     * @param namespace The namespace
+     */
+    public void setNamespace(String namespace) {
+        this.namespace = namespace;
+    }
+
+    /**
+     * Sets the method
+     *
+     * @param method The method
+     */
+    public void setMethod(String method) {
+        this.method = method;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/struts-extras/blob/b3ce14c9/struts2-custom-results-plugin/src/main/java/org/apache/struts2/result/SslOffloadAwareServletRedirectResult.java
----------------------------------------------------------------------
diff --git a/struts2-custom-results-plugin/src/main/java/org/apache/struts2/result/SslOffloadAwareServletRedirectResult.java b/struts2-custom-results-plugin/src/main/java/org/apache/struts2/result/SslOffloadAwareServletRedirectResult.java
new file mode 100644
index 0000000..399c6f8
--- /dev/null
+++ b/struts2-custom-results-plugin/src/main/java/org/apache/struts2/result/SslOffloadAwareServletRedirectResult.java
@@ -0,0 +1,188 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.struts2.result;
+
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.struts2.ServletActionContext;
+import org.apache.struts2.dispatcher.mapper.ActionMapping;
+import org.apache.struts2.dispatcher.Dispatcher;
+import org.apache.struts2.result.ServletRedirectResult;
+import org.apache.struts2.views.util.UrlHelper;
+
+import com.opensymphony.xwork2.ActionContext;
+import com.opensymphony.xwork2.ActionInvocation;
+import com.opensymphony.xwork2.config.entities.ResultConfig;
+import com.opensymphony.xwork2.inject.Inject;
+
+public class SslOffloadAwareServletRedirectResult extends ServletRedirectResult {
+    private static final long serialVersionUID = -5384946213381645549L;
+    private static final Logger LOG = LogManager.getLogger(SslOffloadAwareServletRedirectResult.class);
+    private static final Pattern FORWARDED_PROTO_PARAM_HTTPS = Pattern.compile("[^;]proto=https[$;]");
+
+    private UrlHelper urlHelper;
+
+    @Inject
+    public void setUrlHelper(UrlHelper urlHelper) {
+        this.urlHelper = urlHelper;
+    }
+
+    public SslOffloadAwareServletRedirectResult() {
+        super();
+    }
+
+    public SslOffloadAwareServletRedirectResult(String location) {
+        this(location, null);
+    }
+
+    public SslOffloadAwareServletRedirectResult(String location, String anchor) {
+        super(location, anchor);
+    }
+
+    /**
+     * Redirects to the location specified by calling
+     * {@link HttpServletResponse#sendRedirect(String)}.
+     * 
+     * @param finalLocation
+     *            the location to redirect to.
+     * @param invocation
+     *            an encapsulation of the action execution state.
+     * @throws Exception
+     *             if an error occurs when redirecting.
+     */
+    protected void doExecute(String finalLocation, ActionInvocation invocation) throws Exception {
+        ActionContext ctx = invocation.getInvocationContext();
+        HttpServletRequest request = (HttpServletRequest) ctx.get(ServletActionContext.HTTP_REQUEST);
+        HttpServletResponse response = (HttpServletResponse) ctx.get(ServletActionContext.HTTP_RESPONSE);
+
+        if (isPathUrl(finalLocation)) {
+            if (!finalLocation.startsWith("/")) {
+                ActionMapping mapping = actionMapper.getMapping(request, Dispatcher.getInstance().getConfigurationManager());
+                String namespace = null;
+                if (mapping != null) {
+                    namespace = mapping.getNamespace();
+                }
+
+                if ((namespace != null) && (namespace.length() > 0) && (!"/".equals(namespace))) {
+                    finalLocation = namespace + "/" + finalLocation;
+                } else {
+                    finalLocation = "/" + finalLocation;
+                }
+            }
+
+            // if the URL's are relative to the servlet context, append the
+            // servlet context path
+            if (prependServletContext && (request.getContextPath() != null)
+                    && (request.getContextPath().length() > 0)) {
+                finalLocation = request.getContextPath() + finalLocation;
+            }
+
+            finalLocation = fixSchemeIfNeeded(finalLocation, request);
+        }
+        ResultConfig resultConfig = invocation.getProxy().getConfig().getResults().get(invocation.getResultCode());
+        if (resultConfig != null) {
+            Map<String, String> resultConfigParams = resultConfig.getParams();
+
+            List<String> prohibitedResultParams = getProhibitedResultParams();
+            for (Map.Entry<String, String> e : resultConfigParams.entrySet()) {
+                if (!prohibitedResultParams.contains(e.getKey())) {
+                    Collection<String> values = conditionalParseCollection(e.getValue(), invocation,
+                            suppressEmptyParameters);
+                    if (!suppressEmptyParameters || !values.isEmpty()) {
+                        requestParameters.put(e.getKey(), values);
+                    }
+                }
+            }
+        }
+
+        StringBuilder tmpLocation = new StringBuilder(finalLocation);
+        urlHelper.buildParametersString(requestParameters, tmpLocation, "&");
+
+        // add the anchor
+        if (anchor != null) {
+            tmpLocation.append('#').append(anchor);
+        }
+
+        finalLocation = response.encodeRedirectURL(tmpLocation.toString());
+
+        LOG.debug("Redirecting to finalLocation: {}", finalLocation);
+
+        sendRedirect(response, finalLocation);
+    }
+
+    protected String fixSchemeIfNeeded(String location, HttpServletRequest request) {
+        if (shouldFixScheme(request)) {
+            LOG.debug("https offloading happened, fixing redirectlocation");
+            StringBuilder fixedLocation = new StringBuilder();
+            fixedLocation.append("https");
+            fixedLocation.append("://");
+            fixedLocation.append(request.getServerName());
+            if (request.getServerPort() != 80) {
+                fixedLocation.append(':');
+                fixedLocation.append(request.getServerPort());
+            }
+            fixedLocation.append(location);
+
+            return fixedLocation.toString();
+        } else {
+            return location;
+        }
+    }
+
+    protected boolean shouldFixScheme(HttpServletRequest request) {
+        return "https".equals(request.getHeader("X-Forwarded-Proto")) || hasForwardedHeaderWithProtoParamHttps(request);
+    }
+
+    private boolean hasForwardedHeaderWithProtoParamHttps(HttpServletRequest request) {
+        Enumeration<String> forwardedHeaders = request.getHeaders("Forwarded");
+
+        if (forwardedHeaders == null) {
+            return false;
+        }
+
+        while (forwardedHeaders.hasMoreElements()) {
+            String forwardedHeader = forwardedHeaders.nextElement();
+            String[] forwardedHeaderElements = forwardedHeader.split(",");
+            
+            for (String forwardedHeaderElement : forwardedHeaderElements) {
+                Matcher matcher = FORWARDED_PROTO_PARAM_HTTPS.matcher(forwardedHeaderElement.trim());
+
+                if (matcher.matches()) {
+                    return true;
+                }
+            }
+        }
+
+        return false;
+    }
+
+}