Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

autohost

Package Overview
Dependencies
Maintainers
2
Versions
110
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

autohost

Resource-driven http server

  • 0.1.32
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
1.9K
increased by6045.16%
Maintainers
2
Weekly downloads
 
Created
Source

autohost

Convention-based, opinionated HTTP server library based on express. Lovingly ripped from the guts of Anvil.

This library is experimental and rapidly changing.

Features

  • Resource-based: define protocol-agnostic resources that interact via HTTP or WebSockets
  • Auto-reloads resources on file change
  • Supports server-side websockets and socket.io
  • UI dashboard to review resources' routes, topics and hosted paths

UI Dashboard

Simple navigate to /_autohost to review the current set of resources: An Example AutoHost Application's Dashboard

Quick Start

var host = require( 'autohost' )();
host.init();

Configuration

While the configuration can be provided optionally to the init call, it's recommended to pass this during instantiation after the require.

The object literal follows the format:

{
	appName: '' // application name - used specifically by autohost auth libraries
	static: './public', // where to host static resources from, default value shown
	resources: './resource', // where to load resource modules from, default value shown
	port: 8800, // what port to host at, default shown
	allowedOrigin: 'leankit.com', // used to filter incoming web socket connections based on origin
	websockets: true, // enables websockets
	apiPrefix: '/api', // if you MUST, you can change the prefix of resource routes
	socketIO: true, // enables socket.io,
	noSession: false, // disables sessions
	noCookie: false, // disables cookies
	noBody: false, // disables body parsing
	noCrossOrigin: false // disables cross origin
}

Recommended

var autohost = require( 'autohost' )( {
	appName: 'demo',
	port: 8881
} );

Resources

Resources are expected to be simple modules that return a parameterless function resulting in a JS literal that follows the format:

	{
		name: 'resource-name',
		resources: '', // relative path to static assets for this resource
		actions: [ 
			{
				alias: 'send', // not presently utilized
				verb: 'get', // http verb
				topic: 'send', // topic segment appended the resource name
				path: '', // url pattern appended to the resource name
				handle: function( envelope ) {
					// envelope.data, envelope.headers and envelope.params may contain
					// information about the request/message received

					// envelope reply takes a object literal with data property for
					// http body|websocket message					
				}
			}
		]
	}

Envelope

// common properties
{
	data: // the request/message body
	path: // url of the request (minus protocol/domain/port) OR message topic
	headers: // request/message headers
	user: // the request/socket user
	responseStream: // a write stream for streaming a response
}

// the following properties are only available on HTTP envelopes
{
	context: // metadata added by middleware
	params: // query parameters
	files: // files supplied in body
}

// the following properties are only available on Socket envelopes
{
	socket: // the socket the message arrived on
}

reply( envelope )

Sends a reply back to the requestor via HTTP or web socket. Response envelope is expected to always have a data property containing the body/reply. HTTP responses can included a statusCode property (otherwise a 200 is assumed).

replyWithFile( contentType, fileName, fileStream )

Sends a file as a response.

forwardTo( opts )

Forwards the request using the request library and returns the resulting stream. Works for simple proxying.

	envelope.forwardTo( {
		uri: 'http://myProxy/url'
	} ).pipe( envelope.responseStream );

Authentication

Authentication support is supplied via Passport integration. Your application is expected to provide a strategy and authentication method. You can also provide a regex path to make part of your path open to anonymous access.

You must set this up BEFORE calling .init, calling it after initialization will probably cause 'splosions.

// Note: this is an over-simplification, typically you'd tie in auth store access inside the callback.
// Each passport strategy implementation will differ, please see those for details.
var passport = require( 'passport' );
var BasicStrategy = require( 'passport-http' ).BasicStrategy;
var host = require( '../src/autohost.js' )();

host.withPassportStrategy(
	new BasicStrategy({}, function( username, password, done ) {		
		if( username == 'anon' || ( username == 'admin' && password == 'admin' ) ) {
			done( null, username );
		} else {
			done( null, false );
		}
	} ),
	passport.authenticate( 'basic', { session: false } ),
	/^[\/]anon.*/ );

Authorization

The general approach is this:

  1. every action in the system is made available to the authorization strategy on start-up
  2. an action may be assigned to one or more roles in your authorization strategy
  3. a user may be assigned to one or more roles in your authorization strategy
  4. when a user attempts to activate an action, the action roles are checked against the user roles
  5. if a match is found in both lists, the action completes
  6. if the user has no roles that match any of the action's roles, the action is rejected (403)
  7. if the action has NO roles assigned to it, the user will be able to activate despite roles

This basically goes against least-priviledge. If this is a problem, assign a baseline 'authenticated' or 'user' role to every action returned to you during server start-up OR always return either of these during the 'getRolesFor' call.

The authorization strategy MUST implement 3 calls:

actionList( list, done )

Will recieve a hashmap of resources and resource action names. Action names follow a namespace convention of {resource name}.{alias}. The done call back MUST be called.

Here's an example of the format.

{
	'_autohost': [
		'_autohost.api', 
		'_autohost.resources', 
		'_autohost.actions', 
		'_autohost.connected-sockets'
	]
}

This is provided to your auth provider so that actions can automatically be updated (as in storage) on-the-fly when the server spins up.

getUserRoles( user, done ) -- done( err, roles )

Given a user's id, this must return any roles assigned to the user in the system. Done must be called with error or roles. An exception should never be allowed to bubble up through this call.

getRolesFor( action ) -- done( err, roles )

During activation, the action name ( resource.alias ) is passed to this call to determine what roles are able to activate the action. If you don't want actions to default to enabled despite user role, ALWAYS return at least some baseline role ( i.e. 'user', 'authenticated', etc. ).

Done must be called with error or roles. An exception should never be allowed to bubble up through this call.

Auth admin panel (Experimental)

In order to use this feature, you must provide an authorization strategy with several additional calls. It should go without saying that you're expected invoke the callback with either the result or an error.

Documentation on this API coming soon, see autohost-riak-auth library for an example

Web Socket Stuff

WebSocket-Node library

When establishing a connection to autohost using the WebSocket-Node client, you'll need to append '/websocket' to the end of the URL. This enables autohost to support both socket.io and WebSocket-Node simultaneously.

Methods

  • sendToClient( id, topic, message ) - sends message to specific client via websocket (returns true if successful)
  • notifyClients( topic, message ) - sends message to all clients via web sockets

Events

  • 'socket.client.connected', { socket: socketConnection } - raised when a client connects
  • 'socket.client.identified', { socket: socketConnection, id: id } - raised when client reports unique id
  • 'socket.client.closed', { socket: socketConnection, id: id } - raised when client disconnects the websocket connection

TO DO

  • Add support for clustering (multiple listening processes)
  • Add support for user authentication and authorization (access) logging
  • Add support for rate limiting
  • Better logging
  • More thorough error handling

License

MIT License - http://opensource.org/licenses/MIT

FAQs

Package last updated on 08 Jul 2014

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc