A web app for sending messages over WebSockets using echo.io
JavaScript CSS HTML
Switch branches/tags
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.



A Node.js Express web application that hosts an echo.io WebSocket server.


  • A user can use the web user interface to start and stop a WebSocket server on a specified port.
  • Messages sent to the server will be echoed back to the WebSocket client. The echo message and total round trip time will be displayed.
  • A user can retrieve the message history from the server by sending [HISTORY]. The server will return up to the last 100 messages.

Live site

You can test a live version of echo at the following link:


demo screenshot


Clone this repo or download the archive. Change directory to the package root and run:

npm install

Starting the server

npm start

The server will run on port 3000 by default unless the PORT environment variable is set.

export PORT=80; npm start

Rebuilding client scripts

If you make any changes to the client script files (in the ./client/script/ directory), you will need to regenerate the compiled Handlebars templates and re-browserify the browser JavaScript modules:

npm build

If you plan on doing a lot of editing, you may want to run watchify to automatically build each time files are saved:

npm watch

Web Application Details

echo is an Express single page web application.

It serves the user interface for / requests, and provides the following API to support browser XHR requests:

Starting a WebSocket server

POST /api/v1/echoserver/:port/start

Start a WebSocket server at :port. The acceptable port range is 1024-65535, although a number of ports in that range are restricted or may already be in use on the host.

The server will return a JSON response indicati g success or an error.


curl -X POST localhost:3000/api/v1/echoserver/5555/start


  "status": "ok",
  "message": "echo server started on port 5555"


  "status": "error",
  "message": "listen EADDRINUSE"
Stopping a WebSocket server

POST /api/v1/echoserver/:port/stop

Stop a WebSocket server at :port.

The server will return a JSON response indicating success or an error.


curl -X POST localhost:3000/api/v1/echoserver/5555/stop


  "status": "OK",
  "message": "echo server stopped on port 5555"
Checking WebSocket server state

GET /api/v1/echoserver/:port/

Check a WebSocket server at :port.

The server will return a JSON response indicating the state of the server (stopped or started).


curl -X GET localhost:3000/api/v1/echoserver/5555


  "status": "OK",
  "message": "stopped"

Client application

The client is a Backbone.js application.

The only page that is rendered is a single page application served from /. Although there is no need at the moment for any dynamic server-side rendering, the view is an EJS template with separate header and footer partials for demonstration purposes. It could just as easily be served from the public directory.

The page uses unobtrusive JavaScript with compiled Handlebars templates loaded from a browserified bundle:

<script src="/js/main.bundle.js"></script>

The bundle is generated by browserify, which supports using and developing JavaScript modules in the same style based on CommonJS as Node. JavaScript files located in the client/scripts directory are processed by browserify in a way that generates a single JavaScript file containing the code and recursive dependencies.

Because browserify is listed as a dependency in package.json, it is automatically installed in node_modules. This allows specifying it as an npm script, as shown below:

  "scripts": {
    "start": "node app",
    "build-debug": "browserify -t hbsfy -d -r ./client/scripts/main.js:echo > public/js/main.bundle.js",
    "build-min": "browserify -t hbsfy -r ./client/scripts/main.js:echo | uglifyjs > public/js/main.bundle.min.js",
    "build": "npm run build-debug && npm run build-min",
    "watch": "watchify -t hbsfy -d -r ./client/scripts/main.js:echo -o public/js/main.bundle.js"

Executing the following at the command line will cause both a minified and a debug (non-minified, with a source map) file to be generated:

npm run build

-> outputs single bundle to public/js

The result will be a main.bundle.js and main.bundle.min.js files output to the public/js directory.

The options specified for browserify include a transform plugin called hbsfy. The plugin precompiles the Handlebars templates stored in .hbs files under the client/scripts/views/templates directory. This pre-compilation step saves CPU cycles for the browser client and also allows for a smaller Handlebars download since only the template runtime is needed, and not the template compiler. The views can simply require the templates like any other modules, since after the pre-compilaton step, browserify adds them to the generated bundle also.

As mentioned in a previous section, when editing the client script files, it is helpful to run the the watchify script:

npm watch

Now, each time a client file is saved, watchify will automatically invoke browserify to rebuild the JavaScript bundle.

WebSocket communications

Once a server has been started, the browser app will open a WebSocket to communicate with it. The URI will be in the form ws://host:port, where host is the same as the web application hostname and port is the port that the user specified for starting the WebSocket server.

If the user specifies port 5555 for http://echo.nodester.io, then the WebSocket URI will be ws://echo.nodester.io:5555.

echo uses the echo.io package for WebSocket support and communication protocol. The protocol is documented here. Since the echo.io package hasn't been published to the npm registry, echo package.json specifies the dependency using echo.io's GitHub repo url.