All skills

Sails.js framework patterns for The Boring JavaScript Stack - actions, helpers, routes, policies, hooks, configuration, security, middleware, file uploads, deployment, and more. Use this skill when building, reviewing, or debugging any server-side code in a Sails.js application.

Use this Skill: https://skilld.dev/gh/sailscastshq/boring-stack/sails

This session only. Nothing lands on disk.

rulesmiddleware.md

≈1.7k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Middleware

Sails.js is built on Express and uses an HTTP middleware pipeline. Middleware runs on every request before routing occurs.

config/http.js

The middleware pipeline is configured in config/http.js:

// config/http.js
module.exports.http = {
  middleware: {
    // Middleware execution order
    order: [
      'cookieParser',
      'session',
      'bodyParser',
      'compress',
      'poweredBy',
      'router',
      'assetLog',
      'www',
      'favicon'
    ]

    // Custom middleware definitions
    // myCustomMiddleware: function(req, res, next) { ... }
  }
}

Default Middleware Order

Position Middleware Purpose
1 cookieParser Parse cookies from request headers
2 session Initialize session from cookie/store
3 bodyParser Parse JSON and form-encoded request bodies
4 compress Gzip response compression
5 poweredBy Set X-Powered-By header (removed in production)
6 router Sails router -- matches routes and dispatches to actions
7 assetLog Log static asset requests (development only)
8 www Serve static files from .tmp/public/
9 favicon Serve favicon

Important: The router middleware is where Sails takes over. Everything before router runs on every request. Everything after only runs if no route matched.

Adding Custom Middleware

Add middleware by defining it in config/http.js and inserting it into the order array:

// config/http.js
module.exports.http = {
  middleware: {
    order: [
      'cookieParser',
      'session',
      'requestLogger', // Custom middleware
      'bodyParser',
      'compress',
      'poweredBy',
      'router',
      'www',
      'favicon'
    ],

    // Define the custom middleware
    requestLogger: function (req, res, next) {
      sails.log.verbose(`${req.method} ${req.url}`)
      return next()
    }
  }
}

Middleware as npm Packages

Use Express-compatible middleware packages:

// config/http.js
const helmet = require('helmet')

module.exports.http = {
  middleware: {
    order: [
      'cookieParser',
      'session',
      'helmetMiddleware',
      'bodyParser',
      'compress',
      'router',
      'www',
      'favicon'
    ],

    helmetMiddleware: helmet({
      contentSecurityPolicy: false // CSP handled separately
    })
  }
}

Production Middleware Settings

// config/env/production.js
module.exports = {
  http: {
    cache: 365.25 * 24 * 60 * 60 * 1000, // Cache static assets for 1 year
    trustProxy: true // Trust X-Forwarded-* headers from load balancers
  }
}

trustProxy

Enable trustProxy when behind a reverse proxy (Nginx, Heroku, AWS ELB, Cloudflare):

http: {
  trustProxy: true
}

This allows req.ip to return the real client IP (from X-Forwarded-For) instead of the proxy's IP. Also needed for req.protocol to correctly return https.

Body Parser Configuration

The default body parser handles JSON and URL-encoded form data. For large file uploads, you may need to increase limits:

// config/http.js
module.exports.http = {
  middleware: {
    order: [
      'cookieParser',
      'session',
      'bodyParser',
      'compress',
      'router',
      'www',
      'favicon'
    ],

    // Skipper body parser with file upload support and error handling
    bodyParser: (function () {
      var skipper = require('skipper')
      return skipper({
        strict: true,
        limit: '10MB',
        onBodyParserError: (err, req, res) => {
          if (
            _.isNumber(err.statusCode) &&
            err.statusCode >= 400 &&
            err.statusCode < 500
          ) {
            return res.status(400).send(err.message)
          } else if (req.url.match(sails.LOOKS_LIKE_ASSET_RX)) {
            return res.status(403).send()
          } else {
            sails.log.error('Body parser error:', err)
            return res.status(500).send()
          }
        }
      })
    })(),

    // Custom error handler for edge cases (must be last in order)
    middlewareErrorHandler: function (err, req, res, next) {
      if (err.message === 'Range Not Satisfiable') {
        return res.status(416).send()
      } else if (err.message === 'Precondition Failed') {
        return res.status(412).send()
      } else {
        return next(err)
      }
    }
  }
}

Middleware vs Hooks vs Policies

Mechanism When it runs Scope Use case
Middleware Before routing Every request Parsing, compression, logging
Hook routes After routing, before policies Specific route patterns Shared data, feature flags
Policies After hooks, before action Specific actions Authentication, authorization

Choose the right level:

  • Need to modify req/res for all requests? → Middleware
  • Need to share data or run logic for route patterns? → Hook routes
  • Need to guard specific actions? → Policies

Overriding Built-in Middleware

Replace a built-in middleware by defining it with the same name:

// config/http.js
module.exports.http = {
  middleware: {
    // Replace the default session middleware
    session: require('express-session')({
      secret: process.env.SESSION_SECRET,
      resave: false,
      saveUninitialized: false,
      store: new RedisStore({ url: process.env.REDIS_URL })
    })
  }
}

Disabling Middleware

Remove a middleware from the order array to disable it:

// config/http.js
module.exports.http = {
  middleware: {
    order: [
      'cookieParser',
      'session',
      'bodyParser',
      // 'compress',      // Disable compression (handled by CDN)
      // 'poweredBy',     // Don't expose framework
      'router',
      'www',
      'favicon'
    ]
  }
}

Source: SKILL.md on GitHub

1 alert17d4 checks · Risk SAFE
  • Gen Agent Trust Hub17d

    This skill provides comprehensive documentation and coding patterns for the Sails.js framework as used in The Boring JavaScript Stack. It includes detailed guides on application anatomy, security best practices, and production deployment. No malicious patterns or security vulnerabilities were detected.

  • Socket17d

    2 alerts: gptSecurity

  • Snyk17d

    Risk: LOW · No issues

  • Runlayer7mo

    13/20 files flagged

Signed by skilld at bf19e10. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 3 days ago.

Activeupdated 8 months ago
Other metadata
metadata
{
  "author": "sailscastshq",
  "version": "2.1.0",
  "tags": "sails, sailsjs, backend, mvc, actions, helpers, routes, policies, hooks, middleware, deployment, boring-stack"
}

README badge

README badge for sailscastshq/boring-stack/sails