Skip to content

Commit

Permalink
[JENKINS-73126] Upgrade Winstone from Jetty 10.x to 12.x (EE 8) (#383)
Browse files Browse the repository at this point in the history
Co-authored-by: Olivier Lamy <olamy@apache.org>
  • Loading branch information
basil and olamy authored Aug 12, 2024
1 parent e5a0da5 commit 400eeee
Show file tree
Hide file tree
Showing 10 changed files with 107 additions and 270 deletions.
5 changes: 0 additions & 5 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,6 @@ updates:
schedule:
interval: "weekly"
target-branch: "master"
ignore:
# Restrict updates to jetty in the 10.x space
- dependency-name: "org.eclipse.jetty:*"
versions: [ ">=11" ]

- package-ecosystem: "github-actions"
directory: "/"
schedule:
Expand Down
3 changes: 1 addition & 2 deletions Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,5 @@
*/
buildPlugin(useContainerAgent: true, configurations: [
[platform: 'linux', jdk: 21],
[platform: 'windows', jdk: 17],
[platform: 'linux', jdk: 11]
[platform: 'windows', jdk: 17]
])
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# What is Winstone?
Winstone is a command line interface around Jetty 10.0.x, which implements
Winstone is a command line interface around Jetty 12.0.x, which implements
Servlet 4.0 (JakartaEE 8/`javax.servlet.*`), WebSocket/JSR-356, and HTTP/2 support. It is used as the default
embedded servlet container in Jenkins (via the `executable` package in the `war` module)
and can be used by any other web applications that wants to be self-contained.
Expand Down
37 changes: 21 additions & 16 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,12 @@
</scm>

<properties>
<revision>6.22</revision>
<revision>7.0</revision>
<changelist>-SNAPSHOT</changelist>
<jetty.version>10.0.22</jetty.version>
<jetty.version>12.0.12</jetty.version>
<slf4j.version>2.0.16</slf4j.version>
<gitHubRepo>jenkinsci/winstone</gitHubRepo>
<spotless.check.skip>false</spotless.check.skip>
<!-- TODO until we are ready to ship Winstone 7 with Jetty 12 EE 8 -->
<maven.compiler.release>11</maven.compiler.release>
</properties>

<dependencyManagement>
Expand All @@ -54,6 +52,13 @@
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.ee8</groupId>
<artifactId>jetty-ee8-bom</artifactId>
<version>${jetty.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- TODO SLF4J-437 use BOM -->
<dependency>
<groupId>org.slf4j</groupId>
Expand Down Expand Up @@ -101,10 +106,6 @@
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-unixdomain-server</artifactId>
Expand All @@ -114,21 +115,25 @@
<artifactId>jetty-util</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp</artifactId>
<groupId>org.eclipse.jetty.ee8</groupId>
<artifactId>jetty-ee8-servlet</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.http2</groupId>
<artifactId>http2-hpack</artifactId>
<groupId>org.eclipse.jetty.ee8</groupId>
<artifactId>jetty-ee8-webapp</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.ee8.websocket</groupId>
<artifactId>jetty-ee8-websocket-jetty-server</artifactId>
<!-- or jetty-ee8-websocket-javax-server -->
</dependency>
<dependency>
<groupId>org.eclipse.jetty.http2</groupId>
<artifactId>http2-server</artifactId>
<artifactId>jetty-http2-hpack</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-jetty-server</artifactId>
<!-- or websocket-javax-server -->
<groupId>org.eclipse.jetty.http2</groupId>
<artifactId>jetty-http2-server</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
Expand Down
33 changes: 15 additions & 18 deletions src/main/java/winstone/HostConfiguration.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,12 @@
import java.util.jar.JarFile;
import java.util.logging.Level;
import javax.servlet.SessionTrackingMode;
import org.eclipse.jetty.http.MimeTypes;
import org.eclipse.jetty.ee8.webapp.WebAppContext;
import org.eclipse.jetty.ee8.websocket.server.config.JettyWebSocketServletContainerInitializer;
import org.eclipse.jetty.security.LoginService;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.RequestLog;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.RequestLogHandler;
import org.eclipse.jetty.server.handler.gzip.GzipHandler;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.websocket.server.config.JettyWebSocketServletContainerInitializer;
import winstone.cmdline.CompressionScheme;
import winstone.cmdline.Option;

Expand All @@ -55,7 +52,6 @@ public class HostConfiguration {
private Map<String, String> args;
private Map<String, WebAppContext> webapps;
private ClassLoader commonLibCL;
private MimeTypes mimeTypes = new MimeTypes();
private final LoginService loginService;

public HostConfiguration(Server server, String hostname, ClassLoader commonLibCL, @NonNull Map<String, String> args)
Expand Down Expand Up @@ -85,7 +81,11 @@ public HostConfiguration(Server server, String hostname, ClassLoader commonLibCL
// trim off the trailing '/' that Jetty doesn't like
prefix = prefix.substring(0, prefix.length() - 1);
}
Handler handler = configureAccessLog(create(getWebRoot(webroot, warfile), prefix), "webapp");
WebAppContext webAppContext = create(getWebRoot(webroot, warfile), prefix);
RequestLog requestLog = configureAccessLog("webapp");
if (requestLog != null) {
server.setRequestLog(requestLog);
}

{ // load additional mime types
loadBuiltinMimeTypes();
Expand All @@ -100,7 +100,7 @@ public HostConfiguration(Server server, String hostname, ClassLoader commonLibCL
}
String extension = mapping.substring(0, delimPos);
String mimeType = mapping.substring(delimPos + 1);
this.mimeTypes.addMimeMapping(extension.toLowerCase(), mimeType);
server.getMimeTypes().addMimeMapping(extension.toLowerCase(), mimeType);
}
}
}
Expand All @@ -109,11 +109,11 @@ public HostConfiguration(Server server, String hostname, ClassLoader commonLibCL
switch (compressionScheme) {
case GZIP:
GzipHandler gzipHandler = new GzipHandler();
gzipHandler.setHandler(handler);
gzipHandler.setHandler(webAppContext);
server.setHandler(gzipHandler);
break;
case NONE:
server.setHandler(handler);
server.setHandler(webAppContext);
break;
default:
throw new IllegalArgumentException("Unexpected compression scheme: " + compressionScheme);
Expand All @@ -132,7 +132,8 @@ private void loadBuiltinMimeTypes() {
Properties props = new Properties();
props.load(in);
for (Entry<Object, Object> e : props.entrySet()) {
mimeTypes.addMimeMapping(e.getKey().toString(), e.getValue().toString());
server.getMimeTypes()
.addMimeMapping(e.getKey().toString(), e.getValue().toString());
}
} catch (IOException e) {
throw new UncheckedIOException("Failed to load the built-in MIME types", e);
Expand All @@ -143,24 +144,21 @@ private void loadBuiltinMimeTypes() {
* @param webAppName
* Unique name given to the access logger.
*/
private Handler configureAccessLog(Handler handler, String webAppName) {
private RequestLog configureAccessLog(String webAppName) {
try {
Class<? extends RequestLog> loggerClass =
Option.ACCESS_LOGGER_CLASSNAME.get(args, RequestLog.class, commonLibCL);
if (loggerClass != null) {
// Build the realm
Constructor<? extends RequestLog> loggerConstr = loggerClass.getConstructor(String.class, Map.class);
RequestLogHandler rlh = new RequestLogHandler();
rlh.setHandler(handler);
rlh.setRequestLog(loggerConstr.newInstance(webAppName, args));
return rlh;
return loggerConstr.newInstance(webAppName, args);
} else {
Logger.log(Level.FINER, Launcher.RESOURCES, "WebAppConfig.LoggerDisabled");
}
} catch (Throwable err) {
Logger.log(Level.SEVERE, Launcher.RESOURCES, "WebAppConfig.LoggerError", "", err);
}
return handler;
return null;
}

private WebAppContext create(File app, String prefix) {
Expand Down Expand Up @@ -199,7 +197,6 @@ public void postConfigure() throws Exception {
wac.getSecurityHandler().setLoginService(loginService);
wac.setThrowUnavailableOnStartupException(
true); // if boot fails, abort the process instead of letting empty Jetty run
wac.setMimeTypes(mimeTypes);
wac.getSessionHandler().setSessionTrackingModes(Set.of(SessionTrackingMode.COOKIE));
wac.getSessionHandler().setSessionCookie(WinstoneSession.SESSION_COOKIE_NAME);
this.webapps.put(wac.getContextPath(), wac);
Expand Down
12 changes: 3 additions & 9 deletions src/main/java/winstone/HttpsConnectorFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.HandlerList;
import org.eclipse.jetty.server.handler.SecuredRedirectHandler;
import winstone.cmdline.Option;

Expand Down Expand Up @@ -40,14 +39,9 @@ public Connector start(Map<String, String> args, Server server) throws IOExcepti
if (currentHandler == null) {
server.setHandler(new SecuredRedirectHandler());
} else {
if (currentHandler instanceof HandlerList) {
((HandlerList) currentHandler).addHandler(new SecuredRedirectHandler());
} else {
HandlerList handlers = new HandlerList();
handlers.addHandler(new SecuredRedirectHandler());
handlers.addHandler(currentHandler);
server.setHandler(handlers);
}
Handler.Wrapper securedRedirectHandler = new SecuredRedirectHandler();
securedRedirectHandler.setHandler(currentHandler);
server.setHandler(securedRedirectHandler);
}
}
configureSsl(args, server);
Expand Down
48 changes: 23 additions & 25 deletions src/main/java/winstone/accesslog/SimpleAccessLogger.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,13 @@
import java.nio.file.Files;
import java.nio.file.InvalidPathException;
import java.nio.file.StandardOpenOption;
import java.security.Principal;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.logging.Level;
import org.eclipse.jetty.server.Authentication;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.RequestLog;
import org.eclipse.jetty.server.Response;
Expand Down Expand Up @@ -95,44 +96,41 @@ public SimpleAccessLogger(String webAppName, Map<String, String> startupArgs) th

@Override
public void log(Request request, Response response) {
String uriLine = request.getMethod() + " " + request.getRequestURI() + " " + request.getProtocol();
String uriLine = request.getMethod() + " " + request.getHttpURI().getPath() + " "
+ request.getConnectionMetaData().getProtocol();
int status = response.getStatus();
long size = response.getContentCount();
long size = Response.getContentBytesWritten(response);
String date;
synchronized (DF) {
date = DF.format(new Date());
}

// mimic
// https://github.com/eclipse/jetty.project/blob/jetty-9.4.0.v20161208/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractNCSARequestLog.java#L130
Authentication authentication = request.getAuthentication();
String remoteUser;
if (authentication instanceof Authentication.User) {
Authentication.User user = (Authentication.User) authentication;
remoteUser = user.getUserIdentity().getUserPrincipal().getName();
} else {
remoteUser = null;
}
// https://github.com/jetty/jetty.project/blob/c5b2533fdecce21b54c6fbaf36f79bc3ba909775/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/CustomRequestLog.java#L1093-L1099
Request.AuthenticationState authenticationState = Request.getAuthenticationState(request);
Principal principal = authenticationState == null ? null : authenticationState.getUserPrincipal();

Check warning on line 111 in src/main/java/winstone/accesslog/SimpleAccessLogger.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Partially covered line

Line 111 is only partially covered, one branch is missing
String remoteUser = principal == null ? "-" : principal.getName();

Check warning on line 112 in src/main/java/winstone/accesslog/SimpleAccessLogger.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Partially covered line

Line 112 is only partially covered, one branch is missing

HttpFields httpFields = request.getHeaders();
String logLine = WinstoneResourceBundle.globalReplace(this.pattern, new String[][] {
{"###x-forwarded-for###", nvl(request.getHeader("X-Forwarded-For"))},
{"###x-forwarded-host###", nvl(request.getHeader("X-Forwarded-Host"))},
{"###x-forwarded-proto###", nvl(request.getHeader("X-Forwarded-Proto"))},
{"###x-forwarded-protocol###", nvl(request.getHeader("X-Forwarded-Protocol"))},
{"###x-forwarded-server###", nvl(request.getHeader("X-Forwarded-Server"))},
{"###x-forwarded-ssl###", nvl(request.getHeader("X-Forwarded-Ssl"))},
{"###x-requested-with###", nvl(request.getHeader("X-Requested-With"))},
{"###x-do-not-track###", nvl(request.getHeader("X-Do-Not-Track"))},
{"###dnt###", nvl(request.getHeader("DNT"))},
{"###via###", nvl(request.getHeader("Via"))},
{"###ip###", request.getRemoteHost()},
{"###x-forwarded-for###", nvl(httpFields.get("X-Forwarded-For"))},
{"###x-forwarded-host###", nvl(httpFields.get("X-Forwarded-Host"))},
{"###x-forwarded-proto###", nvl(httpFields.get("X-Forwarded-Proto"))},
{"###x-forwarded-protocol###", nvl(httpFields.get("X-Forwarded-Protocol"))},
{"###x-forwarded-server###", nvl(httpFields.get("X-Forwarded-Server"))},
{"###x-forwarded-ssl###", nvl(httpFields.get("X-Forwarded-Ssl"))},
{"###x-requested-with###", nvl(httpFields.get("X-Requested-With"))},
{"###x-do-not-track###", nvl(httpFields.get("X-Do-Not-Track"))},
{"###dnt###", nvl(httpFields.get("DNT"))},
{"###via###", nvl(httpFields.get("Via"))},
{"###ip###", Request.getRemoteAddr(request)},
{"###user###", nvl(remoteUser)},
{"###time###", "[" + date + "]"},
{"###uriLine###", uriLine},
{"###status###", "" + status},
{"###size###", "" + size},
{"###referer###", nvl(request.getHeader("Referer"))},
{"###userAgent###", nvl(request.getHeader("User-Agent"))}
{"###referer###", nvl(httpFields.get("Referer"))},
{"###userAgent###", nvl(httpFields.get("User-Agent"))}
});
this.outWriter.println(logLine);
}
Expand Down
Loading

0 comments on commit 400eeee

Please sign in to comment.