NODE
THREE

How about a little review?

Framework built on top of Node. Allows us to quickly build out our server.

const express = require('express')

const app = express()

app.listen(3333, () => console.log('server running on port 3333'))

Express

Custom built behavior that allow us to dictate what is sent back or manage data that is sent to us.

app.get('/api/users', (req, res) => {
    res.stats(200).send(users)
})

Above we have a GET request that will execute a callback function anytime a request is made to the '/api/users/' endpoint and send back all users.

Routes/Endpoint

  • Massive - Data mapper that allows us to execute functions that will run our custom built sequel commands.
const massive = require('massive')

massive(CONNECTION_STRING).then((database) => {
    app.set('db', database)
})

app.get('/api/users', (req, res) => {
    req.app.get('db').SQL_COMMAND().then((users) => {
        res.send(users)
    })
})

Massive connects to a Heroku hosted database. We then set a key/value pair called 'db' with a value of database on app. Anytime we want to run a sql command, Massive looks to the root of our project directory for a folder called db. We cannot call this anything else. It will then look for a corresponding sql command that it will execute as a function.

  • dotenv - File that will not expose the stuff we need to keep safe like passwords, connection strings or secrets
require('dotenv').config()

massive(process.env.CONNECTION_STRING)

const PORT = process.env.SERVER_PORT

dotenv always follows the process.env.VARIABLE_NAME syntax. Remember, we solemnly swear we are up to no good will never push up our .env file. The .env file should be at our project root, just like the db folder Massive looks for.

  • body-parser - Middleware that allows us to access data off of our body object when a body is sent.
const express = require('express')
const app = express()

app.use(express.json())

Above we are telling our app variable to use the .json() method on the express object. But why do we pass it into app.use()?  This means that every request, no matter the verb, will use the express.json() function. This is known as middleware.

Middleware

Function that is literally ran in the middle of our requests. This can be all requests or individually.

Middleware

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

app.use(bodyParser.json()) //used on every request

const dateLogger = (req, res, next) => {
    const date = new Date().toLocaleDateString()
    const time = new Date().toLocaleTimeString()
    console.log(`${req.method} ${req.path} ran on ${date} at ${time}`)
    next()
}

app.get('/', dateLogger, (req, res) => {
    // ACTION TO BE PERFORMED
})

// dateLogger is ran anytime we receive a GET request on the '/' route

Middleware

Middleware can be installed via a package, such as bodyParser or cors, or you can create custom middleware as shown by our dateLogger example

What was that next() function?

- You

const dateLogger = (req, res, next) => {
    const date = new Date().toLocaleDateString()
    const time = new Date().toLocaleTimeString()
    console.log(`${req.method} ${req.path} ran on ${date} at ${time}`)
    next()
}

app.get('/', dateLogger, (req, res) => {
    // ACTION TO BE PERFORMED
})



Looking back at our example, we see that are passing in a new param, called next, to our callback function.

Next basically says "Move onto the next applicable route or function"

const dateLogger = (req, res, next) => {
    const date = new Date().toLocaleDateString()
    const time = new Date().toLocaleTimeString()
    console.log(`${req.method} ${req.path} ran on ${date} at ${time}`)
    next()
}

app.get('/', dateLogger, (req, res) => {
    // ACTION TO BE PERFORMED
})



Server: Okay, looks like we received a GET request to the '/' route. Let's run the dateLogger function

dateLogger: I am going to log the date and time and then tell the next function in line to run once I have completed what I need to. Next()

Server: Run callback, run (req, res) => {}

What if we leave next() out?

-You

The next function in line, whether on the same or different route, run.

Practical Example

const express = require('express')
require('dotenv').config()
const app = express()

app.use(express.json())

const checkAdmin = (req, res, next) => {
    const {isAdmin} = req.body
    if(isAdmin){
        // DO ADMIN STUFF, if necessary
        next()
    }
    // TELL THAT FOOL TO GET LOST
}

app.get('/admin', checkAdmin, (req, res) => {
    res.send('Take a look at this admin stuff')
})


const PORT = process.env.SERVER_PORT
app.listen(PORT, () => console.log(`magic is happening on ${PORT}))

Have you ever been to a site that you always have to login to, even though you just logged in ten minutes ago?

It's
Annoying
AF*

*As Frank

Allow me to introduce you to sessions

A session is where you can store data for a user across multiple requests and lengths of time.

Sessions Continued

Sessions can be stored in a variety of ways

  • In memory
  • In a cookie
  • In a memory cache
  • In a database

Imagine you go to Starbucks and order a drink...

const express = require('express')
require('dotenv').config()
const session = require('session')
const app = express()

app.use(express.json())
app.use(session({
    secret: process.env.SESSION_SECRET,
    resave: false,
    saveUninitialized: false,
    cookie: {
        maxAge: 1000 * 60 * 60
    }
}))

const viewCount = (req, res, next) => {
    if(req.session.views){
        req.session.views++
    } else {
        req.session.views = 1
    }
    next()
}

app.get('/', viewCount, (req, res) => {
    res.send(`You have viewed this page ${req.session.views} times`)
})

const PORT = process.env.SERVER_PORT

app.listen(PORT, () => console.log(`it vas lit on port ${PORT}`))

Session Setup

app.use(session({
    secret: process.env.SESSION_SECRET,
    resave: false,
    saveUninitialized: false,
    cookie: {
	maxAge: 1000 * 60 * 60
    }
}))
  • Secret: this should be a pretty random string. This makes it difficult for people to hack the session
  • Resave: force save a session even if it wasn't modified
  • saveUninitialized: Will auto create a session without any sort of modification or acceptance from user
  • Cookie: Set different defaults for our cookie

Sling
Some
Code

Copy of node three

By jonmcd

Copy of node three

  • 126