Node.js Scalable Web Services A lot of buzz around Node.js centers on using it for writing scalable web-sites, apps and services We will now learn how to develop robust, RESTful, JSON-based web services
Node.js HTTP Server Express is a web application framework for Node It is modeled after the Ruby project Sinatra Express provides a lot of plumbing code Let us start with a basic server using only Nodes
http
module
1. const 2. http = require('http'), 3. server = http.createServer(function(req, res) { 4. res.writeHead(200, {'Content-Type': 'text/plain'}); 5. res.end('Hello World\n'); 6. }); 7. server.listen(8080, function(){ 8. console.log('ready captain!'); 9. }); example_code/express/basic_server/basic_server.js
Node.js HTTP Server Request lifecycle
Node.js HTTP Server This is similar to creating a basic TCP server Using the As well as
http
module
server.listen()
createServer()
with a callback for responding
to bind a TCP socket on port 8080
The callback function uses information from the incoming HTTP request to send a response This example lacks a lot of regular tasks of web servers Routing based on URL paths Managing sessions via cookies Parsing incoming requests (form data or JSON) Rejecting malformed requests
The Express framework helps with these and a lot of other things
Node.js Express Serving APIs
Installing Express is - as previously seen - achieved by a call to
npm
npm install --save express
Remember: If you already have a 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13.
package.json
file, this will save the dependency
#!/usr/bin/env node --harmony 'use strict'; const express = require('express'), morgan = require('morgan'), app = express(); app.use(morgan('dev')); app.get('/api/:name', function(req, res) { res.status(200).json({'hello': req.params.name}) }); app.listen(8080, function(){ console.log("ready captain."); });
example_code/express/basic_server/express_server.js
Node.js Express Serving APIs
Note: Even though NodeJS the Right Way is from 2013, the code examples given in the book on Express are outdated in various spots This is not unusual - Web development changes fast Back to the Code First, the program requires Express and creates an application context app
Node.js Express Serving APIs
Express functionality is provided by something called middleware Those are asynchronous functions manipulating the request and response objects To specify such middleware, we call
app.use()
As done with morgan which is a logger middleware In dev mode all requests will be logged to the console is telling Express how to handle HTTP GET requests to the /api/:name path app.get()
The
:name
chunk is called a named route parameter
When the API is hit, that part of the URL will be made available in req.params
Node.js Express Serving APIs
Express has
put()
,
post()
, and
del()
to register handlers for HTTP
In the example above, we tell the response object JSON An object whose
hello
key is set to the
name
res
to send back
parameter
Finally, the program listens on TCP port 8080 for incoming HTTP requests
Node.js Express Running a server with npm
Instead of starting the server with Node directly, we can also use npm npm start
npm knows how to run the server, because of a
scripts
hash in
package.json
1. "scripts": { 2. "start": "node --harmony ./express_server.js" 3. } Excerpt
example_code/express/basic_server/package.json
You can also add a
test
item to the scripts hash to use npm for testing
Node.js Express Running a server with nodemon
Note that when you run your server using Node or npm, once you change your code, you will have to restart your server nodemon (short for Node Monitor) runs a Node program and automatically restarts whenever the source code changes Install it using npm install -g nodemon
Then use it as previously the node command nodemon --harmony express_server.js
Node.js Express Testing REST Endpoints with curl
With the
express_server
running, try it out using curl
curl is a useful commandline tool for issuing HTTP requests The flag 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11.
$
-i
tells curl to output HTTP headers in addition to the body
curl -i http://127.0.0.1:8080/api/jimbo
HTTP/1.1 200 OK X-Powered-By: Express Content-Type: application/json; charset=utf-8 Content-Length: 17 ETag: W/"11-663c743" Date: Mon, 10 Nov 2014 13:28:24 GMT Connection: keep-alive {"hello":"jimbo"}%
Node.js Express Testing REST Endpoints with curl
In the server terminal, you should see 1. GET /api/jimbo 200 0.611 ms - 17
Other often used flags for curl are -X [METHOD]
, for example
-H "headers"
-d [JSON]
, for example
, for example
-X POST
-H "Content-Type: application/json"
-d '{"username":"xyz","password":"abc"}'
Node.js Express Minimalist Todo Application
In
example_code/express/todo_server
Start it with Visit
you can find a very minimalist todo app
node --harmony todo_server.js
http://localhost:8080/
and enter a few todos
Node.js Express Minimalist Todo Application - HTML
The HTML is kept slim for readability 1. 2. 3. <script src="/jquery.js"> 4. <script src="/app.js"> 5. 6. 7. 8. Create new todo: 9. Save 10. 11.
14. 15.
Node.js Express Minimalist Todo Application - HTML
In the HTML code, there is a new
form
tag
With forms, we can handle user input A form should have an GET) The
action
action
and can have a
method
(which defaults to
presents the endpoint where the form-data will be sent to
All form inputs (in our case one input field) will be serialized and POSTed to /todos
Node.js Express Minimalist Todo Application - frontend JS
This minimalist application seems poor in features, but it Facilitates RESTful requests to load and save todos Uses Ajax requests to bring a fast user experience Is all in all only a couple lines of code
What does the frontend JS do? Uses HTTP GET
/todos
Uses HTTP POST
to load all todos upon initial load (see
/todos
to save a new todo (see
app.js
app.js
)
)
Hence, it never has to do a complete page reload
We're not going to dig further into the frontend JS, it's 15 lines of jQuery as described in Web2
Node.js Express Minimalist Todo Application - backend JS
On the server side this app has a couple of new features (see todo_server.js ) It serves static content. This is done by using the middleware.
express.static
Whenever a route cannot be found within Express, it will try to load the file from the folder static_html 1. app.use(express.static(__dirname + '/static_html'));
It parses requests by utilizing a
bodyParser
middleware
Making it possible to easily read form data input 1. app.use(bodyParser.urlencoded({ extended: false }));
Node.js Express Minimalist Todo Application - backend JS
It has two methods defining a route to other with POST 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.
/todos
, one with HTTP GET, the
var todos = []; app.post('/todos', function(req, res) { todos.push(req.body.todo); res.status(200).json({'todo': req.body.todo}); }); app.get('/todos', function(req, res) { res.status(200).json({'todos': todos}); });
Note that the app uses an awesome in-memory database!
Node.js Express Minimalist Todo Application - DEMO time
Run the server in
example_code/express/todo_server
Open the browser at http://localhost:8080/ Save a few todos, hit reload Always take a look at the server log and the browsers network inspector
Resources Node.js the Right Way: Practical, Server-Side JavaScript That Scales