Weekend

Code Warrior

Building API's Quicker

James Gibson

  • Website: gibsunas.co
  • Twitter: @thenodester
  • Github: james-gibson
    
  • Denver Devs Slack: james.the.nodester

Platform Architect & Co-Founder @
Gibsunas Consulting, LLC 

express --git -c sass

So you've run the express generator, now what?

First things first

[npm i || yarn]

Remove bits we don't need

app.use(express.static(path.join(__dirname, 'public')));

We won't need static hosting for the API because it will be serving up only JSON

app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

Also, remove the view engine

Remove bits we don't need

app.use(cookieParser());

Our API will use token-based auth so no cookies needed

And more bits we don't need

Don't forget to remove the things mentioned above from your package.json as well!

Install helpful bits

npm i -S dotenv

// Using PostgreSQL?
npm i -S pg knex

// Using MongoDB? 
// Not my problem.

These packages might come in handy

npm i --save-dev eslint
npm i --save-dev jest
npm i --save-dev flow

These will come in handy

Add useful bits

app.get('/health', (req, res, next) => {
    res.status(204);
    res.send();
});

Health check for future automation

And more useful bits!

app.use((req, res, next) => {
   req.custom = {
      // Add objects/functions here that make your life 
      // easier when you are processing requests.
       
      postgres: ...,
      redis: ...,
   };
   next(); 
});

Install custom services into your request object

Keep track of the bits

var knex = require('knex')({
  client: 'postgres',
  connection: process.env.DATABASE_URL 
  // i.e. postgres://user:pass@localhost:5432/dbname 
});

Instantiate that db connection

Don't leak bits

app.use((error, req, res, next) => {
  let baseResponse = {
    status:'50x'
  };
  
  let envResponse;
  if(process.env.NODE_ENV == 'development') {
    envResponse = {
      message: error.message
    };
  } else {
    envResponse = {
      message: 'Looks like something broke'
    };
  }
  let response = Object.assign(
    {}, 
    baseResponse, 
    envResponse
  );
  res.json(response);
});

Remove some header bits

app.use((req, res, next) => {
   res.removeHeader('Content-Encoding');
   res.removeHeader('X-Powered-By');
   next();
});

Why should we announce that this is an Express server?

Optionally: Add some header bits

app.use(cors());
npm i -S cors
app.use((req, res, next) => {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", 
    "Origin, X-Requested-With, Content-Type, Accept");
  next();
});

||

But how do I secure this?

var passport = require('passport');
var GoogleStrategy = 
    require('passport-google-oauth').OAuthStrategy;

passport.use(new GoogleStrategy({
    consumerKey: GOOGLE_CONSUMER_KEY,
    consumerSecret: GOOGLE_CONSUMER_SECRET,
    callbackURL: "https://<your url here>/callback"
  },
  function(token, tokenSecret, profile, done) {
      // verify user here
  }
));

This seems like overkill...

oAuth right?

It is.

Please don't mistake me, oAuth is pretty awesome.  But it comes with a lot of setup.

Local User Then?

var passport = require('passport')
  , LocalStrategy = require('passport-local').Strategy;

passport.use(new LocalStrategy(
  (username, password, done) => {
    // verify the given credentials match what 
    // you'd expect in your db
  }
));

We'd still have the user management issue

We need simple

very simple.

app.use((req, res, next) => {
    let expectedToken = process.env.API_AUTH_TOKEN;
    let { token } = req.query;

    if(expectedToken !== token) {
        res.status(401);
        res.json({
            error: "Unauthorized action"
        });
    }
    
    next();
});

Where API_AUTH_TOKEN:

(run this in your cmd line)

openssl rand -base64 30  #Don't commit this!

Use Docker!

FROM node:8.4
WORKDIR /usr/src/app
COPY package.json .
COPY . .
RUN yarn 
CMD ["npm", "start"]

Let someone else do the work

Our problems are not always unique

Keep your bits small

This is for fun isn't it?

  • Build more than one service if it makes sense
    • Single route services?
    • Hosting is cheap!
  • Consider writing Swagger docs if it keeps you organized

Don't spend more than needed

Don't spend more than needed (cont.)

* This is a referral link.

Other Helpful Tips

  • Take really good notes!

 

 

  • Browser bookmarks are free!

Thank you!

  • Website: gibsunas.co
  • Twitter: @thenodester
  • Github: james-gibson
    
  • Denver Devs Slack: james.the.nodester
Made with Slides.com