handleRawRequest method
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();
}
}
});
});
}