Skip to content

Commit

Permalink
Merge pull request #12322 from jetty/jetty-12.0.x-9980-customrequestlog
Browse files Browse the repository at this point in the history
Issue #9980 - add additional codes for CustomRequestLog
  • Loading branch information
lachlan-roberts authored Oct 21, 2024
2 parents bc5d192 + a4f88fc commit 1483d14
Show file tree
Hide file tree
Showing 2 changed files with 337 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,13 @@

import org.eclipse.jetty.http.HttpCookie;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpURI;
import org.eclipse.jetty.http.QuotedCSV;
import org.eclipse.jetty.http.pathmap.PathMappings;
import org.eclipse.jetty.util.DateCache;
import org.eclipse.jetty.util.NanoTime;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.URIUtil;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject;
import org.eclipse.jetty.util.component.ContainerLifeCycle;
Expand Down Expand Up @@ -201,7 +203,6 @@
* <p>The query string, prepended with a ? if a query string exists, otherwise an empty string.</p>
* </td>
* </tr>
* <!-- TODO ATTRIBUTE LOGGING -->
* <tr>
* <td>%r</td>
* <td>
Expand All @@ -214,13 +215,13 @@
* <p>The name of the Handler or Servlet generating the response (if any).</p>
* </td>
* </tr>
* <tr>
* <tr>
* <td>%s</td>
* <td>
* <p>The HTTP response status code.</p>
* </td>
* </tr>
* <tr>
* <tr>
* <td>%{format|timeZone|locale}t</td>
* <td>
* <p>The time at which the request was received.</p>
Expand Down Expand Up @@ -262,7 +263,7 @@
* <p>The URL path requested, not including any query string.</p>
* </td>
* </tr>
* <tr>
* <tr>
* <td>%X</td>
* <td>
* <p>The connection status when response is completed:</p>
Expand All @@ -288,6 +289,39 @@
* <p>The value of the VARNAME response trailer.</p>
* </td>
* </tr>
* <tr>
* <td>%{OPTION}uri</td>
* <td>
* <p>The request URI.</p>
* <p>The parameter is optional and may have the be one of the following options:</p>
* <dl>
* <dt>%uri</dt>
* <dd>The entire request URI.</dd>
* <dt>%{-query}uri</dt>
* <dd>The entire request URI without the query.</dd>
* <dt>%{-path,-query}uri</dt>
* <dd>The request URI without path or query (so just `scheme://authority`).</dd>
* <dt>%{scheme}uri</dt>
* <dd>The scheme of the request URI.</dd>
* <dt>%{authority}uri</dt>
* <dd>The authority of the request URI.</dd>
* <dt>%{path}uri</dt>
* <dd>The path of the request URI.</dd>
* <dt>%{query}uri</dt>
* <dd>The query of the request URI.</dd>
* <dt>%{host}uri</dt>
* <dd>The host of the request URI.</dd>
* <dt>%{port}uri</dt>
* <dd>The port of the request URI.</dd>
* </dl>
* </td>
* </tr>
* <tr>
* <td>%{attributeName}attr</td>
* <td>
* <p>The value of the request attribute with the given name.</p>
* </td>
* </tr>
* </table>
* <!-- end::documentation[] -->
*/
Expand All @@ -309,6 +343,7 @@ public record LogDetail(String handlerName, String realPath)
public static final String LOG_DETAIL = CustomRequestLog.class.getName() + ".logDetail";
private static final Logger LOG = LoggerFactory.getLogger(CustomRequestLog.class);
private static final ThreadLocal<StringBuilder> _buffers = ThreadLocal.withInitial(() -> new StringBuilder(256));
private static final Pattern PATTERN = Pattern.compile("^(?:%(?<MOD>!?[0-9,]+)?(?:\\{(?<ARG>[^}]+)})?(?<CODE>(?:(?:ti)|(?:to)|(?:uri)|(?:attr)|[a-zA-Z%]))|(?<LITERAL>[^%]+))(?<REMAINING>.*)", Pattern.DOTALL | Pattern.MULTILINE);

private final RequestLog.Writer _requestLogWriter;
private final MethodHandle _logHandle;
Expand Down Expand Up @@ -444,7 +479,7 @@ protected void doStart() throws Exception

private static void append(StringBuilder buf, String s)
{
if (s == null || s.length() == 0)
if (s == null || s.isEmpty())
buf.append('-');
else
buf.append(s);
Expand Down Expand Up @@ -489,8 +524,6 @@ private static List<Token> getTokens(String formatString)
{PARAM} is an optional string parameter to the percent code.
CODE is a 1 to 2 character string corresponding to a format code.
*/
final Pattern PATTERN = Pattern.compile("^(?:%(?<MOD>!?[0-9,]+)?(?:\\{(?<ARG>[^}]+)})?(?<CODE>(?:(?:ti)|(?:to)|[a-zA-Z%]))|(?<LITERAL>[^%]+))(?<REMAINING>.*)", Pattern.DOTALL | Pattern.MULTILINE);

List<Token> tokens = new ArrayList<>();
String remaining = formatString;
while (remaining.length() > 0)
Expand Down Expand Up @@ -788,6 +821,32 @@ else if ("d".equals(arg))

yield lookup.findStatic(CustomRequestLog.class, "logResponseTrailer", logTypeArg).bindTo(arg);
}
case "uri" ->
{
if (arg == null)
arg = "";
String method = switch (arg)
{
case "" -> "logRequestHttpUri";
case "-query" -> "logRequestHttpUriWithoutQuery";
case "-path,-query" -> "logRequestHttpUriWithoutPathQuery";
case "scheme" -> "logRequestScheme";
case "authority" -> "logRequestAuthority";
case "path" -> "logUrlRequestPath";
case "query" -> "logQueryString";
case "host" -> "logRequestHttpUriHost";
case "port" -> "logRequestHttpUriPort";
default -> throw new IllegalArgumentException("Invalid arg for %uri");
};

yield lookup.findStatic(CustomRequestLog.class, method, logType);
}
case "attr" ->
{
MethodType logRequestAttribute = methodType(void.class, String.class, StringBuilder.class, Request.class, Response.class);
yield lookup.findStatic(CustomRequestLog.class, "logRequestAttribute", logRequestAttribute).bindTo(arg);
}

default -> throw new IllegalArgumentException("Unsupported code %" + code);
};

Expand Down Expand Up @@ -1139,4 +1198,74 @@ private static void logResponseTrailer(String arg, StringBuilder b, Request requ
else
b.append('-');
}

@SuppressWarnings("unused")
private static void logRequestAuthority(StringBuilder b, Request request, Response response)
{
HttpURI httpURI = request.getHttpURI();
if (httpURI.hasAuthority())
append(b, httpURI.getAuthority());
else
b.append('-');
}

@SuppressWarnings("unused")
private static void logRequestScheme(StringBuilder b, Request request, Response response)
{
append(b, request.getHttpURI().getScheme());
}

@SuppressWarnings("unused")
private static void logRequestHttpUri(StringBuilder b, Request request, Response response)
{
append(b, request.getHttpURI().toString());
}

@SuppressWarnings("unused")
private static void logRequestHttpUriWithoutQuery(StringBuilder b, Request request, Response response)
{
HttpURI.Mutable uri = HttpURI.build(request.getHttpURI()).query(null);
append(b, uri.toString());
}

@SuppressWarnings("unused")
private static void logRequestHttpUriWithoutPathQuery(StringBuilder b, Request request, Response response)
{
// HttpURI doesn't support null path so we do this manually.
HttpURI httpURI = request.getHttpURI();
if (httpURI.getScheme() != null)
b.append(httpURI.getScheme()).append(':');
if (httpURI.getHost() != null)
{
b.append("//");
if (httpURI.getUser() != null)
b.append(httpURI.getUser()).append('@');
b.append(httpURI.getHost());
}
int normalizedPort = URIUtil.normalizePortForScheme(httpURI.getScheme(), httpURI.getPort());
if (normalizedPort > 0)
b.append(':').append(normalizedPort);
}

@SuppressWarnings("unused")
private static void logRequestHttpUriHost(StringBuilder b, Request request, Response response)
{
append(b, request.getHttpURI().getHost());
}

@SuppressWarnings("unused")
private static void logRequestHttpUriPort(StringBuilder b, Request request, Response response)
{
b.append(request.getHttpURI().getPort());
}

@SuppressWarnings("unused")
private static void logRequestAttribute(String arg, StringBuilder b, Request request, Response response)
{
Object attribute = request.getAttribute(arg);
if (attribute != null)
append(b, attribute.toString());
else
b.append('-');
}
}
Loading

0 comments on commit 1483d14

Please sign in to comment.