123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 |
- /************************************************************************
- * Copyright 2010-2015 Brian McKelvey.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- ***********************************************************************/
- var extend = require('./utils').extend;
- var util = require('util');
- var EventEmitter = require('events').EventEmitter;
- var WebSocketRouterRequest = require('./WebSocketRouterRequest');
- function WebSocketRouter(config) {
- // Superclass Constructor
- EventEmitter.call(this);
- this.config = {
- // The WebSocketServer instance to attach to.
- server: null
- };
- if (config) {
- extend(this.config, config);
- }
- this.handlers = [];
- this._requestHandler = this.handleRequest.bind(this);
- if (this.config.server) {
- this.attachServer(this.config.server);
- }
- }
- util.inherits(WebSocketRouter, EventEmitter);
- WebSocketRouter.prototype.attachServer = function(server) {
- if (server) {
- this.server = server;
- this.server.on('request', this._requestHandler);
- }
- else {
- throw new Error('You must specify a WebSocketServer instance to attach to.');
- }
- };
- WebSocketRouter.prototype.detachServer = function() {
- if (this.server) {
- this.server.removeListener('request', this._requestHandler);
- this.server = null;
- }
- else {
- throw new Error('Cannot detach from server: not attached.');
- }
- };
- WebSocketRouter.prototype.mount = function(path, protocol, callback) {
- if (!path) {
- throw new Error('You must specify a path for this handler.');
- }
- if (!protocol) {
- protocol = '____no_protocol____';
- }
- if (!callback) {
- throw new Error('You must specify a callback for this handler.');
- }
- path = this.pathToRegExp(path);
- if (!(path instanceof RegExp)) {
- throw new Error('Path must be specified as either a string or a RegExp.');
- }
- var pathString = path.toString();
- // normalize protocol to lower-case
- protocol = protocol.toLocaleLowerCase();
- if (this.findHandlerIndex(pathString, protocol) !== -1) {
- throw new Error('You may only mount one handler per path/protocol combination.');
- }
- this.handlers.push({
- 'path': path,
- 'pathString': pathString,
- 'protocol': protocol,
- 'callback': callback
- });
- };
- WebSocketRouter.prototype.unmount = function(path, protocol) {
- var index = this.findHandlerIndex(this.pathToRegExp(path).toString(), protocol);
- if (index !== -1) {
- this.handlers.splice(index, 1);
- }
- else {
- throw new Error('Unable to find a route matching the specified path and protocol.');
- }
- };
- WebSocketRouter.prototype.findHandlerIndex = function(pathString, protocol) {
- protocol = protocol.toLocaleLowerCase();
- for (var i=0, len=this.handlers.length; i < len; i++) {
- var handler = this.handlers[i];
- if (handler.pathString === pathString && handler.protocol === protocol) {
- return i;
- }
- }
- return -1;
- };
- WebSocketRouter.prototype.pathToRegExp = function(path) {
- if (typeof(path) === 'string') {
- if (path === '*') {
- path = /^.*$/;
- }
- else {
- path = path.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
- path = new RegExp('^' + path + '$');
- }
- }
- return path;
- };
- WebSocketRouter.prototype.handleRequest = function(request) {
- var requestedProtocols = request.requestedProtocols;
- if (requestedProtocols.length === 0) {
- requestedProtocols = ['____no_protocol____'];
- }
- // Find a handler with the first requested protocol first
- for (var i=0; i < requestedProtocols.length; i++) {
- var requestedProtocol = requestedProtocols[i].toLocaleLowerCase();
- // find the first handler that can process this request
- for (var j=0, len=this.handlers.length; j < len; j++) {
- var handler = this.handlers[j];
- if (handler.path.test(request.resourceURL.pathname)) {
- if (requestedProtocol === handler.protocol ||
- handler.protocol === '*')
- {
- var routerRequest = new WebSocketRouterRequest(request, requestedProtocol);
- handler.callback(routerRequest);
- return;
- }
- }
- }
- }
- // If we get here we were unable to find a suitable handler.
- request.reject(404, 'No handler is available for the given request.');
- };
- module.exports = WebSocketRouter;
|