Skip to content

Commit e8e2d4d

Browse files
committed
chore(implementation)!: use Jetty-12 core without servlets
Port the invoker to upgrade to Eclipse Jetty-12 version 12. Specifically using the new core APIs of Eclipse Jetty-12 that allow the overhead of a Servlet container to be avoided. BREAKING CHANGE: use Java 17 or above, as required by Eclipse Jetty-12.
1 parent 5328718 commit e8e2d4d

File tree

4 files changed

+29
-39
lines changed

4 files changed

+29
-39
lines changed

invoker/core/src/main/java/com/google/cloud/functions/invoker/http/HttpRequestImpl.java

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@
1414

1515
package com.google.cloud.functions.invoker.http;
1616

17-
import static java.util.stream.Collectors.toMap;
18-
1917
import com.google.cloud.functions.HttpRequest;
2018
import java.io.BufferedReader;
2119
import java.io.IOException;
@@ -25,14 +23,15 @@
2523
import java.nio.charset.StandardCharsets;
2624
import java.util.ArrayList;
2725
import java.util.Collection;
26+
import java.util.Collections;
27+
import java.util.HashMap;
2828
import java.util.List;
2929
import java.util.Map;
3030
import java.util.Optional;
3131
import java.util.TreeMap;
3232
import java.util.concurrent.ExecutionException;
3333
import java.util.regex.Matcher;
3434
import java.util.regex.Pattern;
35-
import java.util.stream.StreamSupport;
3635
import org.eclipse.jetty.http.HttpField;
3736
import org.eclipse.jetty.http.HttpFields;
3837
import org.eclipse.jetty.http.HttpHeader;
@@ -41,10 +40,12 @@
4140
import org.eclipse.jetty.http.MultiPartFormData;
4241
import org.eclipse.jetty.io.Content;
4342
import org.eclipse.jetty.server.Request;
44-
import org.eclipse.jetty.util.Fields.Field;
43+
import org.eclipse.jetty.util.Fields;
4544

4645
public class HttpRequestImpl implements HttpRequest {
4746
private final Request request;
47+
private InputStream inputStream;
48+
private BufferedReader reader;
4849

4950
public HttpRequestImpl(Request request) {
5051
this.request = request;
@@ -72,9 +73,15 @@ public Optional<String> getQuery() {
7273

7374
@Override
7475
public Map<String, List<String>> getQueryParameters() {
76+
Fields fields = Request.extractQueryParameters(request);
77+
if (fields.isEmpty()) {
78+
return Collections.emptyMap();
79+
}
7580

76-
return Request.extractQueryParameters(request).stream()
77-
.collect(toMap(Field::getName, Field::getValues));
81+
Map<String, List<String>> map = new HashMap<>();
82+
fields.forEach(field -> map.put(field.getName(),
83+
Collections.unmodifiableList(field.getValues())));
84+
return Collections.unmodifiableMap(map);
7885
}
7986

8087
@Override
@@ -94,9 +101,14 @@ public Map<String, HttpPart> getParts() {
94101
parser.setMaxMemoryFileSize(-1);
95102
return parser.parse(request);
96103
}).get();
97-
return StreamSupport.stream(parts.spliterator(), false)
98-
.map(HttpPartImpl::new)
99-
.collect(toMap(HttpPartImpl::getName, p -> p));
104+
105+
if (parts.size() == 0) {
106+
return Collections.emptyMap();
107+
}
108+
109+
Map<String, HttpPart> map = new HashMap<>();
110+
parts.forEach(part -> map.put(part.getName(), new HttpPartImpl(part)));
111+
return Collections.unmodifiableMap(map);
100112
} catch (InterruptedException | ExecutionException e) {
101113
throw new RuntimeException(e);
102114
}
@@ -118,9 +130,6 @@ public Optional<String> getCharacterEncoding() {
118130
return Optional.ofNullable(charset == null ? null : charset.name());
119131
}
120132

121-
private InputStream inputStream;
122-
private BufferedReader reader;
123-
124133
@Override
125134
public InputStream getInputStream() throws IOException {
126135
if (reader != null) {

invoker/core/src/main/java/com/google/cloud/functions/invoker/http/HttpResponseImpl.java

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@
2121
import java.io.OutputStream;
2222
import java.nio.charset.Charset;
2323
import java.nio.charset.StandardCharsets;
24-
import java.util.ArrayList;
25-
import java.util.Collection;
2624
import java.util.List;
2725
import java.util.Map;
2826
import java.util.Objects;
@@ -34,6 +32,8 @@
3432

3533
public class HttpResponseImpl implements HttpResponse {
3634
private final Response response;
35+
private OutputStream outputStream;
36+
private BufferedWriter writer;
3737

3838
public HttpResponseImpl(Response response) {
3939
this.response = response;
@@ -70,13 +70,6 @@ public Map<String, List<String>> getHeaders() {
7070
return HttpRequestImpl.toStringListMap(response.getHeaders());
7171
}
7272

73-
private static <T> List<T> list(Collection<T> collection) {
74-
return (collection instanceof List<?>) ? (List<T>) collection : new ArrayList<>(collection);
75-
}
76-
77-
private OutputStream outputStream;
78-
private BufferedWriter writer;
79-
8073
@Override
8174
public OutputStream getOutputStream() {
8275
if (writer != null) {

invoker/core/src/main/java/com/google/cloud/functions/invoker/runner/Invoker.java

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@
5454
import org.eclipse.jetty.server.Response;
5555
import org.eclipse.jetty.server.Server;
5656
import org.eclipse.jetty.server.ServerConnector;
57-
import org.eclipse.jetty.server.handler.ContextHandler;
5857
import org.eclipse.jetty.server.handler.ErrorHandler;
5958
import org.eclipse.jetty.util.Callback;
6059
import org.eclipse.jetty.util.thread.QueuedThreadPool;
@@ -234,7 +233,7 @@ ClassLoader getFunctionClassLoader() {
234233
* unit or integration test, use {@link #startTestServer()} instead.
235234
*
236235
* @see #stopServer()
237-
* @throws Exception
236+
* @throws Exception If there was a problem starting the server
238237
*/
239238
public void startServer() throws Exception {
240239
startServer(true);
@@ -266,7 +265,7 @@ public void startServer() throws Exception {
266265
* }</pre>
267266
*
268267
* @see #stopServer()
269-
* @throws Exception
268+
* @throws Exception If there was a problem starting the server
270269
*/
271270
public void startTestServer() throws Exception {
272271
startServer(false);
@@ -292,15 +291,13 @@ public boolean handle(Request request, Response response, Callback callback) {
292291
connector.setReuseAddress(true);
293292
connector.setReusePort(true);
294293
server.setConnectors(new Connector[] {connector});
295-
296-
ContextHandler contextHandler = new ContextHandler("/");
297-
server.setHandler(NotFoundHandler.forServlet(contextHandler));
294+
server.setHandler(new NotFoundHandler());
298295

299296
Class<?> functionClass = loadFunctionClass();
300297

301298
Handler handler;
302299
if (functionSignatureType == null) {
303-
handler = servletForDeducedSignatureType(functionClass);
300+
handler = handlerForDeducedSignatureType(functionClass);
304301
} else {
305302
switch (functionSignatureType) {
306303
case "http":
@@ -327,8 +324,6 @@ public boolean handle(Request request, Response response, Callback callback) {
327324
}
328325
}
329326

330-
// TODO servletHolder.getRegistration().setMultipartConfig(new MultipartConfigElement(""));
331-
332327
server.getTail().setHandler(handler);
333328
server.start();
334329
logServerInfo();
@@ -376,7 +371,7 @@ private Class<?> loadFunctionClass() throws ClassNotFoundException {
376371
}
377372
}
378373

379-
private Handler servletForDeducedSignatureType(Class<?> functionClass) {
374+
private Handler handlerForDeducedSignatureType(Class<?> functionClass) {
380375
if (HttpFunction.class.isAssignableFrom(functionClass)) {
381376
return HttpFunctionExecutor.forClass(functionClass);
382377
}
@@ -456,16 +451,11 @@ private static boolean isGcf() {
456451

457452
/**
458453
* Wrapper that intercepts requests for {@code /favicon.ico} and {@code /robots.txt} and causes
459-
* them to produce a 404 status. Otherwise they would be sent to the function code, like any other
454+
* them to produce a 404 status. Otherwise, they would be sent to the function code, like any other
460455
* URL, meaning that someone testing their function by using a browser as an HTTP client can see
461456
* two requests, one for {@code /favicon.ico} and one for {@code /} (or whatever).
462457
*/
463458
private static class NotFoundHandler extends Handler.Wrapper {
464-
static NotFoundHandler forServlet(ContextHandler servletHandler) {
465-
NotFoundHandler handler = new NotFoundHandler();
466-
handler.setHandler(servletHandler);
467-
return handler;
468-
}
469459

470460
private static final Set<String> NOT_FOUND_PATHS =
471461
new HashSet<>(Arrays.asList("/favicon.ico", "/robots.txt"));
@@ -507,7 +497,6 @@ private static class OnlyApiClassLoader extends ClassLoader {
507497
protected Class<?> findClass(String name) throws ClassNotFoundException {
508498
String prefix = "com.google.cloud.functions.";
509499
if ((name.startsWith(prefix) && Character.isUpperCase(name.charAt(prefix.length())))
510-
|| name.startsWith("javax.servlet.")
511500
|| isCloudEventsApiClass(name)) {
512501
return runtimeClassLoader.loadClass(name);
513502
}

invoker/core/src/test/java/com/google/cloud/functions/invoker/http/HttpTest.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@ private static class SimpleServer implements AutoCloseable {
9393
SimpleServer(Handler handler) throws Exception {
9494
this.server = new Server(serverPort);
9595
server.setHandler(handler);
96-
// TODO servletHolder.getRegistration().setMultipartConfig(new MultipartConfigElement("tiddly"));
9796
server.start();
9897
}
9998

0 commit comments

Comments
 (0)