MultiRequestHandler class
Class which can process multiple ClientRequest send in one HttpRequest. Is responsible for unpacking HttpRequest and calling aproriate handler which has been registered inside it.
class MultiRequestHandler { final _createLoopBackConnection; MultiRequestHandler([this._createLoopBackConnection = createLoopBackConnection]) { this.registerHandler("ping", (_) => new Future.value("pong")); } /** * List of handlers for [ClientRequest]. Index is matching with * [ClientRequest.type] */ final Map<String, ServerRequestHandler> _registeredExecutors = new Map(); /** * Default handler form [ClientRequest] */ ServerRequestHandler _defaultExecutor = null; /** * Process [HttpRequest] extract from it [HttpBody] * then extract [PackedRequest]s process them and generate proper * [HttpResponse] */ void handleHttpRequest(Request request) { if (request.type != 'json') { throw new Exception('Request type is ${request.type}, ' 'json was expected!'); } List<PackedRequest> packedRequests = // packedRequestsFromJson(JSON.decode(request.body)); packedRequestsFromJson(request.body); // decorate individual clientRequests with authenticatedUserId property _splitAndProcessRequests(packedRequests, request.authenticatedUserId) .then((response) { request.response ..headers.contentType = JSON_CONTENT_TYPE ..statusCode = HttpStatus.OK ..write(JSON.encode({'responses': response, 'authenticatedUserId': request.authenticatedUserId})) ..close(); }).catchError((e) { request.response ..headers.contentType = JSON_CONTENT_TYPE ..statusCode = HttpStatus.BAD_REQUEST ..close(); }, test: (e) => e is UnknownHandlerException); } Future<List> handleLoopBackRequest(String requests, authenticatedUserId) { return _splitAndProcessRequests(packedRequestsFromJson(JSON.decode(requests)), authenticatedUserId); } /** * Run asynchroniusly [PackedRequest]s in order as they are presented in [requests] * and return list of processed results from each request. */ Future<List> _splitAndProcessRequests(List<PackedRequest> requests, authenticatedUserId) { final List responses = new List(); //now you need to call on each element of requests function _handleClientRequest //this calls are asynchronous but must run in sequencial order //results from calls are collected inside response //if you encounter error during execution of any fuction run you end //execution of all next functions and complete future result with error return Future.forEach( requests, (PackedRequest request) { // Create new server request from packed request and add // authenticatedUserId to it ServerRequest serverRequest = new ServerRequest( request.clientRequest.type, request.clientRequest.args, authenticatedUserId, _createLoopBackConnection(this, authenticatedUserId) ); return _handleServerRequest(serverRequest).then( (response) { responses.add({'id': request.id, 'response': response}); }); } ).then((_) => new Future.value(responses)). catchError((e, s) { logger.shout('Exception during request processing: $e \n $s'); throw e; }); } /** * Try to find which handler should execute [ServerRequest]. * If for [ServerRequest.type] is not not registered any executor than will * try to run default executor if presented. In other cases throws * exception [UnknownHandlerException]. */ Future _handleServerRequest(ServerRequest request){ if(_registeredExecutors.containsKey(request.type)){ return _registeredExecutors[request.type](request); } else if(_defaultExecutor != null) { return _defaultExecutor(request); } else { return new Future.error(new UnknownHandlerException(request.type)); } } /** * Register default [ClientRequestHandler] for incomming [ClientRequest] * Default executor is called only if executor for [ClientRequest.type] is * not registerd. * Multiple registration cause exception [AlreadyRegisteredHandlerException]. */ void registerDefaultHandler(ServerRequestHandler requestExecutor) { if (_defaultExecutor == null) { _defaultExecutor = requestExecutor; } else { throw new AlreadyRegisteredHandlerException(""); } } /** * Register [ClientRequestHandler] for incomming [ClientRequest] with * [ClientRequest.type] setted to [name]. Multiple registration for * same [name] cause exception [AlreadyRegisteredHandlerException]. */ void registerHandler(String name, ServerRequestHandler requestExecutor){ if(_registeredExecutors.containsKey(name)){ throw new AlreadyRegisteredHandlerException(name); } else { _registeredExecutors[name] = requestExecutor; } } }
Constructors
new MultiRequestHandler([_createLoopBackConnection = createLoopBackConnection]) #
Creates a new Object instance.
Object instances have no meaningful state, and are only useful through their identity. An Object instance is equal to itself only.
MultiRequestHandler([this._createLoopBackConnection = createLoopBackConnection]) { this.registerHandler("ping", (_) => new Future.value("pong")); }
Methods
void handleHttpRequest(Request request) #
Process HttpRequest extract from it HttpBody then extract PackedRequests process them and generate proper HttpResponse
void handleHttpRequest(Request request) { if (request.type != 'json') { throw new Exception('Request type is ${request.type}, ' 'json was expected!'); } List<PackedRequest> packedRequests = // packedRequestsFromJson(JSON.decode(request.body)); packedRequestsFromJson(request.body); // decorate individual clientRequests with authenticatedUserId property _splitAndProcessRequests(packedRequests, request.authenticatedUserId) .then((response) { request.response ..headers.contentType = JSON_CONTENT_TYPE ..statusCode = HttpStatus.OK ..write(JSON.encode({'responses': response, 'authenticatedUserId': request.authenticatedUserId})) ..close(); }).catchError((e) { request.response ..headers.contentType = JSON_CONTENT_TYPE ..statusCode = HttpStatus.BAD_REQUEST ..close(); }, test: (e) => e is UnknownHandlerException); }
Future<List> handleLoopBackRequest(String requests, authenticatedUserId) #
Future<List> handleLoopBackRequest(String requests, authenticatedUserId) { return _splitAndProcessRequests(packedRequestsFromJson(JSON.decode(requests)), authenticatedUserId); }
void registerDefaultHandler(ServerRequestHandler requestExecutor) #
Register default ClientRequestHandler
for incomming ClientRequest
Default executor is called only if executor for ClientRequest.type
is
not registerd.
Multiple registration cause exception AlreadyRegisteredHandlerException.
void registerDefaultHandler(ServerRequestHandler requestExecutor) { if (_defaultExecutor == null) { _defaultExecutor = requestExecutor; } else { throw new AlreadyRegisteredHandlerException(""); } }
void registerHandler(String name, ServerRequestHandler requestExecutor) #
Register ClientRequestHandler
for incomming ClientRequest with
ClientRequest.type
setted to
name. Multiple registration for
same
name cause exception AlreadyRegisteredHandlerException.
void registerHandler(String name, ServerRequestHandler requestExecutor){ if(_registeredExecutors.containsKey(name)){ throw new AlreadyRegisteredHandlerException(name); } else { _registeredExecutors[name] = requestExecutor; } }