-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adding demo of how to access Request fields during RequestLog.
- Loading branch information
Showing
3 changed files
with
313 additions
and
0 deletions.
There are no files selected for viewing
120 changes: 120 additions & 0 deletions
120
embedded/requestlog/src/main/java/examples/ParamRequestLog.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
// | ||
// ======================================================================== | ||
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others. | ||
// | ||
// This program and the accompanying materials are made available under the | ||
// terms of the Eclipse Public License v. 2.0 which is available at | ||
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 | ||
// which is available at https://www.apache.org/licenses/LICENSE-2.0. | ||
// | ||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 | ||
// ======================================================================== | ||
// | ||
|
||
package examples; | ||
|
||
import java.io.IOException; | ||
import java.util.concurrent.ExecutionException; | ||
|
||
import org.eclipse.jetty.http.HttpHeader; | ||
import org.eclipse.jetty.server.FormFields; | ||
import org.eclipse.jetty.server.Request; | ||
import org.eclipse.jetty.server.RequestLog; | ||
import org.eclipse.jetty.server.Response; | ||
import org.eclipse.jetty.util.Fields; | ||
import org.eclipse.jetty.util.component.ContainerLifeCycle; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
public class ParamRequestLog extends ContainerLifeCycle implements RequestLog | ||
{ | ||
private static final Logger LOG = LoggerFactory.getLogger(ParamRequestLog.class); | ||
private final RequestLog.Writer logWriter; | ||
|
||
public ParamRequestLog(RequestLog.Writer requestLogWriter) | ||
{ | ||
this.logWriter = requestLogWriter; | ||
installBean(this.logWriter); | ||
} | ||
|
||
@Override | ||
public void log(Request request, Response response) | ||
{ | ||
try | ||
{ | ||
StringBuilder entry = new StringBuilder(); | ||
|
||
entry.append(request.getMethod()); | ||
entry.append(" "); | ||
entry.append(request.getHttpURI().toString()); | ||
entry.append(" "); | ||
|
||
long requestContentLength = request.getHeaders().getLongField(HttpHeader.CONTENT_LENGTH); | ||
if (requestContentLength != -1) | ||
{ | ||
entry.append("(Length:%,d) ".formatted(requestContentLength)); | ||
} | ||
|
||
entry.append(response.getStatus()); | ||
entry.append(" "); | ||
|
||
Fields queryFields = getRequestQueryFields(request); | ||
appendFields(entry, "Query", queryFields); | ||
|
||
entry.append(" "); | ||
|
||
Fields formFields = getRequestFormFields(request); | ||
appendFields(entry, "Form", formFields); | ||
|
||
logWriter.write(entry.toString()); | ||
} | ||
catch (Throwable e) | ||
{ | ||
LOG.warn("Unable to log request", e); | ||
} | ||
} | ||
|
||
private void appendFields(Appendable appendable, String type, Fields fields) throws IOException | ||
{ | ||
appendable.append("["); | ||
appendable.append(type); | ||
if (fields == null) | ||
{ | ||
appendable.append(": <null>]"); | ||
return; | ||
} | ||
|
||
appendable.append(".size=%d".formatted(fields.getSize())); | ||
for (Fields.Field field: fields) | ||
{ | ||
appendable.append(", %s=%s".formatted(field.getName(), field.getValue())); | ||
} | ||
appendable.append("]"); | ||
} | ||
|
||
private Fields getRequestFormFields(Request request) | ||
{ | ||
Object attr = request.getAttribute(FormFields.class.getName()); | ||
if (attr instanceof FormFields futureFormFields) | ||
{ | ||
try | ||
{ | ||
return futureFormFields.get(); | ||
} | ||
catch (InterruptedException | ExecutionException e) | ||
{ | ||
return null; | ||
} | ||
} | ||
else if (attr instanceof Fields fields) | ||
{ | ||
return fields; | ||
} | ||
return null; | ||
} | ||
|
||
private Fields getRequestQueryFields(Request request) | ||
{ | ||
return Request.extractQueryParameters(request); | ||
} | ||
} |
88 changes: 88 additions & 0 deletions
88
embedded/requestlog/src/main/java/examples/ParamRequestLogDemo.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
// | ||
// ======================================================================== | ||
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others. | ||
// | ||
// This program and the accompanying materials are made available under the | ||
// terms of the Eclipse Public License v. 2.0 which is available at | ||
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 | ||
// which is available at https://www.apache.org/licenses/LICENSE-2.0. | ||
// | ||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 | ||
// ======================================================================== | ||
// | ||
|
||
package examples; | ||
|
||
import org.eclipse.jetty.http.HttpHeader; | ||
import org.eclipse.jetty.io.Content; | ||
import org.eclipse.jetty.server.Handler; | ||
import org.eclipse.jetty.server.Request; | ||
import org.eclipse.jetty.server.RequestLog; | ||
import org.eclipse.jetty.server.Response; | ||
import org.eclipse.jetty.server.Server; | ||
import org.eclipse.jetty.server.Slf4jRequestLogWriter; | ||
import org.eclipse.jetty.server.handler.ContextHandler; | ||
import org.eclipse.jetty.server.handler.ContextHandlerCollection; | ||
import org.eclipse.jetty.util.Callback; | ||
import org.eclipse.jetty.util.Fields; | ||
|
||
public class ParamRequestLogDemo | ||
{ | ||
public static void main(String[] args) throws Exception | ||
{ | ||
Server server = ParamRequestLogDemo.newServer(8080); | ||
server.start(); | ||
server.join(); | ||
} | ||
|
||
public static Server newServer(int port) | ||
{ | ||
Server server = new Server(port); | ||
|
||
Handler.Sequence handlers = new Handler.Sequence(); | ||
server.setHandler(handlers); | ||
|
||
ContextHandlerCollection contexts = new ContextHandlerCollection(); | ||
server.setHandler(contexts); | ||
|
||
contexts.addHandler(new ContextHandler(new NoReadParamHandler(), "/no-read")); | ||
contexts.addHandler(new ContextHandler(new ReadParamHandler(), "/read")); | ||
|
||
Slf4jRequestLogWriter requestLoggingWriter = new Slf4jRequestLogWriter(); | ||
requestLoggingWriter.setLoggerName("EXAMPLE.REQUESTLOG"); | ||
RequestLog requestLog = new ParamRequestLog(requestLoggingWriter); | ||
server.setRequestLog(requestLog); | ||
|
||
return server; | ||
} | ||
|
||
public static class ReadParamHandler extends Handler.Abstract | ||
{ | ||
@Override | ||
public boolean handle(Request request, Response response, Callback callback) throws Exception | ||
{ | ||
Fields params = Request.getParameters(request); | ||
StringBuilder reply = new StringBuilder("Params.size=%d%n".formatted(params.getSize())); | ||
for (Fields.Field field: params) | ||
{ | ||
reply.append("Param[%s]=%s%n".formatted(field.getName(), field.getValue())); | ||
} | ||
response.getHeaders().put(HttpHeader.CONTENT_TYPE, "text/plain; charset=utf-8"); | ||
Content.Sink.write(response, true, reply.toString(), callback); | ||
return true; | ||
} | ||
} | ||
|
||
public static class NoReadParamHandler extends Handler.Abstract | ||
{ | ||
@Override | ||
public boolean handle(Request request, Response response, Callback callback) throws Exception | ||
{ | ||
long requestContentLength = request.getHeaders().getLongField(HttpHeader.CONTENT_LENGTH); | ||
String reply = "Didn't read params, Request.header[content-length]=%d%n".formatted(requestContentLength); | ||
response.getHeaders().put(HttpHeader.CONTENT_TYPE, "text/plain; charset=utf-8"); | ||
Content.Sink.write(response, true, reply, callback); | ||
return true; | ||
} | ||
} | ||
} |
105 changes: 105 additions & 0 deletions
105
embedded/requestlog/src/test/java/examples/ParamRequestLogDemoTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
// | ||
// ======================================================================== | ||
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others. | ||
// | ||
// This program and the accompanying materials are made available under the | ||
// terms of the Eclipse Public License v. 2.0 which is available at | ||
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 | ||
// which is available at https://www.apache.org/licenses/LICENSE-2.0. | ||
// | ||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 | ||
// ======================================================================== | ||
// | ||
|
||
package examples; | ||
|
||
import java.io.IOException; | ||
import java.net.http.HttpClient; | ||
import java.net.http.HttpRequest; | ||
import java.net.http.HttpResponse; | ||
|
||
import org.eclipse.jetty.server.Server; | ||
import org.eclipse.jetty.util.component.LifeCycle; | ||
import org.junit.jupiter.api.AfterEach; | ||
import org.junit.jupiter.api.BeforeEach; | ||
import org.junit.jupiter.params.ParameterizedTest; | ||
import org.junit.jupiter.params.provider.CsvSource; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import static java.nio.charset.StandardCharsets.UTF_8; | ||
import static org.hamcrest.MatcherAssert.assertThat; | ||
import static org.hamcrest.Matchers.is; | ||
|
||
public class ParamRequestLogDemoTest | ||
{ | ||
private static final Logger LOG = LoggerFactory.getLogger(ParamRequestLogDemoTest.class); | ||
private Server server; | ||
|
||
@BeforeEach | ||
public void startServer() throws Exception | ||
{ | ||
LOG.warn("===== SEE Console Logging Output for \":INFO :EXAMPLE.REQUESTLOG:\" entries ====="); | ||
|
||
server = ParamRequestLogDemo.newServer(0); | ||
server.start(); | ||
} | ||
|
||
@AfterEach | ||
public void stopServer() | ||
{ | ||
LifeCycle.stop(server); | ||
} | ||
|
||
/** | ||
* Demonstrate behavior with request that have no form sent (in request body). | ||
*/ | ||
@ParameterizedTest | ||
@CsvSource(delimiter = '|', textBlock = """ | ||
# Path | Expected Response Status | ||
/read/ | 200 | ||
/read/?name=Bob | 200 | ||
/no-read/ | 200 | ||
/no-read/?name=Carl | 200 | ||
/no-read/?name=Anne&role=Chef | 200 | ||
/other/ | 404 | ||
""") | ||
public void testRequestNoForm(String path, int expectedStatus) throws IOException, InterruptedException | ||
{ | ||
HttpClient client = HttpClient.newBuilder().build(); | ||
|
||
HttpRequest request = HttpRequest.newBuilder() | ||
.uri(server.getURI().resolve(path)) | ||
.version(HttpClient.Version.HTTP_1_1) | ||
.build(); | ||
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString(UTF_8)); | ||
assertThat(response.statusCode(), is(expectedStatus)); | ||
} | ||
|
||
/** | ||
* Demonstrate behavior with request that has a form sent (as a request body). | ||
*/ | ||
@ParameterizedTest | ||
@CsvSource(delimiter = '|', textBlock = """ | ||
# Path | Form Data | Expected Response Status | ||
/read/ | co=Canada | 200 | ||
/read/?name=Bob | co=Aussie | 200 | ||
/no-read/ | co=Swiss | 200 | ||
/no-read/?name=Carl | co=Aruba | 200 | ||
/no-read/?name=Anne&role=Chef | co=Sweden | 200 | ||
/other/ | co=France | 404 | ||
""") | ||
public void testRequestUrlForm(String path, String formdata, int expectedStatus) throws IOException, InterruptedException | ||
{ | ||
HttpClient client = HttpClient.newBuilder().build(); | ||
|
||
HttpRequest request = HttpRequest.newBuilder() | ||
.uri(server.getURI().resolve(path)) | ||
.version(HttpClient.Version.HTTP_1_1) | ||
.header("Content-Type", "application/x-www-form-urlencoded") | ||
.POST(HttpRequest.BodyPublishers.ofString(formdata)) | ||
.build(); | ||
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString(UTF_8)); | ||
assertThat(response.statusCode(), is(expectedStatus)); | ||
} | ||
} |