handleRawRequest method

Future handleRawRequest(
  1. Request request,
  2. Response response
)

Handles a single request.

Implementation

Future handleRawRequest(Request request, Response response) {
  app.logger.info('[Server] Called handleRawRequest');

  return createRequestContext(request, response).then((req) {
    return createResponseContext(request, response, req).then((res) {
      Future handle() {
        var path = req.path;
        if (path == '/') path = '';

        Tuple4<List, Map<String, dynamic>, ParseResult<RouteResult>,
            MiddlewarePipeline> resolveTuple() {
          var r = app.optimizedRouter;
          var resolved =
              r.resolveAbsolute(path, method: req.method, strip: false);
          var pipeline = MiddlewarePipeline<RequestHandler>(resolved);
          return Tuple4(
            pipeline.handlers,
            resolved.fold<Map<String, dynamic>>(
                <String, dynamic>{}, (out, r) => out..addAll(r.allParams)),
            //(resolved.isEmpty ? null : resolved.first.parseResult),
            resolved.first.parseResult,
            pipeline,
          );
        }

        var cacheKey = req.method + path;
        var tuple = app.environment.isProduction
            ? app.handlerCache.putIfAbsent(cacheKey, resolveTuple)
            : resolveTuple();
        var line = tuple.item4 as MiddlewarePipeline<RequestHandler>;
        var it = MiddlewarePipelineIterator<RequestHandler>(line);

        req.params.addAll(tuple.item2);

        req.container
          ?..registerSingleton<RequestContext>(req)
          ..registerSingleton<ResponseContext>(res)
          ..registerSingleton<MiddlewarePipeline>(tuple.item4)
          ..registerSingleton<MiddlewarePipeline<RequestHandler>>(line)
          ..registerSingleton<MiddlewarePipelineIterator>(it)
          ..registerSingleton<MiddlewarePipelineIterator<RequestHandler>>(it)
          ..registerSingleton<ParseResult<RouteResult>?>(tuple.item3)
          ..registerSingleton<ParseResult?>(tuple.item3);

        if (!app.environment.isProduction) {
          req.container?.registerSingleton<Stopwatch>(Stopwatch()..start());
        }

        return runPipeline(it, req, res, app)
            .then((_) => sendResponse(request, response, req, res));
      }

      if (useZone == false) {
        Future f;

        try {
          f = handle();
        } catch (e, st) {
          f = Future.error(e, st);
        }

        return f.catchError((e, StackTrace st) {
          if (e is FormatException) {
            throw AngelHttpException.badRequest(message: e.message)
              ..stackTrace = st;
          }
          throw AngelHttpException(
              stackTrace: st,
              statusCode: (e is AngelHttpException) ? e.statusCode : 500,
              message: e?.toString() ?? '500 Internal Server Error');
        }, test: (e) => e is AngelHttpException).catchError(
            (ee, StackTrace st) {
          //print(">>>> Framework error: $ee");
          //var t = (st).runtimeType;
          //print(">>>> StackTrace: $t");
          AngelHttpException e;
          if (ee is AngelHttpException) {
            e = ee;
          } else {
            e = AngelHttpException(
                stackTrace: st,
                statusCode: 500,
                message: ee?.toString() ?? '500 Internal Server Error');
          }

          var error = e.error ?? e;
          var trace = Trace.from(StackTrace.current).terse;
          app.logger.severe(e.message, error, trace);

          return handleAngelHttpException(e, st, req, res, request, response);
        });
      } else {
        var zoneSpec = ZoneSpecification(
          print: (self, parent, zone, line) {
            app.logger.info(line);
          },
          handleUncaughtError: (self, parent, zone, error, stackTrace) {
            var trace = Trace.from(stackTrace).terse;

            // TODO: To be revisited
            Future(() {
              AngelHttpException e;

              if (error is FormatException) {
                e = AngelHttpException.badRequest(message: error.message);
              } else if (error is AngelHttpException) {
                e = error;
              } else {
                e = AngelHttpException(
                    stackTrace: stackTrace, message: error.toString());
              }

              app.logger.severe(e.message, error, trace);

              return handleAngelHttpException(
                  e, trace, req, res, request, response);
            }).catchError((e, StackTrace st) {
              var trace = Trace.from(st).terse;
              closeResponse(response);
              // Ideally, we won't be in a position where an absolutely fatal error occurs,
              // but if so, we'll need to log it.
              app.logger.severe(
                  'Fatal error occurred when processing $uri.', e, trace);
            });
          },
        );

        var zone = Zone.current.fork(specification: zoneSpec);
        req.container?.registerSingleton<Zone>(zone);
        req.container?.registerSingleton<ZoneSpecification>(zoneSpec);

        // If a synchronous error is thrown, it's not caught by `zone.run`,
        // so use a try/catch, and recover when need be.

        try {
          return zone.run(handle);
        } catch (e, st) {
          zone.handleUncaughtError(e, st);
          return Future.value();
        }
      }
    });
  });
}