2016-09-15 19:53:01 +00:00
|
|
|
library angel_framework.http.request_context;
|
2016-10-22 20:41:36 +00:00
|
|
|
|
2016-09-15 19:53:01 +00:00
|
|
|
import 'dart:async';
|
|
|
|
import 'dart:io';
|
2016-10-22 20:41:36 +00:00
|
|
|
import 'package:angel_route/src/extensible.dart';
|
2016-09-15 19:53:01 +00:00
|
|
|
import 'package:body_parser/body_parser.dart';
|
|
|
|
import 'angel_base.dart';
|
2016-04-18 03:27:23 +00:00
|
|
|
|
|
|
|
/// A convenience wrapper around an incoming HTTP request.
|
2016-04-21 20:37:02 +00:00
|
|
|
class RequestContext extends Extensible {
|
2016-10-22 20:41:36 +00:00
|
|
|
BodyParseResult _body;
|
|
|
|
ContentType _contentType;
|
2016-11-23 19:50:17 +00:00
|
|
|
HttpRequest _io;
|
2016-10-22 20:41:36 +00:00
|
|
|
String _path;
|
|
|
|
|
2016-04-18 03:27:23 +00:00
|
|
|
/// The [Angel] instance that is responding to this request.
|
2016-09-15 19:53:01 +00:00
|
|
|
AngelBase app;
|
2016-04-18 03:27:23 +00:00
|
|
|
|
|
|
|
/// Any cookies sent with this request.
|
2016-11-23 19:50:17 +00:00
|
|
|
List<Cookie> get cookies => io.cookies;
|
2016-04-18 03:27:23 +00:00
|
|
|
|
|
|
|
/// All HTTP headers sent with this request.
|
2016-11-23 19:50:17 +00:00
|
|
|
HttpHeaders get headers => io.headers;
|
2016-04-18 03:27:23 +00:00
|
|
|
|
|
|
|
/// The requested hostname.
|
2016-11-23 19:50:17 +00:00
|
|
|
String get hostname => io.headers.value(HttpHeaders.HOST);
|
|
|
|
|
|
|
|
/// A [Map] of values that should be DI'd.
|
|
|
|
final Map injections = {};
|
|
|
|
|
|
|
|
/// The underlying [HttpRequest] instance underneath this context.
|
|
|
|
HttpRequest get io => _io;
|
2016-04-18 03:27:23 +00:00
|
|
|
|
|
|
|
/// The user's IP.
|
|
|
|
String get ip => remoteAddress.address;
|
|
|
|
|
|
|
|
/// This request's HTTP method.
|
2016-11-23 19:50:17 +00:00
|
|
|
String get method => io.method;
|
2016-04-18 03:27:23 +00:00
|
|
|
|
|
|
|
/// All post data submitted to the server.
|
2016-10-22 20:41:36 +00:00
|
|
|
Map get body => _body.body;
|
2016-04-18 03:27:23 +00:00
|
|
|
|
|
|
|
/// The content type of an incoming request.
|
2016-10-22 20:41:36 +00:00
|
|
|
ContentType get contentType => _contentType;
|
2016-04-18 03:27:23 +00:00
|
|
|
|
|
|
|
/// Any and all files sent to the server with this request.
|
2016-10-22 20:41:36 +00:00
|
|
|
List<FileUploadInfo> get files => _body.files;
|
2016-04-18 03:27:23 +00:00
|
|
|
|
2017-01-14 13:56:14 +00:00
|
|
|
/// The original body bytes sent with this request. May be empty.
|
|
|
|
List<int> get originalBuffer => _body.originalBuffer ?? [];
|
|
|
|
|
2016-04-18 03:27:23 +00:00
|
|
|
/// The URL parameters extracted from the request URI.
|
|
|
|
Map params = {};
|
|
|
|
|
|
|
|
/// The requested path.
|
2016-10-22 20:41:36 +00:00
|
|
|
String get path => _path;
|
2016-04-18 03:27:23 +00:00
|
|
|
|
|
|
|
/// The parsed request query string.
|
2016-10-22 20:41:36 +00:00
|
|
|
Map get query => _body.query;
|
2016-04-18 03:27:23 +00:00
|
|
|
|
|
|
|
/// The remote address requesting this resource.
|
2016-12-21 03:10:03 +00:00
|
|
|
InternetAddress get remoteAddress => io.connectionInfo.remoteAddress;
|
2016-04-18 03:27:23 +00:00
|
|
|
|
|
|
|
/// The user's HTTP session.
|
2016-11-23 19:50:17 +00:00
|
|
|
HttpSession get session => io.session;
|
2016-10-22 20:41:36 +00:00
|
|
|
|
|
|
|
/// The [Uri] instance representing the path this request is responding to.
|
2016-11-23 19:50:17 +00:00
|
|
|
Uri get uri => io.uri;
|
2016-04-18 03:27:23 +00:00
|
|
|
|
|
|
|
/// Is this an **XMLHttpRequest**?
|
2016-10-22 20:41:36 +00:00
|
|
|
bool get xhr =>
|
2016-12-21 03:10:03 +00:00
|
|
|
io.headers.value("X-Requested-With")?.trim()?.toLowerCase() ==
|
2016-10-22 20:41:36 +00:00
|
|
|
'xmlhttprequest';
|
2016-04-18 03:27:23 +00:00
|
|
|
|
2016-11-23 19:50:17 +00:00
|
|
|
@deprecated
|
|
|
|
HttpRequest get underlyingRequest {
|
|
|
|
throw new Exception(
|
|
|
|
'`RequestContext#underlyingRequest` is deprecated. Please update your application to use the newer `RequestContext#io`.');
|
|
|
|
}
|
2016-10-22 20:41:36 +00:00
|
|
|
|
|
|
|
/// Magically transforms an [HttpRequest] into a [RequestContext].
|
|
|
|
static Future<RequestContext> from(HttpRequest request, AngelBase app) async {
|
|
|
|
RequestContext ctx = new RequestContext();
|
|
|
|
|
|
|
|
ctx.app = app;
|
|
|
|
ctx._contentType = request.headers.contentType;
|
|
|
|
ctx._path = request.uri
|
|
|
|
.toString()
|
|
|
|
.replaceAll("?" + request.uri.query, "")
|
|
|
|
.replaceAll(new RegExp(r'/+$'), '');
|
2016-11-23 19:50:17 +00:00
|
|
|
ctx._io = request;
|
2016-10-22 20:41:36 +00:00
|
|
|
|
2017-01-14 13:53:38 +00:00
|
|
|
ctx._body = (await parseBody(request,
|
|
|
|
storeOriginalBuffer: app.storeOriginalBuffer == true)) ??
|
|
|
|
{};
|
2016-10-22 20:41:36 +00:00
|
|
|
|
|
|
|
return ctx;
|
2016-04-18 03:27:23 +00:00
|
|
|
}
|
2016-11-23 19:50:17 +00:00
|
|
|
|
2017-01-20 22:11:20 +00:00
|
|
|
/// Grabs an object by key or type from [params], [injections], or
|
|
|
|
/// [app].container. Use this to perform dependency injection
|
|
|
|
/// within a service hook.
|
|
|
|
grab(key) {
|
|
|
|
if (params.containsKey(key))
|
|
|
|
return params[key];
|
|
|
|
else if (injections.containsKey(key))
|
|
|
|
return injections[key];
|
|
|
|
else if (key is Type) {
|
|
|
|
try {
|
|
|
|
return app.container.make(key);
|
|
|
|
} catch (e) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2016-12-23 20:53:39 +00:00
|
|
|
void inject(type, value) {
|
2016-11-23 19:50:17 +00:00
|
|
|
injections[type] = value;
|
|
|
|
}
|
2016-10-22 20:41:36 +00:00
|
|
|
}
|