v17.1.0: Raw HTTP body and JSON param filtering

@evantahler evantahler released this Aug 10, 2017 · 30 commits to master since this release

Store connection.rawConnection.params.rawBody on web connections

Some APIs ask you to compare checksums of the body of a request (#1081) to ensure their origin. Until now, ActionHero did not allow you access to the raw POST/PUT body of an http request. A new config option, api.config.servers.web.saveRawBody can be toggled to true to save the body of your requests as a Buffer.

Please note that enabling this feature may increase the memory requirements of each of your actions.

Use dot-prop package with api.config.general.filteredParams to allow for filtering of JSON params

Uses the dot-prop package to allow for filtering parameters using a dot notation.

Added to api.utils.filterObjectForLogging since I wanted the filter for my own logging messages as well (not just action logs)

//example, as filled from config/api.js
filteredParams: [ 'p4', 'o1.p3' ],

//example, as used in initializers/actionProcessor.js
var params = { p1 : 1, o1 : { p2: 'ok', p3: 'secret' }, p4: 'long string that clogs logs' }
var filteredParams = api.utils.filterObjectForLogging( params)
//filteredParams --> { p1 : 1, o1 : { p2: 'ok', p3: '[FILTERED]' }, p4: '[FILTERED]' }


  • All dependent packages updated to their latest versions
  • Updated worker log messages to start with to [ worker ] (rather than worker:) to match [ action ]


v17.0.3: Server Custom Methods

@evantahler evantahler released this Jul 3, 2017 · 46 commits to master since this release

Server Custom Methods

  • You can now create custom methods on your connections!
  • The first of these, which is included within ActionHero by popular request, is connection.setHeader, which is a proxy for connection.rawConnection.res.setHeader
  • You can create you own extensions to servers with a middleware:
 module.exports = {
   startPriority: 1000,
   start: function (api, next) {
     let webServer = api.servers.servers.web
     webServer.connectionCustomMethods = webServer.connectionCustomMethods || {}
     webServer.connectionCustomMethods.requestHeaders = function (connection) {
       return connection.rawConnection.req.headers

 module.exports = {
   name: 'logHeaders',
   description 'Log Web Request Headers',
   run: function (api, data, next) {
     let headers = data.connection.requestHeaders()
     api.log('Headers:', 'debug', headers)
  • Note that the type of connection determines the server, which then sets the custom methods. The above example of connection.setHeader only works for web connections.
  • by @evantahler and @gcoonrod via #1080

Config option to disable access to internal CLI commands

  • Using the new api.config.general.cliIncludeInternal option, you can prevent use of the ActionHero CLI commands in your project from including the internal methods, like generate and generateAction
  • This is helpful if you are shipping an application with your own CLI commands
  • bu @evantahler via #1076

Fix memory leak for actions with data.toRender: false

  • For actions with data.toRender !== true, not called connection.destroy().
    This provoked memory leak.
  • by @witem via #1078

ClusterPidfile Cleanup

  • Remove cluster_pidfile when stopping process gracefully
  • catch for removing the 0th worker
  • by @evantahler via #1065

New ActionHero Website


  • Commit NPM package-lock.json
  • Update integration tests to run on node v8
  • Move test runner to circle.ci from travis.ci


v17.0.2: Redis Priority and Dependency Updates

@evantahler evantahler released this May 21, 2017 · 86 commits to master since this release

Update Redis stop priority to be last

The Reids initializer is likely to be relied on by many other parts of the system. To that end, the 'stop' priority of redis is now 99999

Update Major versions of dependancies

  • cross-env now at v5.0.x
  • ws now at v3.0.x
  • ioredis now at v3.0.x


v17.0.1: revert to use recursiveDirectoryGlob for link following

@evantahler evantahler released this May 7, 2017 · 100 commits to master since this release

Revert to use recursiveDirectoryGlob for link following

We have reverted to bring back api.utils.recursiveDirectoryGlob for link following. Perviously, v17.0.0 did not follow ActionHero's link files properly

Catch Exceptions in Initializers

via @S3bb1 via #1045


v17.0.0 Localization and Custom CLI Commands

@evantahler evantahler released this Apr 24, 2017 · 107 commits to master since this release

Saner Localization

  • clarify the usage of i18n and connection.localize by converting all localizations to use mustache-style strings. IE: data.connection.localize(['hello {{name}}', {name: 'Evan'}]) rather than data.connection.localize(['hello %s', 'Evan'])
  • [BREAKING CAHNGE] Stop localizing all internal and logging messages
    • this feature was rarely used and added complexity. This also slowed down the logging of message from the server as it required 2 interpolation passes each time
    • convert all internal message interpolation into es6 interpolation, ie: a log ${message}. Now that we required node v4+, this is OK
  • [BREAKTING CHANGE] move all user-visible strings from actionhero into the locale file. This creates a single file which can be used to modify ActionHero strings
  • ensure that by default, calling either api.i18n.localize or connection.localize on an unknown string will not cause an error, and this string will be added to the locale file properly
  • by @evantahler via #1036

Custom CLI Commands

Allow actionhero developers to create new files in ./bin which can be run via the CLI. These commands will have access to a the ActionHero api and CLI arguments object within a run method.

For example, a file in ./bin/redis/keys would be run via ./node_modules/.bin/actionhero redis keys --prefix actionhero

'use strict'

module.exports = {
  name: 'redis keys',
  description: 'I list all the keys in redis',
  example: 'actionhero keys --prefix actionhero',

  inputs: {
    prefix: {
      requried: true,
      default: 'actionhero',
      note: 'the redis prefix for searching keys'

  run: function (api, data, next) {
    api.redis.clients.client.keys(data.params.prefix, (error, keys) => {
      if (error) { throw error }

      api.log(`Found ${keys.length} keys:`)
      keys.forEach((k) => { api.log(k) })

      return next(null, true)
  • [breaking change]: ActionHero projects will now be generated with a ./bin directory.
  • [breaking change]: ./config/api.js now defines api.config.general.paths.cli, which defaults to path.join(__dirname, '/../bin'). This is where the actionhero script runner sources its files.

ActionHero CLI commands have:

  • name
  • description
  • example

Inputs for CLI commands have

  • required (true/false)
  • default (string only)
  • note

These are sourced by actionhero help, and the example above would return:

* redis keys
  description: I list all the keys in redis
  example: actionhero keys --prefix actionhero
    [prefix] (optional)
      note: the redis prefix for searching keys
      default: actionhero

This PR includes a refactor of all CLI commands

Replace api.utils.recursiveDirectoryGlob with the glob package

Breaking Changes and How to Overcome Them:

  • Localization (i18n)
    • In ./config/i18n.js be sure to enable objectNotation, or else the new locale file will be gibberish to ActionHero
    • As of this release, ActionHero no longer localizes its log messages. This is done to simplify and speed up the logger methods. There is not mitigation path here without overwriting the api.log() method.
    • Any use of % interpolation should be removed from your logger strings. Favor native JS string templates.
  • ActionHero now ships with locale files by default.
    • You will need to acquire the default locale file and copy it into ./locales/en.json within your project.
    • The error reporters have all been changed to use these new locale file and mustache-style syntax.
      Update your from the default errors file
    • The welcomeMessage and goodbyeMessage are removed from the config files and ActionHero now refrences the locale files for these strings. Update yours accodingly.
  • api.utils.recursiveDirectoryGlob has been removed in favor of the glob package. Use this instead.


v16.0.5: Connection Internal Errors

@evantahler evantahler released this Apr 6, 2017 · 131 commits to master since this release

This minor release ensures that connections return error objects internally when attempting to use a not-found verb. This also ensure that the socket server responds with the error string in the same manner it used to maintain backwards compatibility.

by @evantahler via dbef734


v16.0.4: Cache Lock fix and Standard fixed

@evantahler evantahler released this Apr 6, 2017 · 133 commits to master since this release

Fix for api.cache.lock

The old implementation of the api.cache.lock method did not check the result of the setnx function, which could have lead to multiple nodes acquiring the same lock multiple times.

Update to the latest version of Standard

The latest version of Standard.js checks for deprecated methods from node's core. We were using a few of these older methods and they have been removed.


  • Update all dependent packages to their latest versions


v16.0.3: New Github Team and Nested schema inputs

@evantahler evantahler released this Mar 28, 2017 · 144 commits to master since this release

New actionhero github team.

This repo is now actionhero/actionhero (rather than the old evantahler/actionhero). We are a grown up organization now! All links in the project and docs should be updated.

Add schema inputs for Actions

Add schema input type for actions which allow validator, required, default, and formatter for actions with inputs having nested properties.

exports.addUser = {
  name: 'api/addUser',
  description: 'I add user',
  firstName: { required: true },
  lastName: { required: false },
  username: { required: true },
  address: {
    required: false,
    schema: {
      country: {
        required: true,
        default: 'USA'
      state: { required: false },
      city: {
        required: true,
        formatter: (val) => `City:${val}`,
        validator: (val) => val.length > 10,
  run: () => {},

Newly generated projects include standard.js and pass lint

New Actionhero projects (created with actionhero generate) will now include standard as a devDependency and pretest with the linter. New package.json will also include the necessary standard global ignores so that everything passes. This is all also now tested

fix(http): use documented api methods to set headers

We now properly supply connection.rawConnection.res.writeHead with a hash rather than an array.


Update all dependant packages to their latest versions.

  • This will include a major version bump to both fakeredis and primus


v16.0.2: Standard & hotfix

@evantahler evantahler released this Mar 1, 2017 · 175 commits to master since this release

  • Fixes a bug introduced in v16.0.1 which would crash the server if rebooting due to initializer change in development mode [#1006]
  • Upgrades our test suite & linter to Standard v9.
    • Includes dirty-chai, to enforce that the chai matchers we use in our test suite follow proper JS convention, and avoid assertions on access.


v16.0.1: Streams & Tests

@evantahler evantahler released this Feb 24, 2017 · 182 commits to master since this release

Do not require a fileLength when sending a stream

(web server) Allows Actionhero to pipe streams of unknown length to web clients, skipping the Content-Length header

Error on duplicated initializer name

When booting Actionhero, if you have initializers with duplicated names (including those which would overwrite a core initializer) the server will exit with a relevant error message.

Fixes socket helper functions

(when booting the web server) cleanSocket and chmodSocket both assumed port to be a string. While this should be the case, there are no prior checks for this condition so the error thrown is quite confusing for the end user. The code has been modified to check that the port is a string type before calling indexOf on it.


  • Better testing of redis shutdown behavior
  • use cross-env in test environment so windows users can play along at home
  • Ensure that generator and test examples pass Standard lint
  • Move to the Chai assertion library in tests, dropping should

Upgrade dependent packages to latest versions