Jetty HTTP to HTTPS Redirect Implementation Guide for Version 6.1.24


2 views

When implementing HTTP to HTTPS redirection in Jetty 6.1.24, many developers encounter a common pitfall where the redirect simply doesn't trigger, returning HTTP 200 instead of the expected 301/302 redirect. The root cause often lies in misunderstanding how the RedirectPatternRule works.

The XML configuration you've shown attempts to match the full URL including protocol (http://), but Jetty's pattern matching operates differently:


<!-- This won't work as expected -->
<New id="redirect" class="org.mortbay.jetty.handler.rewrite.RedirectPatternRule">
  <Set name="pattern">http://foobar.com/*</Set>
  <Set name="location">https://foobar.com</Set>
</New>

The pattern attribute should match the request URI without the scheme or domain.

Here's the correct way to implement the redirect:


<Configure id="Server" class="org.mortbay.jetty.Server">
  <Call name="addBean">
    <Arg>
      <New class="org.mortbay.jetty.handler.rewrite.RewriteHandler">
        <Set name="rewriteRequestURI">true</Set>
        <Set name="rewritePathInfo">false</Set>
        <Set name="originalPathAttribute">requestedPath</Set>
        
        <Call name="addRule">
          <Arg>
            <New class="org.mortbay.jetty.handler.rewrite.RedirectPatternRule">
              <Set name="pattern">/*</Set>
              <Set name="location">https://foobar.com$P</Set>
            </New>
          </Arg>
        </Call>
      </New>
    </Arg>
  </Call>
</Configure>

For more control over the redirect behavior:


<New class="org.mortbay.jetty.handler.rewrite.RedirectPatternRule">
  <Set name="pattern">/insecure/*</Set>
  <Set name="location">https://foobar.com/secure$P</Set>
  <Set name="statusCode">301</Set>  <!-- Permanent redirect -->
</New>

Another way to enforce HTTPS is through connector configuration:


<Configure id="Server" class="org.mortbay.jetty.Server">
  <Call name="addConnector">
    <Arg>
      <New class="org.mortbay.jetty.security.SslSocketConnector">
        <Set name="Port">443</Set>
        <Set name="redirectPort">8443</Set>
        <!-- SSL configuration here -->
      </New>
    </Arg>
  </Call>
</Configure>

After implementation, verify using:


curl -v http://foobar.com

You should see HTTP 302 or 301 response with Location header pointing to HTTPS version.


When implementing HTTP to HTTPS redirection in Jetty 6.x, many developers encounter unexpected behavior where requests remain on HTTP despite configured rules. The core issue often lies in how rewrite rules interact with connectors and handler chains.

For Jetty 6.1.24, the RedirectPatternRule requires precise configuration. The original example misses several critical aspects:

<New id="rewrite" class="org.mortbay.jetty.handler.rewrite.RewriteHandler">
  <Set name="rules">
    <Array type="org.mortbay.jetty.handler.rewrite.Rule">
      <Item>
        <New class="org.mortbay.jetty.handler.rewrite.RedirectPatternRule">
          <Set name="pattern">*</Set>
          <Set name="location">https://foobar.com$P</Set>
        </New>
      </Item>
    </Array>
  </Set>
</New>

Ensure both HTTP and HTTPS connectors are properly configured in jetty.xml:

<Call name="addConnector">
  <Arg>
    <New class="org.mortbay.jetty.security.SslSocketConnector">
      <Set name="port">8443</Set>
      <Set name="keystore">path/to/keystore</Set>
      <Set name="password">keystorePassword</Set>
    </New>
  </Arg>
</Call>

For complete coverage, consider these additional scenarios:

  • Preserve original request paths using $P variable
  • Handle HTTP methods properly (GET vs POST)
  • Maintain session information during redirect

For more control, implement a custom handler:

public class ForceHttpsHandler extends AbstractHandler {
  public void handle(String target, Request request,
                    HttpServletRequest httpRequest,
                    HttpServletResponse httpResponse) {
    if (!request.isSecure()) {
      String redirect = "https://" + request.getServerName() + request.getRequestURI();
      httpResponse.sendRedirect(redirect);
    }
  }
}