Miguel Coder
Miguel Coder

Reputation: 1949

Node Middleware Without Express

I'm building an AWS Lambda Server to Integrate with API Gateway and I'm unable to expose the server so that I can hook it into Express. I'm wondering if anyone knows a best practice for using middleware without Express.

Here is my code.

    var jobs = require('./jobs');
    var http = require('http')

    const server = http.createServer()

    server.on('request', (req, res) => {


    //I want to be able to add a function here that executes all of the middleware that I specify.

    const { headers, method, url } = req;

    let body = [];

    if(url)

            enableCors(res);
            res.writeHead(200, {'Content-Type': 'application/json'})

            const resBody = { headers, method, url, body };

            res.write(JSON.stringify(resBody));
            res.end();
    }).listen(8080);

I want to have something similar to Express where I can write something like this and the server will know to search that directory for my routes.

server.use('/api', require('./api'))

Upvotes: 1

Views: 4710

Answers (3)

Noel Llevares
Noel Llevares

Reputation: 16077

Since what you want is a local simulation of API Gateway using express, here's what I'm using for my projects.

This does not require serverless or claudiajs.

I also always just use Lambda Proxy integration so it's simpler.

Something like this...

const bodyParser = require('body-parser')
const cors = require('cors')
const express = require('express')

// Two different Lambda handlers
const { api } = require('../src/api')
const { login } = ('../src/login')

const app = express()

app.use(bodyParser.json())
app.use(cors())

// route and their handlers
app.post('/login', lambdaProxyWrapper(login))
app.all('/*', lambdaProxyWrapper(api))

app.listen(8200, () => console.info('Server running on port 8200...'))


function lambdaProxyWrapper(handler) {
  return (req, res) => {
    // Here we convert the request into a Lambda event
    const event = {
      httpMethod: req.method,
      queryStringParameters: req.query,
      pathParameters: {
        proxy: req.params[0],
      },
      body: JSON.stringify(req.body),
    }

    return handler(event, null, (err, response) => {
      res.status(response.statusCode)
      res.set(response.headers)

      return res.json(JSON.parse(response.body))
    })
  }
}

Then, run it with nodemon so it watches the files and reloads as necessary.

nodemon --watch '{src,scripts}/**/*.js' scripts/server.js

Upvotes: 3

Miguel Coder
Miguel Coder

Reputation: 1949

I found a way to simulate a local Lambda and API Gateway using the serverless framework with the serverless-offline plugin and following this tutorial.

This builds a dockerized container that allows me to create my endpoints locally using the serverless.yml file in the following format.

functions:
  getDataFromBackend:
    handler: handler.handlerFunc
    events:
      - http:
          path: /api/path/to/endpoint/{param}
          method: get
          cors: true

Then I after I run this command...

sls offline start -r us-east-1 --noTimeout

I get endpoints that I can hit by adding their respective functions to the handler.js file.

These functions receive the (event, context, callback) functions just like a Lambda function would.

Now I can build for serverless locally :)

I hope this helps someone

Upvotes: 0

Paul
Paul

Reputation: 36339

Node http has no concept of middleware. You either need to create your own middleware chain, or else use something like express. If, for some reason, you don't want to use express (not clear from your question why this is the case) you could always choose to use connect, which express is based on.

var connect = require('connect');
var http = require('http');

var app = connect();

// gzip/deflate outgoing responses
var compression = require('compression');
app.use(compression());

// store session state in browser cookie
var cookieSession = require('cookie-session');
app.use(cookieSession({
    keys: ['secret1', 'secret2']
}));

// parse urlencoded request bodies into req.body
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({extended: false}));

// respond to all requests
app.use((req, res) => {
  const { headers, method, url } = req;

  let body = [];

  if(url)
    enableCors(res);
  res.writeHead(200, {'Content-Type': 'application/json'})

  const resBody = { headers, method, url, body };

  res.write(JSON.stringify(resBody));
  res.end();
});

//create node.js http server and listen on port
http.createServer(app).listen(8080);

Upvotes: 1

Related Questions