diff --git a/lib/application.dart b/lib/application.dart index 5a7600bc6..77d2480ca 100644 --- a/lib/application.dart +++ b/lib/application.dart @@ -2,7 +2,6 @@ part of monadart; /// A set of values to configure an instance of a web server application. class ApplicationInstanceConfiguration { - /// The address to listen for HTTP requests on. /// /// By default, this address will default to 'any' address. If [isIpv6Only] is true, @@ -37,7 +36,6 @@ class ApplicationInstanceConfiguration { /// that are attached to this application. Map pipelineOptions; - /// Whether or not the server configuration defined by this instance can be shared across isolates. /// /// Defaults to false. When false, only one isolate may listen for requests on the [address] and [port] @@ -51,13 +49,13 @@ class ApplicationInstanceConfiguration { /// A copy constructor ApplicationInstanceConfiguration.fromConfiguration( ApplicationInstanceConfiguration config) - : this.address = config.address, - this.port = config.port, - this.isIpv6Only = config.isIpv6Only, - this.isUsingClientCertificate = config.isUsingClientCertificate, - this.serverCertificateName = config.serverCertificateName, - this.shared = config.shared, - this.pipelineOptions = config.pipelineOptions; + : this.address = config.address, + this.port = config.port, + this.isIpv6Only = config.isIpv6Only, + this.isUsingClientCertificate = config.isUsingClientCertificate, + this.serverCertificateName = config.serverCertificateName, + this.shared = config.shared, + this.pipelineOptions = config.pipelineOptions; } /// A abstract class that concrete subclasses will implement to provide request handling behavior. @@ -66,7 +64,6 @@ class ApplicationInstanceConfiguration { /// responds to requests is defined by its [ApplicationPipeline]. Instances of this class must implement the /// [handleRequest] method from [RequestHandler] - this is the entry point of all requests into this pipeline. abstract class ApplicationPipeline implements RequestHandler { - /// Passed in options for this pipeline from its owning [Application]. /// /// These values give an opportunity for a pipeline to have a customization point within attachTo., like running @@ -74,18 +71,16 @@ abstract class ApplicationPipeline implements RequestHandler { /// if the user did not set any configuration values. Map options; - void onPipelineOpen(); + void pipelineWillOpen(); + void pipelineDidOpen(); } - - /// A container for web server applications. /// /// Applications are responsible for managing starting and stopping of HTTP server instances across multiple isolates. /// Behavior specific to an application is implemented by setting the [Application]'s [configuration] and providing /// a [pipelineType] as a [ApplicationPipeline] subclass. class Application { - /// A list of items identifying the Isolates running a HTTP(s) listener and response handlers. List<_ServerRecord> servers = []; @@ -93,7 +88,7 @@ class Application { /// /// This must be configured prior to [start]ing the [Application]. ApplicationInstanceConfiguration configuration = - new ApplicationInstanceConfiguration(); + new ApplicationInstanceConfiguration(); /// The type of [ApplicationPipeline] that configures how requests are handled. /// @@ -118,7 +113,7 @@ class Application { for (int i = 0; i < numberOfInstances; i++) { var config = - new ApplicationInstanceConfiguration.fromConfiguration(configuration); + new ApplicationInstanceConfiguration.fromConfiguration(configuration); var serverRecord = await _spawn(config, i + 1); servers.add(serverRecord); @@ -129,17 +124,18 @@ class Application { }); } - Future<_ServerRecord> _spawn(ApplicationInstanceConfiguration config, int identifier) async { + Future<_ServerRecord> _spawn( + ApplicationInstanceConfiguration config, int identifier) async { var receivePort = new ReceivePort(); var pipelineTypeMirror = reflectType(pipelineType); var pipelineLibraryURI = (pipelineTypeMirror.owner as LibraryMirror).uri; var pipelineTypeName = MirrorSystem.getName(pipelineTypeMirror.simpleName); - var initialMessage = new _InitialServerMessage( - pipelineTypeName, pipelineLibraryURI, config, identifier, receivePort.sendPort); + var initialMessage = new _InitialServerMessage(pipelineTypeName, + pipelineLibraryURI, config, identifier, receivePort.sendPort); var isolate = - await Isolate.spawn(_Server.entry, initialMessage, paused: true); + await Isolate.spawn(_Server.entry, initialMessage, paused: true); isolate.addErrorListener(receivePort.sendPort); return new _ServerRecord(isolate, receivePort, identifier); @@ -153,52 +149,56 @@ class _Server { ApplicationPipeline pipeline; int identifier; - _Server(this.pipeline, this.configuration, this.identifier, this.parentMessagePort); + _Server(this.pipeline, this.configuration, this.identifier, + this.parentMessagePort); Future start() async { + pipeline.options = configuration.pipelineOptions; + pipeline.pipelineWillOpen(); + var onBind = (s) { server = s; server.serverHeader = "monadart/${this.identifier}"; - pipeline.options = configuration.pipelineOptions; - server.map((httpReq) => new ResourceRequest(httpReq)) - .listen(pipeline.handleRequest); + server + .map((httpReq) => new ResourceRequest(httpReq)) + .listen(pipeline.handleRequest); - pipeline.onPipelineOpen(); + pipeline.pipelineDidOpen(); }; if (configuration.serverCertificateName != null) { HttpServer - .bindSecure(configuration.address, configuration.port, - certificateName: configuration.serverCertificateName, - v6Only: configuration.isIpv6Only, - shared: configuration.shared) - .then(onBind); + .bindSecure(configuration.address, configuration.port, + certificateName: configuration.serverCertificateName, + v6Only: configuration.isIpv6Only, + shared: configuration.shared) + .then(onBind); } else if (configuration.isUsingClientCertificate) { HttpServer - .bindSecure(configuration.address, configuration.port, - requestClientCertificate: true, - v6Only: configuration.isIpv6Only, - shared: configuration.shared) - .then(onBind); + .bindSecure(configuration.address, configuration.port, + requestClientCertificate: true, + v6Only: configuration.isIpv6Only, + shared: configuration.shared) + .then(onBind); } else { HttpServer - .bind(configuration.address, configuration.port, - v6Only: configuration.isIpv6Only, shared: configuration.shared) - .then(onBind); + .bind(configuration.address, configuration.port, + v6Only: configuration.isIpv6Only, shared: configuration.shared) + .then(onBind); } } static void entry(_InitialServerMessage params) { var pipelineSourceLibraryMirror = - currentMirrorSystem().libraries[params.pipelineLibraryURI]; + currentMirrorSystem().libraries[params.pipelineLibraryURI]; var pipelineTypeMirror = pipelineSourceLibraryMirror.declarations[ - new Symbol(params.pipelineTypeName)] as ClassMirror; + new Symbol(params.pipelineTypeName)] as ClassMirror; var app = pipelineTypeMirror.newInstance(new Symbol(""), []).reflectee; - var server = - new _Server(app, params.configuration, params.identifier, params.parentMessagePort); + var server = new _Server( + app, params.configuration, params.identifier, params.parentMessagePort); server.start(); } @@ -224,5 +224,5 @@ class _InitialServerMessage { int identifier; _InitialServerMessage(this.pipelineTypeName, this.pipelineLibraryURI, - this.configuration, this.identifier, this.parentMessagePort); -} \ No newline at end of file + this.configuration, this.identifier, this.parentMessagePort); +} diff --git a/lib/controller_routing.dart b/lib/controller_routing.dart index a4b95b5c0..9201a2285 100644 --- a/lib/controller_routing.dart +++ b/lib/controller_routing.dart @@ -1,7 +1,5 @@ part of monadart; - - /// A 'GET' HttpMethod annotation. /// /// Handler methods on [HttpController]s that handle GET requests must be annotated with this. @@ -42,8 +40,8 @@ class HttpMethod { const HttpMethod(this.method) : this._parameters = null; HttpMethod._fromMethod(HttpMethod m, List parameters) - : this.method = m.method, - this._parameters = parameters; + : this.method = m.method, + this._parameters = parameters; /// Returns whether or not this [HttpMethod] matches a [ResourceRequest]. bool matchesRequest(ResourceRequest req) { diff --git a/lib/documentable.dart b/lib/documentable.dart index fc3a843e7..96cb670dd 100644 --- a/lib/documentable.dart +++ b/lib/documentable.dart @@ -1,3 +1 @@ -abstract class Documentable { - -} \ No newline at end of file +abstract class Documentable {} diff --git a/lib/http_controller.dart b/lib/http_controller.dart index 683cdd5ff..41b106cca 100644 --- a/lib/http_controller.dart +++ b/lib/http_controller.dart @@ -1,11 +1,9 @@ part of monadart; - /// Base class for web service handlers. /// /// Subclasses of this class can process and respond to an HTTP request. abstract class HttpController implements RequestHandler { - /// The exception handler for a request handler method that generates an HTTP error response. /// /// The default handler will always respond to the HTTP request with a 500 status code. @@ -14,7 +12,8 @@ abstract class HttpController implements RequestHandler { /// is in place. Function get exceptionHandler => _exceptionHandler; - void set exceptionHandler(Response handler(ResourceRequest resourceRequest, dynamic exceptionOrError, StackTrace stacktrace)) { + void set exceptionHandler(Response handler(ResourceRequest resourceRequest, + dynamic exceptionOrError, StackTrace stacktrace)) { _exceptionHandler = handler; } @@ -62,15 +61,18 @@ abstract class HttpController implements RequestHandler { var decl = decls[key]; if (decl is MethodMirror) { var methodAttrs = decl.metadata.firstWhere( - (attr) => attr.reflectee is HttpMethod, orElse: () => null); + (attr) => attr.reflectee is HttpMethod, + orElse: () => null); if (methodAttrs != null) { - var params = (decl as MethodMirror).parameters - .where((pm) => !pm.isOptional) - .map((pm) => MirrorSystem.getName(pm.simpleName)) - .toList(); + var params = (decl as MethodMirror) + .parameters + .where((pm) => !pm.isOptional) + .map((pm) => MirrorSystem.getName(pm.simpleName)) + .toList(); - HttpMethod r = new HttpMethod._fromMethod(methodAttrs.reflectee, params); + HttpMethod r = + new HttpMethod._fromMethod(methodAttrs.reflectee, params); if (r.matchesRequest(req)) { symbol = key; @@ -82,33 +84,35 @@ abstract class HttpController implements RequestHandler { if (symbol == null) { throw new _InternalControllerException( - "No handler for request method and parameters available.", HttpStatus.NOT_FOUND); + "No handler for request method and parameters available.", + HttpStatus.NOT_FOUND); } return symbol; } - dynamic _readRequestBodyForRequest(ResourceRequest req) async - { + dynamic _readRequestBodyForRequest(ResourceRequest req) async { if (resourceRequest.request.contentLength > 0) { var incomingContentType = resourceRequest.request.headers.contentType; var matchingContentType = acceptedContentTypes.firstWhere((ct) { return ct.primaryType == incomingContentType.primaryType && - ct.subType == incomingContentType.subType; + ct.subType == incomingContentType.subType; }, orElse: () => null); if (matchingContentType != null) { - return (await HttpBodyHandler - .processRequest(resourceRequest.request)).body; + return (await HttpBodyHandler.processRequest(resourceRequest.request)) + .body; } else { - throw new _InternalControllerException("Unsupported Content-Type", HttpStatus.UNSUPPORTED_MEDIA_TYPE); + throw new _InternalControllerException( + "Unsupported Content-Type", HttpStatus.UNSUPPORTED_MEDIA_TYPE); } } return null; } - dynamic _convertParameterWithMirror(String parameterValue, ParameterMirror parameterMirror) { + dynamic _convertParameterWithMirror( + String parameterValue, ParameterMirror parameterMirror) { var typeMirror = parameterMirror.type; if (typeMirror.isSubtypeOf(reflectType(String))) { return parameterValue; @@ -122,46 +126,54 @@ abstract class HttpController implements RequestHandler { var reflValue = cm.invoke(parseDecl.simpleName, [parameterValue]); return reflValue.reflectee; } catch (e) { - throw new _InternalControllerException("Invalid value for parameter type", - HttpStatus.BAD_REQUEST, - responseMessage: "URI parameter is wrong type"); + throw new _InternalControllerException( + "Invalid value for parameter type", HttpStatus.BAD_REQUEST, + responseMessage: "URI parameter is wrong type"); } } } // If we get here, then it wasn't a string and couldn't be parsed, and we should throw? - throw new _InternalControllerException("Invalid path parameter type, types must be String or implement parse", - HttpStatus.INTERNAL_SERVER_ERROR, - responseMessage: "URI parameter is wrong type"); + throw new _InternalControllerException( + "Invalid path parameter type, types must be String or implement parse", + HttpStatus.INTERNAL_SERVER_ERROR, + responseMessage: "URI parameter is wrong type"); return null; } - List _parametersForRequest(ResourceRequest req, Symbol handlerMethodSymbol) { + List _parametersForRequest( + ResourceRequest req, Symbol handlerMethodSymbol) { var handlerMirror = - reflect(this).type.declarations[handlerMethodSymbol] as MethodMirror; + reflect(this).type.declarations[handlerMethodSymbol] as MethodMirror; return handlerMirror.parameters - .where((methodParmeter) => !methodParmeter.isOptional) - .map((methodParameter) { - var value = this.resourceRequest.path.variables[MirrorSystem.getName(methodParameter.simpleName)]; + .where((methodParmeter) => !methodParmeter.isOptional) + .map((methodParameter) { + var value = this.resourceRequest.path.variables[ + MirrorSystem.getName(methodParameter.simpleName)]; return _convertParameterWithMirror(value, methodParameter); }).toList(); } - Map _queryParametersForRequest(ResourceRequest req, Symbol handlerMethodSymbol) { + Map _queryParametersForRequest( + ResourceRequest req, Symbol handlerMethodSymbol) { var queryParams = req.request.uri.queryParameters; if (queryParams.length == 0) { return null; } - var optionalParams = (reflect(this).type.declarations[handlerMethodSymbol] as MethodMirror) - .parameters.where((methodParameter) => methodParameter.isOptional).toList(); + var optionalParams = (reflect(this).type.declarations[handlerMethodSymbol] + as MethodMirror) + .parameters + .where((methodParameter) => methodParameter.isOptional) + .toList(); var retMap = {}; queryParams.forEach((k, v) { var keySymbol = new Symbol(k); - var matchingParameter = optionalParams.firstWhere((p) => p.simpleName == keySymbol, orElse: () => null); + var matchingParameter = optionalParams + .firstWhere((p) => p.simpleName == keySymbol, orElse: () => null); if (matchingParameter != null) { retMap[keySymbol] = _convertParameterWithMirror(v, matchingParameter); } @@ -173,18 +185,22 @@ abstract class HttpController implements RequestHandler { Future _process() async { try { var methodSymbol = _routeMethodSymbolForRequest(resourceRequest); - var handlerParameters = _parametersForRequest(resourceRequest, methodSymbol); - var handlerQueryParameters = _queryParametersForRequest(resourceRequest, methodSymbol); + var handlerParameters = + _parametersForRequest(resourceRequest, methodSymbol); + var handlerQueryParameters = + _queryParametersForRequest(resourceRequest, methodSymbol); requestBody = await _readRequestBodyForRequest(resourceRequest); - Future eventualResponse = - reflect(this).invoke(methodSymbol, handlerParameters, handlerQueryParameters).reflectee; + Future eventualResponse = reflect(this) + .invoke(methodSymbol, handlerParameters, handlerQueryParameters) + .reflectee; var response = await eventualResponse; response.body = responseBodyEncoder(response.body); - response.headers[HttpHeaders.CONTENT_TYPE] = responseContentType.toString(); + response.headers[HttpHeaders.CONTENT_TYPE] = + responseContentType.toString(); resourceRequest.respond(response); } on _InternalControllerException catch (e) { @@ -207,14 +223,14 @@ abstract class HttpController implements RequestHandler { } } - static Response _defaultExceptionHandler(ResourceRequest resourceRequest, dynamic exceptionOrError, StackTrace stacktrace) { + static Response _defaultExceptionHandler(ResourceRequest resourceRequest, + dynamic exceptionOrError, StackTrace stacktrace) { print( "Path: ${resourceRequest.request.uri}\nError: $exceptionOrError\n $stacktrace"); return new Response.serverError(); } - void handleRequest(ResourceRequest req) { resourceRequest = req; _process(); @@ -228,7 +244,7 @@ class _InternalControllerException { final String responseMessage; _InternalControllerException(this.message, this.statusCode, - {HttpHeaders additionalHeaders: null, - String responseMessage: null}) : this.additionalHeaders = additionalHeaders, - this.responseMessage = responseMessage; + {HttpHeaders additionalHeaders: null, String responseMessage: null}) + : this.additionalHeaders = additionalHeaders, + this.responseMessage = responseMessage; } diff --git a/lib/monadart.dart b/lib/monadart.dart index e0f5ef3a4..9e46543fd 100644 --- a/lib/monadart.dart +++ b/lib/monadart.dart @@ -16,4 +16,4 @@ part 'http_controller.dart'; part 'response.dart'; part 'application.dart'; part 'request_handler.dart'; -part 'controller_routing.dart'; \ No newline at end of file +part 'controller_routing.dart'; diff --git a/lib/request_handler.dart b/lib/request_handler.dart index e8818ead1..dc3bee016 100644 --- a/lib/request_handler.dart +++ b/lib/request_handler.dart @@ -6,7 +6,8 @@ abstract class RequestHandler { class RequestHandlerGenerator implements RequestHandler { void handleRequest(ResourceRequest req) { - var handler = reflectClass(T).newInstance(new Symbol(""), []).reflectee as RequestHandler; + var handler = reflectClass(T).newInstance(new Symbol(""), []).reflectee + as RequestHandler; handler.handleRequest(req); } -} \ No newline at end of file +} diff --git a/lib/resource_pattern.dart b/lib/resource_pattern.dart index d449125e7..54cbfc088 100644 --- a/lib/resource_pattern.dart +++ b/lib/resource_pattern.dart @@ -1,12 +1,10 @@ part of monadart; - /// A representation of a Route match, containing the elements of the matched path. /// /// Instances of this class can be used by handlers after the router to inspect /// specifics of the incoming path without having to dissect the path on their own. class ResourcePatternMatch { - /// A map of variable to values in this match. /// /// If a path has variables (indicated by the :name syntax) in the path, @@ -37,7 +35,6 @@ class ResourcePatternMatch { } class ResourcePattern { - static String remainingPath = "remainingPath"; _ResourcePatternSet matchHead; @@ -45,21 +42,23 @@ class ResourcePattern { ResourcePattern(String patternString) { List pathElements = splitPattern(patternString); - List<_ResourcePatternElement> elems = resourceElementsFromPathElements(patternString); + List<_ResourcePatternElement> elems = + resourceElementsFromPathElements(patternString); matchHead = matchSpecFromElements(pathElements, elems); } - static _ResourcePatternSet matchSpecFromElements(List pathElements, List<_ResourcePatternElement> resourceElements) { + static _ResourcePatternSet matchSpecFromElements(List pathElements, + List<_ResourcePatternElement> resourceElements) { // These two arrays should be identical in size by the time they get here _ResourcePatternSet setHead = new _ResourcePatternSet(); _ResourcePatternSet setPtr = setHead; - for(int i = 0; i < pathElements.length; i++) { + for (int i = 0; i < pathElements.length; i++) { String seg = pathElements[i]; - if(seg.startsWith("[")) { + if (seg.startsWith("[")) { _ResourcePatternSet set = new _ResourcePatternSet(); setPtr.nextOptionalSet = set; @@ -68,8 +67,8 @@ class ResourcePattern { setPtr.addElement(resourceElements[i]); - for(int i = seg.length - 1; i >= 0; i--) { - if(seg[i] == "]") { + for (int i = seg.length - 1; i >= 0; i--) { + if (seg[i] == "]") { setPtr = setPtr.parentSet; } else { break; @@ -77,7 +76,7 @@ class ResourcePattern { } } - if(setPtr != setHead) { + if (setPtr != setHead) { throw new ArgumentError("unmatched brackets in optional paths"); } @@ -85,19 +84,23 @@ class ResourcePattern { } static List splitPattern(String patternString) { - return patternString.split("/").fold(new List(), (List accum, String e) { + return patternString.split("/").fold(new List(), + (List accum, String e) { var trimmed = e.trim(); - if(trimmed.length > 0) { + if (trimmed.length > 0) { accum.add(trimmed); } return accum; }); } - - static List<_ResourcePatternElement> resourceElementsFromPathElements(String patternString) { + static List<_ResourcePatternElement> resourceElementsFromPathElements( + String patternString) { var expr = new RegExp(r"[\[\]]"); - return splitPattern(patternString).map((segment) => new _ResourcePatternElement(segment.replaceAll(expr, ""))).toList(); + return splitPattern(patternString) + .map((segment) => + new _ResourcePatternElement(segment.replaceAll(expr, ""))) + .toList(); } ResourcePatternMatch matchUri(Uri uri) { @@ -108,33 +111,35 @@ class ResourcePattern { var resourceSet = matchHead; var resourceIterator = resourceSet.elements.iterator; - while(resourceSet != null) { + while (resourceSet != null) { while (resourceIterator.moveNext()) { // If we run into a *, then we're definitely a match so just grab the end of the path and return it. var resourceSegment = resourceIterator.current; if (resourceSegment.matchesRemaining) { - var remainingString = incomingPathSegments.sublist(incomingPathIndex, incomingPathSegments.length).join("/"); + var remainingString = incomingPathSegments + .sublist(incomingPathIndex, incomingPathSegments.length) + .join("/"); match.remainingPath = remainingString; return match; } else { // If we're out of path segments, then we don't match - if(incomingPathIndex >= incomingPathSegments.length) { + if (incomingPathIndex >= incomingPathSegments.length) { return null; } var pathSegment = incomingPathSegments[incomingPathIndex]; - incomingPathIndex ++; + incomingPathIndex++; bool matches = resourceSegment.fullMatchForString(pathSegment); - if(!matches) { + if (!matches) { // There was a path segment available, but it did not match return null; } // We match! - if(resourceSegment.name != null) { + if (resourceSegment.name != null) { match.variables[resourceSegment.name] = pathSegment; } @@ -144,8 +149,8 @@ class ResourcePattern { resourceSet = resourceSet.nextOptionalSet; // If we have path remaining, then we either have optional left or we don't have a match - if(incomingPathIndex < incomingPathSegments.length) { - if(resourceSet == null) { + if (incomingPathIndex < incomingPathSegments.length) { + if (resourceSet == null) { return null; } else { resourceIterator = resourceSet.elements.iterator; @@ -179,10 +184,10 @@ class _ResourcePatternElement { RegExp matchRegex; _ResourcePatternElement(String segment) { - if(segment.startsWith(":")) { + if (segment.startsWith(":")) { var contents = segment.substring(1, segment.length); constructFromString(contents); - } else if(segment == "*") { + } else if (segment == "*") { matchesRemaining = true; } else { matchRegex = new RegExp(segment); @@ -191,31 +196,36 @@ class _ResourcePatternElement { // I'd prefer that this used a outer non-capturing group on the parantheses after the name; // but apparently this regex parser won't pick up the capture group inside the noncapturing group for some reason - static RegExp patternFinder = new RegExp(r"^(\w+)(\(([^\)]+)\))?$", caseSensitive: false); + static RegExp patternFinder = + new RegExp(r"^(\w+)(\(([^\)]+)\))?$", caseSensitive: false); void constructFromString(String str) { Match m = patternFinder.firstMatch(str); - if(m == null) { - throw new ArgumentError("invalid resource pattern segment ${str}, available formats are the following: literal, *, {name}, {name(pattern)}"); + if (m == null) { + throw new ArgumentError( + "invalid resource pattern segment ${str}, available formats are the following: literal, *, {name}, {name(pattern)}"); } name = m.group(1); var matchString = ".+"; - if(m.groupCount == 3) { - if(m.group(2) != null) { + if (m.groupCount == 3) { + if (m.group(2) != null) { matchString = m.group(2); } } - matchRegex = new RegExp(r"^" + "${matchString}" + r"$", caseSensitive:false); + matchRegex = + new RegExp(r"^" + "${matchString}" + r"$", caseSensitive: false); } bool fullMatchForString(String pathSegment) { var iter = matchRegex.allMatches(pathSegment).iterator; if (iter.moveNext()) { var match = iter.current; - if(match.start == 0 && match.end == pathSegment.length && !iter.moveNext()) { + if (match.start == 0 && + match.end == pathSegment.length && + !iter.moveNext()) { return true; } else { return false; @@ -227,10 +237,9 @@ class _ResourcePatternElement { String toString() { String str = "${matchesRemaining} ${name} "; - if(matchRegex != null) { + if (matchRegex != null) { str = str + matchRegex.pattern; } return str; } - -} \ No newline at end of file +} diff --git a/lib/resource_request.dart b/lib/resource_request.dart index f57291c43..cbef71afc 100644 --- a/lib/resource_request.dart +++ b/lib/resource_request.dart @@ -5,7 +5,6 @@ part of monadart; /// Contains a standard library [HttpRequest], along with other values /// to associate data with a request. class ResourceRequest { - /// The internal [HttpRequest] of this [ResourceRequest]. /// /// The standard library generated HTTP request object. This contains @@ -32,9 +31,7 @@ class ResourceRequest { /// to the request so that the handling [HttpController] has access to it. Map context = new Map(); - ResourceRequest(this.request) { - - } + ResourceRequest(this.request) {} void respond(Response respObj) { response.statusCode = respObj.statusCode; @@ -51,4 +48,4 @@ class ResourceRequest { response.close(); } -} \ No newline at end of file +} diff --git a/lib/response.dart b/lib/response.dart index c0bbad0ce..2c820f41a 100644 --- a/lib/response.dart +++ b/lib/response.dart @@ -5,7 +5,6 @@ part of monadart; /// This object can be used to write an HTTP response and contains conveniences /// for creating these objects. class Response { - /// An object representing the body of the [Response], which will be encoded later. /// /// This is typically a map that will be encoded to JSON. @@ -26,31 +25,41 @@ class Response { this.headers = headers; this.statusCode = statusCode; - if(this.headers == null) { + if (this.headers == null) { this.headers = {}; } } - Response.ok(dynamic body, {Map headers}) : this(HttpStatus.OK, headers, body); - Response.created(String location, {dynamic body, Map headers}) { + Response.ok(dynamic body, {Map headers}) + : this(HttpStatus.OK, headers, body); + Response.created(String location, + {dynamic body, Map headers}) { this.headers = headers; this.body = body; this.statusCode = HttpStatus.CREATED; - if(this.headers == null) { - this.headers = {HttpHeaders.LOCATION : location}; + if (this.headers == null) { + this.headers = {HttpHeaders.LOCATION: location}; } else { this.headers[HttpHeaders.LOCATION] = location; } } - Response.accepted({Map headers}) : this(HttpStatus.ACCEPTED, headers, null); + Response.accepted({Map headers}) + : this(HttpStatus.ACCEPTED, headers, null); - Response.badRequest({Map headers, dynamic body}) : this(HttpStatus.BAD_REQUEST, headers, body); - Response.unauthorized({Map headers, dynamic body}) : this(HttpStatus.UNAUTHORIZED, headers, body); - Response.forbidden({Map headers, dynamic body}) : this(HttpStatus.FORBIDDEN, headers, body); - Response.notFound({Map headers, dynamic body}) : this(HttpStatus.NOT_FOUND, headers, body); - Response.conflict({Map headers, dynamic body}) : this(HttpStatus.CONFLICT, headers, body); - Response.gone({Map headers, dynamic body}) : this(HttpStatus.GONE, headers, body); + Response.badRequest({Map headers, dynamic body}) + : this(HttpStatus.BAD_REQUEST, headers, body); + Response.unauthorized({Map headers, dynamic body}) + : this(HttpStatus.UNAUTHORIZED, headers, body); + Response.forbidden({Map headers, dynamic body}) + : this(HttpStatus.FORBIDDEN, headers, body); + Response.notFound({Map headers, dynamic body}) + : this(HttpStatus.NOT_FOUND, headers, body); + Response.conflict({Map headers, dynamic body}) + : this(HttpStatus.CONFLICT, headers, body); + Response.gone({Map headers, dynamic body}) + : this(HttpStatus.GONE, headers, body); - Response.serverError({Map headers, dynamic body}) : this(HttpStatus.INTERNAL_SERVER_ERROR, headers, body); -} \ No newline at end of file + Response.serverError({Map headers, dynamic body}) + : this(HttpStatus.INTERNAL_SERVER_ERROR, headers, body); +} diff --git a/lib/router.dart b/lib/router.dart index 54956fb22..2b55c9635 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -24,11 +24,12 @@ class Router implements RequestHandler { String get basePath => _basePath; void set basePath(String bp) { - if(_routes.length > 0) { + if (_routes.length > 0) { throw new _RouterException("Cannot alter basePath after adding routes."); } _basePath = bp; } + String _basePath; /// How this router handles [ResourceRequest]s that don't match its routes. @@ -41,6 +42,7 @@ class Router implements RequestHandler { void set unhandledRequestHandler(void handler(ResourceRequest req)) { _unhandledRequestHandler = handler; } + var _unhandledRequestHandler; /// Creates a new [Router]. @@ -76,16 +78,16 @@ class Router implements RequestHandler { } _ResourceRoute _createRoute(String pattern, {RequestHandler handler: null}) { - if(basePath != null) { + if (basePath != null) { pattern = basePath + pattern; } - // Strip out any extraneous /s var finalPattern = pattern.split("/").where((c) => c != "").join("/"); var streamController = new StreamController(); - var route = new _ResourceRoute(new ResourcePattern(finalPattern), streamController, handler); + var route = new _ResourceRoute( + new ResourcePattern(finalPattern), streamController, handler); _routes.add(route); return route; @@ -101,7 +103,7 @@ class Router implements RequestHandler { for (var route in _routes) { var routeMatch = route.pattern.matchUri(req.request.uri); - if(routeMatch != null) { + if (routeMatch != null) { req.path = routeMatch; route.streamController.add(req); @@ -113,7 +115,6 @@ class Router implements RequestHandler { _unhandledRequestHandler(req); } - void _handleUnhandledRequest(ResourceRequest req) { req.response.statusCode = HttpStatus.NOT_FOUND; req.response.close(); @@ -131,4 +132,4 @@ class _ResourceRoute { class _RouterException implements Exception { final String message; _RouterException(this.message); -} \ No newline at end of file +} diff --git a/test/application_tests.dart b/test/application_tests.dart index 85ab586f9..6af697b93 100644 --- a/test/application_tests.dart +++ b/test/application_tests.dart @@ -13,8 +13,6 @@ main() { expect(app.servers.length, 1); }); - //////////////////////////////////////////// - test("Application responds to request", () async { var response = await http.get("http://localhost:8080/t"); expect(response.statusCode, 200);