2 - Express WebApp
We will now convert our app into a webapp.
Express
npm install express method-override morgan body-parser cors -—save
Now change index.js replacing the code with the following
import app from './src/server'
const isProduction = process.env.NODE_ENV === 'production'
const port = isProduction ? process.env.PORT : 3001
app.listen(port, () => {
/* eslint-disable no-console */
console.log(`Server running on port ${port}`)
})
Lets start to organize the code, so create a src folder and the server.js file within it
mkdir src
vi src/server.js
Including the following content
import express from 'express'
const app = express()
app.get('/', (req, res) => {
res.status(200).send('hello')
})
export default app
Now we have a simple webserver listening on port 3001 (test environment). So let start it
npm start
And now you can check it either by a UI client like Postman or with a curl command
curl http://localhost:3001/
> hello
Testing the web server (supertest)
That's a start. Now lets setup the infrastructure to start testing the webservice right away.
We will use the supertest which is nice library to test http requests with expectations for the response.
So lets install the dependency
npm install --save-dev supertest
And now we will start also organizing the code. Lets create a folder for this new kind of tests and an initial test.
mkdir test/integration
vi test/integration/api_spec.js
With the following content
/* eslint-env node, mocha */
import request from 'supertest'
import app from '../../src/server'
describe('API', () => {
it('requestiong / gives a hello', (done) => {
request(app)
.get('/')
.expect(200, 'hello', done)
})
})
Lets also remove the old test
rm test/hello_spec.js
Now run the tests
npm test
Logger
Now our server is a sad one. Every time it receives a request it doesn't log anything so it is difficult to develop/debug.
Lets add a logger library
npm install --save morgan
Then edit server.js file and add the following lines (only the ones with comments at the end
import express from 'express'
import morgan from 'morgan' // ADD
const app = express()
app.use(morgan('dev')) // ADD
// ...
Now start the server again and perform a request. You should see something like
[nodemon] 1.11.0
[nodemon] to restart at any time, enter `rs`
[nodemon] watching: *.*
[nodemon] starting `babel-node index`
Server running on port 3001
GET / 200 3.107 ms - 5
Notice the last line !
Setting-up Express
Now in order to successfully process JSON as input and forms data sent to the server we need to configure express. And we will also configure some other misc tasks by using middlewares
npm install --save body-parser compression method-override
As we are going to configure a couple of things into our app it is better to take away that code to keep server.js simple, so go ahead and create a folder and a new file for this configurations
mkdir src/config
vi src/config/express.js
And add the following content
import methodOverride from 'method-override'
import bodyParser from 'body-parser'
import morgan from 'morgan'
import compression from 'compression'
export default function(app) {
app.use(methodOverride())
app.use(bodyParser.urlencoded({ extended: 'true' })) // parse application/x-www-form-urlencoded
app.use(bodyParser.json()) // parse application/json
app.use(bodyParser.json({ type: 'application/vnd.api+json' })) // parse application/vnd.api+json as json
app.use(morgan('dev'))
app.use(compression())
}
We will now update server.js to include this new file and to remove the morgan configuration from there. It should look like this
import express from 'express'
const app = express()
import config from './config/express' // ADDED
config(app) // ADDED
app.get('/', (req, res) => {
res.status(200).send('hello')
})
export default app
So lets try it out with a new end-point.
Edit server.js and add the following
app.post('/', (req, res) => {
const message = `hello ${req.body.to}!`
res.json({ status: 'ok', message: message })
})
Notice that we are using the body attribute from the request. This is possible because of our previous configuration (body-parsers). In this case we are expecting a body with a JSON object like
{
"to" : "someone"
}
We can also write directly a json response with .json() method.
So go ahead an try it with curl (or postman)
curl -X POST http://localhost:3001/ --data '{ "to" : "pepito" }'
> {"status":"ok","message":"hello undefined!"}
But now lets add a new test case for this. Edit test/integration/api_spec.js and add
it('POST / gives a hello including the to', (done) => {
request(app)
.post('/')
.send({ to: 'someone' })
.expect('Content-Type', /json/)
.expect(200, {status: "ok", message: "hello someone!"}, done)
})
Now run the tests again.