144 lines
3 KiB
Dart
144 lines
3 KiB
Dart
import 'dart:async';
|
|
import 'dart:io';
|
|
import 'package:body_parser/body_parser.dart';
|
|
import 'package:http_parser/http_parser.dart';
|
|
import '../core/core.dart';
|
|
|
|
/// An implementation of [RequestContext] that wraps a [HttpRequest].
|
|
class HttpRequestContextImpl extends RequestContext {
|
|
ContentType _contentType;
|
|
HttpRequest _io;
|
|
String _override, _path;
|
|
|
|
@override
|
|
ContentType get contentType {
|
|
return _contentType;
|
|
}
|
|
|
|
@override
|
|
List<Cookie> get cookies {
|
|
return io.cookies;
|
|
}
|
|
|
|
@override
|
|
HttpHeaders get headers {
|
|
return io.headers;
|
|
}
|
|
|
|
@override
|
|
String get hostname {
|
|
return io.headers.value('host');
|
|
}
|
|
|
|
/// The underlying [HttpRequest] instance underneath this context.
|
|
HttpRequest get io => _io;
|
|
|
|
@override
|
|
String get method {
|
|
return _override ?? originalMethod;
|
|
}
|
|
|
|
@override
|
|
String get originalMethod {
|
|
return io.method;
|
|
}
|
|
|
|
@override
|
|
String get path {
|
|
return _path;
|
|
}
|
|
|
|
@override
|
|
InternetAddress get remoteAddress {
|
|
return io.connectionInfo.remoteAddress;
|
|
}
|
|
|
|
@override
|
|
HttpSession get session {
|
|
return io.session;
|
|
}
|
|
|
|
@override
|
|
Uri get uri {
|
|
return io.uri;
|
|
}
|
|
|
|
@override
|
|
bool get xhr {
|
|
return io.headers.value("X-Requested-With")?.trim()?.toLowerCase() ==
|
|
'xmlhttprequest';
|
|
}
|
|
|
|
/// Magically transforms an [HttpRequest] into a [RequestContext].
|
|
static Future<HttpRequestContextImpl> from(
|
|
HttpRequest request, Angel app, String path) {
|
|
HttpRequestContextImpl ctx = new HttpRequestContextImpl();
|
|
|
|
String override = request.method;
|
|
|
|
if (app.allowMethodOverrides == true)
|
|
override =
|
|
request.headers.value('x-http-method-override')?.toUpperCase() ??
|
|
request.method;
|
|
|
|
ctx.app = app;
|
|
ctx._contentType = request.headers.contentType;
|
|
ctx._override = override;
|
|
|
|
/*
|
|
// Faster way to get path
|
|
List<int> _path = [];
|
|
|
|
// Go up until we reach a ?
|
|
for (int ch in request.uri.toString().codeUnits) {
|
|
if (ch != $question)
|
|
_path.add(ch);
|
|
else
|
|
break;
|
|
}
|
|
|
|
// Remove trailing slashes
|
|
int lastSlash = -1;
|
|
|
|
for (int i = _path.length - 1; i >= 0; i--) {
|
|
if (_path[i] == $slash)
|
|
lastSlash = i;
|
|
else
|
|
break;
|
|
}
|
|
|
|
if (lastSlash > -1)
|
|
ctx._path = new String.fromCharCodes(_path.take(lastSlash));
|
|
else
|
|
ctx._path = new String.fromCharCodes(_path);
|
|
*/
|
|
|
|
ctx._path = path;
|
|
ctx._io = request;
|
|
|
|
if (app.lazyParseBodies != true) {
|
|
return ctx.parse().then((_) => ctx);
|
|
}
|
|
|
|
return new Future.value(ctx);
|
|
}
|
|
|
|
@override
|
|
Future close() {
|
|
_contentType = null;
|
|
_io = null;
|
|
_override = _path = null;
|
|
return super.close();
|
|
}
|
|
|
|
@override
|
|
Future<BodyParseResult> parseOnce() {
|
|
return parseBodyFromStream(
|
|
io,
|
|
io.headers.contentType != null
|
|
? new MediaType.parse(io.headers.contentType.toString())
|
|
: null,
|
|
io.uri,
|
|
storeOriginalBuffer: app.storeOriginalBuffer == true);
|
|
}
|
|
}
|