Author: jawi Date: Mon May 26 10:32:31 2014 New Revision: 1597554 URL: http://svn.apache.org/r1597554 Log: FELIX-4420 - Implement sendRedirect:
- rewrite redirects if the redirect-URL is at the same host as the rewritten URLs; - added some tests in order to verify the correctness. Added: felix/trunk/http/sslfilter/src/main/java/org/apache/felix/http/sslfilter/internal/SslFilterConstants.java (with props) felix/trunk/http/sslfilter/src/main/java/org/apache/felix/http/sslfilter/internal/SslFilterResponse.java (with props) felix/trunk/http/sslfilter/src/test/java/org/apache/felix/http/sslfilter/internal/SslFilterResponseTest.java (with props) Modified: felix/trunk/http/sslfilter/src/main/java/org/apache/felix/http/sslfilter/internal/SslFilter.java felix/trunk/http/sslfilter/src/main/java/org/apache/felix/http/sslfilter/internal/SslFilterRequest.java Modified: felix/trunk/http/sslfilter/src/main/java/org/apache/felix/http/sslfilter/internal/SslFilter.java URL: http://svn.apache.org/viewvc/felix/trunk/http/sslfilter/src/main/java/org/apache/felix/http/sslfilter/internal/SslFilter.java?rev=1597554&r1=1597553&r2=1597554&view=diff ============================================================================== --- felix/trunk/http/sslfilter/src/main/java/org/apache/felix/http/sslfilter/internal/SslFilter.java (original) +++ felix/trunk/http/sslfilter/src/main/java/org/apache/felix/http/sslfilter/internal/SslFilter.java Mon May 26 10:32:31 2014 @@ -18,6 +18,9 @@ */ package org.apache.felix.http.sslfilter.internal; +import static org.apache.felix.http.sslfilter.internal.SslFilterConstants.HDR_X_FORWARDED_SSL; +import static org.apache.felix.http.sslfilter.internal.SslFilterConstants.HDR_X_FORWARDED_SSL_CERTIFICATE; + import java.io.IOException; import java.security.cert.CertificateException; import java.util.Dictionary; @@ -29,17 +32,19 @@ import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import org.osgi.service.cm.ConfigurationException; import org.osgi.service.log.LogService; +@SuppressWarnings("rawtypes") public class SslFilter implements Filter { public static final String PID = "org.apache.felix.http.sslfilter.SslFilter"; - private static final String DEFAULT_SSL_HEADER = "X-Forwarded-SSL"; + private static final String DEFAULT_SSL_HEADER = HDR_X_FORWARDED_SSL; private static final String DEFAULT_SSL_VALUE = "on"; - private static final String DEFAULT_CERT_HEADER = "X-Forwarded-SSL-Certificate"; + private static final String DEFAULT_CERT_HEADER = HDR_X_FORWARDED_SSL_CERTIFICATE; private static final String PROP_SSL_HEADER = "ssl-forward.header"; private static final String PROP_SSL_VALUE = "ssl-forward.value"; @@ -62,12 +67,14 @@ public class SslFilter implements Filter final ConfigHolder cfg = this.config; HttpServletRequest httpReq = (HttpServletRequest) req; + HttpServletResponse httpResp = (HttpServletResponse) res; + if (cfg.sslValue.equalsIgnoreCase(httpReq.getHeader(cfg.sslHeader))) { try { - // In case this fails, we fall back to the original HTTP - // request, which is better than nothing... + httpResp = new SslFilterResponse(httpResp, httpReq); + // In case this fails, we fall back to the original HTTP request, which is better than nothing... httpReq = new SslFilterRequest(httpReq, httpReq.getHeader(cfg.certHeader)); } catch (CertificateException e) @@ -76,11 +83,10 @@ public class SslFilter implements Filter } } - // forward the request making sure any certificate is removed - // again after the request processing gets back here + // forward the request making sure any certificate is removed again after the request processing gets back here try { - chain.doFilter(httpReq, res); + chain.doFilter(httpReq, httpResp); } finally { @@ -96,7 +102,7 @@ public class SslFilter implements Filter // make sure there is some configuration } - void configure(@SuppressWarnings("rawtypes") final Dictionary properties) throws ConfigurationException + void configure(Dictionary properties) throws ConfigurationException { String certHeader = DEFAULT_CERT_HEADER; String sslHeader = DEFAULT_SSL_HEADER; @@ -115,7 +121,7 @@ public class SslFilter implements Filter + certHeader + "'."); } - private String getOptionalString(@SuppressWarnings("rawtypes") Dictionary properties, String key) throws ConfigurationException + private String getOptionalString(Dictionary properties, String key) throws ConfigurationException { Object raw = properties.get(key); if (raw == null || "".equals(((String) raw).trim())) @@ -129,7 +135,7 @@ public class SslFilter implements Filter return ((String) raw).trim(); } - private String getMandatoryString(@SuppressWarnings("rawtypes") Dictionary properties, String key) throws ConfigurationException + private String getMandatoryString(Dictionary properties, String key) throws ConfigurationException { String value = getOptionalString(properties, key); if (value == null) Added: felix/trunk/http/sslfilter/src/main/java/org/apache/felix/http/sslfilter/internal/SslFilterConstants.java URL: http://svn.apache.org/viewvc/felix/trunk/http/sslfilter/src/main/java/org/apache/felix/http/sslfilter/internal/SslFilterConstants.java?rev=1597554&view=auto ============================================================================== --- felix/trunk/http/sslfilter/src/main/java/org/apache/felix/http/sslfilter/internal/SslFilterConstants.java (added) +++ felix/trunk/http/sslfilter/src/main/java/org/apache/felix/http/sslfilter/internal/SslFilterConstants.java Mon May 26 10:32:31 2014 @@ -0,0 +1,78 @@ +/* + * 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.felix.http.sslfilter.internal; + +/** + * Provides constants used in the SSL filter. + */ +interface SslFilterConstants +{ + /** + * If there is an SSL certificate associated with the request, it must be exposed by the servlet container to the + * servlet programmer as an array of objects of type java.security.cert.X509Certificate and accessible via a + * ServletRequest attribute of <tt>javax.servlet.request.X509Certificate</tt>. + * <p> + * The order of this array is defined as being in ascending order of trust. The first certificate in the chain is + * the one set by the client, the next is the one used to authenticate the first, and so on. + */ + String ATTR_SSL_CERTIFICATE = "javax.servlet.request.X509Certificate"; + + /** + * De-facto header used to inform what protocol the forwarded client used to connect to the proxy, such as "https". + */ + String HDR_X_FORWARDED_PROTO = "X-Forwarded-Proto"; + /** + * De-facto header used to inform what port the forwarded client used to connect to the proxy, such as "433". + */ + String HDR_X_FORWARDED_PORT = "X-Forwarded-Port"; + /** + * De-facto header used to inform that the proxy is forwarding a SSL request. + */ + String HDR_X_FORWARDED_SSL = "X-Forwarded-SSL"; + /** + * De-facto(?) header used to pass the certificate the client used to connect to the proxy, in X.509 format. + */ + String HDR_X_FORWARDED_SSL_CERTIFICATE = "X-Forwarded-SSL-Certificate"; + + /** + * HTTP header used to explain the client it should redirect to another URL. + */ + String HDR_LOCATION = "Location"; + + /** + * HTTP protocol/scheme. + */ + String HTTP = "http"; + /** + * Default port used for HTTP. + */ + int HTTP_PORT = 80; + + /** + * HTTPS protocol/scheme. + */ + String HTTPS = "https"; + /** + * Default port used for HTTPS. + */ + int HTTPS_PORT = 443; + + String UTF_8 = "UTF-8"; + String X_509 = "X.509"; +} Propchange: felix/trunk/http/sslfilter/src/main/java/org/apache/felix/http/sslfilter/internal/SslFilterConstants.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: felix/trunk/http/sslfilter/src/main/java/org/apache/felix/http/sslfilter/internal/SslFilterRequest.java URL: http://svn.apache.org/viewvc/felix/trunk/http/sslfilter/src/main/java/org/apache/felix/http/sslfilter/internal/SslFilterRequest.java?rev=1597554&r1=1597553&r2=1597554&view=diff ============================================================================== --- felix/trunk/http/sslfilter/src/main/java/org/apache/felix/http/sslfilter/internal/SslFilterRequest.java (original) +++ felix/trunk/http/sslfilter/src/main/java/org/apache/felix/http/sslfilter/internal/SslFilterRequest.java Mon May 26 10:32:31 2014 @@ -18,6 +18,11 @@ */ package org.apache.felix.http.sslfilter.internal; +import static org.apache.felix.http.sslfilter.internal.SslFilterConstants.ATTR_SSL_CERTIFICATE; +import static org.apache.felix.http.sslfilter.internal.SslFilterConstants.HTTPS; +import static org.apache.felix.http.sslfilter.internal.SslFilterConstants.UTF_8; +import static org.apache.felix.http.sslfilter.internal.SslFilterConstants.X_509; + import java.io.ByteArrayInputStream; import java.io.InputStream; import java.io.UnsupportedEncodingException; @@ -32,45 +37,29 @@ import javax.servlet.http.HttpServletReq class SslFilterRequest extends HttpServletRequestWrapper { - // The HTTPS scheme name - private static final String HTTPS_SCHEME = "https"; - // The HTTP scheme prefix in an URL private static final String HTTP_SCHEME_PREFIX = "http://"; // pattern to convert the header to a PEM certificate for parsing // by replacing spaces with line breaks - private static Pattern HEADER_TO_CERT = Pattern.compile("(?! CERTIFICATE)(?= ) "); - - // character encoding for the client certificate header - private static final String UTF_8 = "UTF-8"; - - /** - * If there is an SSL certificate associated with the request, it must be - * exposed by the servlet container to the servlet programmer as an array of - * objects of type java.security.cert.X509Certificate and accessible via a - * ServletRequest attribute of javax.servlet.request.X509Certificate. - * <p> - * The order of this array is defined as being in ascending order of trust. - * The first certificate in the chain is the one set by the client, the next - * is the one used to authenticate the first, and so on. - */ - protected static final String ATTR_SSL_CERTIFICATE = "javax.servlet.request.X509Certificate"; - - private String requestURL; + private static final Pattern HEADER_TO_CERT = Pattern.compile("(?! CERTIFICATE)(?= ) "); @SuppressWarnings("unchecked") SslFilterRequest(HttpServletRequest request, String clientCertHeader) throws CertificateException { super(request); + + // TODO jawi: perhaps we should make this class a little smarter wrt the given request: + // it now always assumes it should rewrite its URL, while this might not always be the + // case... - if (clientCertHeader != null && clientCertHeader.length() > 0) + if (clientCertHeader != null && !"".equals(clientCertHeader.trim())) { final String clientCert = HEADER_TO_CERT.matcher(clientCertHeader).replaceAll("\n"); try { - CertificateFactory fac = CertificateFactory.getInstance("X.509"); + CertificateFactory fac = CertificateFactory.getInstance(X_509); InputStream instream = new ByteArrayInputStream(clientCert.getBytes(UTF_8)); @@ -92,7 +81,7 @@ class SslFilterRequest extends HttpServl public String getScheme() { - return HTTPS_SCHEME; + return HTTPS; } public boolean isSecure() @@ -102,19 +91,13 @@ class SslFilterRequest extends HttpServl public StringBuffer getRequestURL() { - if (this.requestURL == null) + StringBuffer tmp = new StringBuffer(super.getRequestURL()); + // In case the request happened over http, simply insert an additional 's' + // to make the request appear to be done over https... + if (tmp.indexOf(HTTP_SCHEME_PREFIX) == 0) { - StringBuffer tmp = super.getRequestURL(); - if (tmp.indexOf(HTTP_SCHEME_PREFIX) == 0) - { - this.requestURL = HTTPS_SCHEME.concat(tmp.substring(4)); - } - else - { - this.requestURL = tmp.toString(); - } + tmp.insert(4, 's'); } - - return new StringBuffer(this.requestURL); + return tmp; } } Added: felix/trunk/http/sslfilter/src/main/java/org/apache/felix/http/sslfilter/internal/SslFilterResponse.java URL: http://svn.apache.org/viewvc/felix/trunk/http/sslfilter/src/main/java/org/apache/felix/http/sslfilter/internal/SslFilterResponse.java?rev=1597554&view=auto ============================================================================== --- felix/trunk/http/sslfilter/src/main/java/org/apache/felix/http/sslfilter/internal/SslFilterResponse.java (added) +++ felix/trunk/http/sslfilter/src/main/java/org/apache/felix/http/sslfilter/internal/SslFilterResponse.java Mon May 26 10:32:31 2014 @@ -0,0 +1,148 @@ +/* + * 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.felix.http.sslfilter.internal; + +import static org.apache.felix.http.sslfilter.internal.SslFilterConstants.HDR_LOCATION; +import static org.apache.felix.http.sslfilter.internal.SslFilterConstants.HDR_X_FORWARDED_PORT; +import static org.apache.felix.http.sslfilter.internal.SslFilterConstants.HDR_X_FORWARDED_PROTO; +import static org.apache.felix.http.sslfilter.internal.SslFilterConstants.HTTP; +import static org.apache.felix.http.sslfilter.internal.SslFilterConstants.HTTPS; +import static org.apache.felix.http.sslfilter.internal.SslFilterConstants.HTTPS_PORT; +import static org.apache.felix.http.sslfilter.internal.SslFilterConstants.HTTP_PORT; + +import java.net.MalformedURLException; +import java.net.URL; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpServletResponseWrapper; + +/** + * Provides a custom {@link HttpServletResponse} for use in SSL filter. + */ +class SslFilterResponse extends HttpServletResponseWrapper +{ + private final String serverName; + private final String serverProto; + private final int serverPort; + private final String clientProto; + private final int clientPort; + + public SslFilterResponse(HttpServletResponse response, HttpServletRequest request) + { + super(response); + + // Only rewrite URLs for the host & port the request was sent to... + this.serverName = request.getServerName(); + this.serverPort = request.getServerPort(); + + String proto = request.getHeader(HDR_X_FORWARDED_PROTO); + if (HTTP.equalsIgnoreCase(proto)) + { + // Not really a useful scenario: client is talking HTTP to proxy, and we should rewrite all HTTPS-based URLs... + this.clientProto = HTTP; + this.serverProto = HTTPS; + } + else + { + // Client is talking HTTPS to proxy, so we should rewrite all HTTP-based URLs... + this.clientProto = HTTPS; + this.serverProto = HTTP; + } + + int port; + try + { + String fwdPort = request.getHeader(HDR_X_FORWARDED_PORT); + port = Integer.valueOf(fwdPort); + } + catch (Exception e) + { + // Use default port for the used protocol... + port = -1; + } + // Normalize the protocol port... + if ((port > 0) && ((HTTPS.equals(this.clientProto) && (port == HTTPS_PORT)) || (HTTP.equals(this.clientProto) && (port == HTTP_PORT)))) + { + // Port is the default one, do not use it... + port = -1; + } + + this.clientPort = port; + } + + @Override + public void setHeader(String name, String value) + { + if (HDR_LOCATION.equalsIgnoreCase(name)) + { + URL rewritten = rewriteUrlIfNeeded(value); + // Trying to set a redirect location to the original client-side URL, which should be https... + if (rewritten != null) + { + value = rewritten.toExternalForm(); + } + } + super.setHeader(name, value); + } + + private int normalizePort(String protocol, int port) + { + if (port > 0) + { + return port; + } + if (HTTPS.equalsIgnoreCase(protocol)) + { + return HTTPS_PORT; + } + return HTTP_PORT; + } + + private URL rewriteUrlIfNeeded(String value) + { + try + { + URL url = new URL(value); + + String actualProto = url.getProtocol(); + + if (!this.serverProto.equalsIgnoreCase(actualProto)) + { + return null; + } + + if (!this.serverName.equals(url.getHost())) + { + return null; + } + + if (normalizePort(this.serverProto, this.serverPort) != normalizePort(actualProto, url.getPort())) + { + return null; + } + + return new URL(this.clientProto, this.serverName, this.clientPort, url.getFile()); + } + catch (MalformedURLException e) + { + return null; + } + } +} Propchange: felix/trunk/http/sslfilter/src/main/java/org/apache/felix/http/sslfilter/internal/SslFilterResponse.java ------------------------------------------------------------------------------ svn:eol-style = native Added: felix/trunk/http/sslfilter/src/test/java/org/apache/felix/http/sslfilter/internal/SslFilterResponseTest.java URL: http://svn.apache.org/viewvc/felix/trunk/http/sslfilter/src/test/java/org/apache/felix/http/sslfilter/internal/SslFilterResponseTest.java?rev=1597554&view=auto ============================================================================== --- felix/trunk/http/sslfilter/src/test/java/org/apache/felix/http/sslfilter/internal/SslFilterResponseTest.java (added) +++ felix/trunk/http/sslfilter/src/test/java/org/apache/felix/http/sslfilter/internal/SslFilterResponseTest.java Mon May 26 10:32:31 2014 @@ -0,0 +1,378 @@ +/* + * 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.felix.http.sslfilter.internal; + +import static junit.framework.Assert.assertEquals; +import static org.apache.felix.http.sslfilter.internal.SslFilterConstants.HTTP; +import static org.apache.felix.http.sslfilter.internal.SslFilterConstants.HTTPS; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.IOException; +import java.io.PrintWriter; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +import javax.servlet.ServletOutputStream; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.junit.Test; + +public class SslFilterResponseTest +{ + private static final String BACKEND_SERVER = "backend.server"; + private static final String OTHER_SERVER = "other.server"; + + private static final String DEFAULT_HTTP_PORT = "80"; + private static final String ALT_HTTP_PORT = "8080"; + private static final String DEFAULT_HTTPS_PORT = "443"; + private static final String ALT_HTTPS_PORT = "8443"; + + private static final String LOCATION = "Location"; + + @Test + public void testSetHttpLocationHeaderToNullValue() throws Exception + { + HttpServletResponse resp = createServletResponse(); + HttpServletRequest req = createServletRequest(BACKEND_SERVER); + + SslFilterResponse sresp = new SslFilterResponse(resp, req); + + sresp.setHeader(LOCATION, null); + + assertEquals(null, sresp.getHeader(LOCATION)); + } + + @Test + public void testSetHttpsLocationHeaderToOriginalRequestURI() throws Exception + { + String location, expected; + + HttpServletResponse resp = createServletResponse(); + HttpServletRequest req = createServletRequest(BACKEND_SERVER); + + SslFilterResponse sresp = new SslFilterResponse(resp, req); + + location = HTTPS + "://" + BACKEND_SERVER + "/foo"; + expected = location; + + sresp.setHeader(LOCATION, location); + + assertEquals(expected, sresp.getHeader(LOCATION)); + } + + @Test + public void testSetHttpLocationHeaderToOriginalRequestURI() throws Exception + { + String location, expected; + + HttpServletResponse resp = createServletResponse(); + HttpServletRequest req = createServletRequest(BACKEND_SERVER); + + SslFilterResponse sresp = new SslFilterResponse(resp, req); + + location = HTTP + "://" + BACKEND_SERVER + "/foo"; + expected = HTTPS + "://" + BACKEND_SERVER + "/foo"; + + sresp.setHeader(LOCATION, location); + + assertEquals(expected, sresp.getHeader(LOCATION)); + } + + @Test + public void testSetHttpLocationHeaderToOriginalRequestWithExplicitPort() throws Exception + { + String location, expected; + + HttpServletResponse resp = createServletResponse(); + HttpServletRequest req = createServletRequest(BACKEND_SERVER); + + SslFilterResponse sresp = new SslFilterResponse(resp, req); + + location = HTTP + "://" + BACKEND_SERVER + ":" + DEFAULT_HTTP_PORT + "/foo"; + expected = HTTPS + "://" + BACKEND_SERVER + "/foo"; + + sresp.setHeader(LOCATION, location); + + assertEquals(expected, sresp.getHeader(LOCATION)); + } + + @Test + public void testSetHttpLocationHeaderToOriginalRequestWithForwardedPort() throws Exception + { + String location, expected; + + HttpServletResponse resp = createServletResponse(); + HttpServletRequest req = createServletRequest(BACKEND_SERVER, DEFAULT_HTTP_PORT, HTTPS, ALT_HTTPS_PORT); + + SslFilterResponse sresp = new SslFilterResponse(resp, req); + + location = HTTP + "://" + BACKEND_SERVER + "/foo"; + expected = HTTPS + "://" + BACKEND_SERVER + ":" + ALT_HTTPS_PORT + "/foo"; + + sresp.setHeader(LOCATION, location); + + assertEquals(expected, sresp.getHeader(LOCATION)); + } + + @Test + public void testSetHttpLocationHeaderToOriginalRequestWithDifferentPort() throws Exception + { + String location, expected; + + HttpServletResponse resp = createServletResponse(); + HttpServletRequest req = createServletRequest(BACKEND_SERVER); + + SslFilterResponse sresp = new SslFilterResponse(resp, req); + + location = HTTP + "://" + BACKEND_SERVER + ":" + ALT_HTTP_PORT + "/foo"; + expected = location; + + sresp.setHeader(LOCATION, location); + + assertEquals(expected, sresp.getHeader(LOCATION)); + } + + @Test + public void testSetHttpLocationHeaderToOtherRequestURI() throws Exception + { + HttpServletResponse resp = createServletResponse(); + HttpServletRequest req = createServletRequest(BACKEND_SERVER); + + SslFilterResponse sresp = new SslFilterResponse(resp, req); + + String location = HTTP + "://" + OTHER_SERVER + "/foo"; + String expected = location; + + sresp.setHeader(LOCATION, location); + + assertEquals(expected, sresp.getHeader(LOCATION)); + } + + private HttpServletRequest createServletRequest(String serverName) + { + return createServletRequest(serverName, DEFAULT_HTTP_PORT, HTTPS, DEFAULT_HTTPS_PORT); + } + + private HttpServletRequest createServletRequest(String serverName, String serverPort, String forwardedProto, String forwardedPort) + { + HttpServletRequest req = mock(HttpServletRequest.class); + when(req.getServerName()).thenReturn(serverName); + when(req.getServerPort()).thenReturn(Integer.parseInt(serverPort)); + when(req.getHeader("X-Forwarded-Proto")).thenReturn(forwardedProto); + when(req.getHeader("X-Forwarded-Port")).thenReturn(forwardedPort); + return req; + } + + private HttpServletResponse createServletResponse() + { + HttpServletResponse resp = new HttpServletResponse() + { + private final Map<String, String> headers = new HashMap<String, String>(); + private int status = -1; + private boolean committed = false; + + public void setLocale(Locale loc) + { + throw new UnsupportedOperationException(); + } + + public void setContentType(String type) + { + throw new UnsupportedOperationException(); + } + + public void setContentLength(int len) + { + throw new UnsupportedOperationException(); + } + + public void setCharacterEncoding(String charset) + { + throw new UnsupportedOperationException(); + } + + public void setBufferSize(int size) + { + throw new UnsupportedOperationException(); + } + + public void resetBuffer() + { + } + + public void reset() + { + } + + public boolean isCommitted() + { + return this.committed; + } + + public PrintWriter getWriter() throws IOException + { + throw new UnsupportedOperationException(); + } + + public ServletOutputStream getOutputStream() throws IOException + { + throw new UnsupportedOperationException(); + } + + public Locale getLocale() + { + throw new UnsupportedOperationException(); + } + + public String getContentType() + { + throw new UnsupportedOperationException(); + } + + public String getCharacterEncoding() + { + throw new UnsupportedOperationException(); + } + + public int getBufferSize() + { + throw new UnsupportedOperationException(); + } + + public void flushBuffer() throws IOException + { + committed = true; + } + + public void setStatus(int sc, String sm) + { + status = sc; + committed = true; + } + + public void setStatus(int sc) + { + status = sc; + committed = true; + } + + public void setIntHeader(String name, int value) + { + headers.put(name, Integer.toString(value)); + } + + public void setHeader(String name, String value) + { + headers.put(name, value); + } + + public void setDateHeader(String name, long date) + { + throw new UnsupportedOperationException(); + } + + public void sendRedirect(String location) throws IOException + { + throw new UnsupportedOperationException(); + } + + public void sendError(int sc, String msg) throws IOException + { + throw new UnsupportedOperationException(); + } + + public void sendError(int sc) throws IOException + { + throw new UnsupportedOperationException(); + } + + public int getStatus() + { + return status; + } + + public Collection<String> getHeaders(String name) + { + return Collections.singleton(headers.get(name)); + } + + public Collection<String> getHeaderNames() + { + return headers.keySet(); + } + + public String getHeader(String name) + { + return headers.get(name); + } + + public String encodeUrl(String url) + { + throw new UnsupportedOperationException(); + } + + public String encodeURL(String url) + { + throw new UnsupportedOperationException(); + } + + public String encodeRedirectUrl(String url) + { + throw new UnsupportedOperationException(); + } + + public String encodeRedirectURL(String url) + { + throw new UnsupportedOperationException(); + } + + public boolean containsHeader(String name) + { + return headers.containsKey(name); + } + + public void addIntHeader(String name, int value) + { + throw new UnsupportedOperationException(); + } + + public void addHeader(String name, String value) + { + throw new UnsupportedOperationException(); + } + + public void addDateHeader(String name, long date) + { + throw new UnsupportedOperationException(); + } + + public void addCookie(Cookie cookie) + { + throw new UnsupportedOperationException(); + } + }; + return resp; + } +} Propchange: felix/trunk/http/sslfilter/src/test/java/org/apache/felix/http/sslfilter/internal/SslFilterResponseTest.java ------------------------------------------------------------------------------ svn:eol-style = native