2929import io .cloudevents .http .HttpMessageFactory ;
3030import java .io .BufferedReader ;
3131import java .io .IOException ;
32+ import java .io .InputStreamReader ;
3233import java .io .Reader ;
3334import java .lang .reflect .Type ;
35+ import java .nio .charset .StandardCharsets ;
3436import java .time .OffsetDateTime ;
3537import java .time .format .DateTimeFormatter ;
3638import java .util .ArrayList ;
3739import java .util .Arrays ;
38- import java .util .Collections ;
3940import java .util .List ;
4041import java .util .Map ;
42+ import java .util .Objects ;
4143import java .util .Optional ;
4244import java .util .TreeMap ;
4345import java .util .logging .Level ;
4446import java .util .logging .Logger ;
45- import javax .servlet .http .HttpServlet ;
46- import javax .servlet .http .HttpServletRequest ;
47- import javax .servlet .http .HttpServletResponse ;
47+ import org .eclipse .jetty .http .HttpField ;
48+ import org .eclipse .jetty .http .HttpHeader ;
49+ import org .eclipse .jetty .http .HttpStatus ;
50+ import org .eclipse .jetty .io .Content ;
51+ import org .eclipse .jetty .server .Handler ;
52+ import org .eclipse .jetty .server .Request ;
53+ import org .eclipse .jetty .server .Response ;
54+ import org .eclipse .jetty .util .Callback ;
4855
4956/** Executes the user's background function. */
50- public final class BackgroundFunctionExecutor extends HttpServlet {
57+ public final class BackgroundFunctionExecutor extends Handler . Abstract {
5158 private static final Logger logger = Logger .getLogger ("com.google.cloud.functions.invoker" );
5259
5360 private final FunctionExecutor <?> functionExecutor ;
@@ -175,8 +182,10 @@ static Optional<Type> backgroundFunctionTypeArgument(
175182 .findFirst ();
176183 }
177184
178- private static Event parseLegacyEvent (HttpServletRequest req ) throws IOException {
179- try (BufferedReader bodyReader = req .getReader ()) {
185+ private static Event parseLegacyEvent (Request req ) throws IOException {
186+ try (BufferedReader bodyReader = new BufferedReader (
187+ new InputStreamReader (Content .Source .asInputStream (req ),
188+ Objects .requireNonNullElse (Request .getCharset (req ), StandardCharsets .ISO_8859_1 )))) {
180189 return parseLegacyEvent (bodyReader );
181190 }
182191 }
@@ -223,7 +232,7 @@ private static Context contextFromCloudEvent(CloudEvent cloudEvent) {
223232 * for the various triggers. CloudEvents are ones that follow the standards defined by <a
224233 * href="https://cloudevents.io">cloudevents.io</a>.
225234 *
226- * @param <CloudEventDataT> the type to be used in the {@link Unmarshallers} call when
235+ * @param <CloudEventDataT> the type to be used in the {code Unmarshallers} call when
227236 * unmarshalling this event, if it is a CloudEvent.
228237 */
229238 private abstract static class FunctionExecutor <CloudEventDataT > {
@@ -320,20 +329,23 @@ void serviceCloudEvent(CloudEvent cloudEvent) throws Exception {
320329
321330 /** Executes the user's background function. This can handle all HTTP methods. */
322331 @ Override
323- public void service ( HttpServletRequest req , HttpServletResponse res ) throws IOException {
324- String contentType = req .getContentType ( );
332+ public boolean handle ( Request req , Response res , Callback callback ) throws Exception {
333+ String contentType = req .getHeaders (). get ( HttpHeader . CONTENT_TYPE );
325334 try {
326335 if ((contentType != null && contentType .startsWith ("application/cloudevents+json" ))
327- || req .getHeader ("ce-specversion" ) != null ) {
336+ || req .getHeaders (). get ("ce-specversion" ) != null ) {
328337 serviceCloudEvent (req );
329338 } else {
330339 serviceLegacyEvent (req );
331340 }
332- res .setStatus (HttpServletResponse .SC_OK );
341+ res .setStatus (HttpStatus .OK_200 );
342+ callback .succeeded ();
333343 } catch (Throwable t ) {
334- res .setStatus (HttpServletResponse .SC_INTERNAL_SERVER_ERROR );
335344 logger .log (Level .SEVERE , "Failed to execute " + functionExecutor .functionName (), t );
345+ res .setStatus (HttpStatus .INTERNAL_SERVER_ERROR_500 );
346+ callback .succeeded ();
336347 }
348+ return true ;
337349 }
338350
339351 private enum CloudEventKind {
@@ -347,10 +359,11 @@ private enum CloudEventKind {
347359 * @param <CloudEventT> a fake type parameter, which corresponds to the type parameter of {@link
348360 * FunctionExecutor}.
349361 */
350- private <CloudEventT > void serviceCloudEvent (HttpServletRequest req ) throws Exception {
362+ private <CloudEventT > void serviceCloudEvent (Request req ) throws Exception {
351363 @ SuppressWarnings ("unchecked" )
352364 FunctionExecutor <CloudEventT > executor = (FunctionExecutor <CloudEventT >) functionExecutor ;
353- byte [] body = req .getInputStream ().readAllBytes ();
365+
366+ byte [] body = Content .Source .asByteArrayAsync (req , -1 ).get ();
354367 MessageReader reader = HttpMessageFactory .createReaderFromMultimap (headerMap (req ), body );
355368 // It's important not to set the context ClassLoader earlier, because MessageUtils will use
356369 // ServiceLoader.load(EventFormat.class) to find a handler to deserialize a binary CloudEvent
@@ -364,17 +377,16 @@ private <CloudEventT> void serviceCloudEvent(HttpServletRequest req) throws Exce
364377 // https://github.com/cloudevents/sdk-java/pull/259.
365378 }
366379
367- private static Map <String , List <String >> headerMap (HttpServletRequest req ) {
380+ private static Map <String , List <String >> headerMap (Request req ) {
368381 Map <String , List <String >> headerMap = new TreeMap <>(String .CASE_INSENSITIVE_ORDER );
369- for (String header : Collections .list (req .getHeaderNames ())) {
370- for (String value : Collections .list (req .getHeaders (header ))) {
371- headerMap .computeIfAbsent (header , unused -> new ArrayList <>()).add (value );
372- }
382+ for (HttpField field : req .getHeaders ()) {
383+ headerMap .computeIfAbsent (field .getName (), unused -> new ArrayList <>())
384+ .addAll (field .getValueList ());
373385 }
374386 return headerMap ;
375387 }
376388
377- private void serviceLegacyEvent (HttpServletRequest req ) throws Exception {
389+ private void serviceLegacyEvent (Request req ) throws Exception {
378390 Event event = parseLegacyEvent (req );
379391 runWithContextClassLoader (() -> functionExecutor .serviceLegacyEvent (event ));
380392 }
0 commit comments