part3a
hello world
command version
pnpm init
add “start” in scripts section
// package.json
"start": "node index.js",
add index.js
console.log("hello world");
node index.js
or
pnpm start
Simple web server
const http = require("http");
const app = http.createServer((request, response) => { response.writeHead(200, { "Content-Type": "text/plain" }); response.end("Hello World");});
const PORT = 3001;app.listen(PORT);console.log(`Server running on port ${PORT}`);
pnpm start
check http://localhost:3001 and http://localhost:3001/foo/bar
// index.js
const http = require("http");
let notes = [ { id: "1", content: "HTML is easy", important: true, }, { id: "2", content: "Browser can execute only JavaScript", important: false, }, { id: "3", content: "GET and POST are the most important methods of HTTP protocol", important: true, },];const app = http.createServer((request, response) => { response.writeHead(200, { "Content-Type": "application/json" }); response.end(JSON.stringify(notes));});
const PORT = 3001;app.listen(PORT);console.log(`Server running on port ${PORT}`);
check http://localhost:3001 and http://localhost:3001/notes
Express
pnpm i express
Web and Express
const express = require("express");const app = express();
let notes = [ { id: "1", content: "HTML is easy", important: true, }, { id: "2", content: "Browser can execute only JavaScript", important: false, }, { id: "3", content: "GET and POST are the most important methods of HTTP protocol", important: true, },];
app.get("/", (request, response) => { response.send("<h1>Hello World!</h1>");});
app.get("/api/notes", (request, response) => { response.json(notes);});
const PORT = 3001;app.listen(PORT, () => { console.log(`Server running on port ${PORT}`);});
pnpm start
check http://localhost:3001/ and http://localhost:3001/api/notes
nodemon
pnpm i -D nodemon
add scripts
// package.json
"dev": "nodemon index.js",
Fetching a single resource
app.get("/api/notes/:id", (request, response) => { const id = request.params.id; const note = notes.find((note) => note.id === id);
if (note) { response.json(note); } else { response.status(404).end(); }});
Deleting resources
app.delete("/api/notes/:id", (request, response) => { const id = request.params.id; notes = notes.filter((note) => note.id !== id);
response.status(204).end();});
VSCode REST client
Add new folder “requests” at root.
Add new file extend name .rest in it.
GET http://localhost:3001/api/notes
###POST http://localhost:3001/api/notes/ HTTP/1.1content-type: application/json
{ "name": "sample", "time": "Wed, 21 Oct 2015 18:27:50 GMT"}
Click on the “Send Request” button while viewing this file, it will imply the request and show the response at right side.
Receiving data
const express = require("express");const app = express();
app.use(express.json());
//...
app.post("/api/notes", (request, response) => { const maxId = notes.length > 0 ? Math.max(...notes.map((n) => Number(n.id))) : 0;
const note = request.body; note.id = String(maxId + 1);
notes = notes.concat(note);
response.json(note);});
Response 400 on empty content
const generateId = () => { const maxId = notes.length > 0 ? Math.max(...notes.map((n) => Number(n.id))) : 0; return String(maxId + 1);};
app.post("/api/notes", (request, response) => { const body = request.body;
if (!body.content) { return response.status(400).json({ error: "content missing", }); }
const note = { content: body.content, important: Boolean(body.important) || false, id: generateId(), };
notes = notes.concat(note);
response.json(note);});
Exercises 3.1 - 3.6
Setup a new repo.
3.1 Phonebook backend step 1
http://localhost:3001/api/persons
[ { id: "1", name: "Arto Hellas", number: "040-123456", }, { id: "2", name: "Ada Lovelace", number: "39-44-5323523", }, { id: "3", name: "Dan Abramov", number: "12-43-234345", }, { id: "4", name: "Mary Poppendieck", number: "39-23-6423122", },];
3.2 Phonebook backend step 2
The page has to show the time that the request was received and how many entries are in the phonebook at the time of processing the request.
3.3 Phonebook backend step 3
Get single person
http://localhost:3001/api/persons/5
3.4 Phonebook backend Step 4
Delete single person
3.5 Phonebook backend step 5
Create person
Generate a new id for the phonebook entry with the Math.random function. Use a big enough range for your random values so that the likelihood of creating duplicate ids is small.
3.6 Phonebook backend step 6
Error handling for creating new entries.
The request is not allowed to succeed, if:
- The name or number is missing
- The name already exists in the phonebook
{ "error": "name must be unique" }
My solutions
My solutions:
(Please complete your own solutions before click here.)
3.1 /api/persons
cd exercisesmakedir part3cd part3mkdir phonebookcd phonebookpnpm initcode .add scripts: "start": "node index.js",add index.js, content: console.log("hello world")pnpm startpnpm i nodemonpnpm i expressadd scripts: "dev": "nodemon index.js",pnpm dev
const express = require("express");const app = express();
app.use(express.json());
let persons = [ { id: "1", name: "Arto Hellas", number: "040-123456", }, { id: "2", name: "Ada Lovelace", number: "39-44-5323523", }, { id: "3", name: "Dan Abramov", number: "12-43-234345", }, { id: "4", name: "Mary Poppendieck", number: "39-23-6423122", },];
app.get("/api/persons", (request, response) => { response.json(persons);});
const PORT = 3001;app.listen(PORT, () => { console.log(`Server running on port ${PORT}`);});
add requests/get_all_persons.rest
// get_all_persons.rest
GET http://localhost:3001/api/persons
3.2 /info
pnpm i axios
const axios = require("axios");const express = require("express");const app = express();
app.use(express.json());
let persons = [ { id: "1", name: "Arto Hellas", number: "040-123456", }, { id: "2", name: "Ada Lovelace", number: "39-44-5323523", }, { id: "3", name: "Dan Abramov", number: "12-43-234345", }, { id: "4", name: "Mary Poppendieck", number: "39-23-6423122", },];
app.get("/api/persons", (request, response) => { response.json(persons);});
app.get("/info", (request, response) => { let respPersons; axios.get("http://localhost:3001/api/persons").then((resp) => { // console.log(resp) respPersons = resp.data; // console.log(respPersons)
response.send(` Phonebook has info for ${respPersons.length} ${ respPersons.length === 1 ? "person" : "people" } <br /> ${new Date().toString()} `); });});
const PORT = 3001;app.listen(PORT, () => { console.log(`Server running on port ${PORT}`);});
GET http://localhost:3001/api/persons
###GET http://localhost:3001/info
3.3 Get single person
3.4 Delete single person
3.5 Post one person
const axios = require("axios");const express = require("express");const app = express();
app.use(express.json());
let persons = [ { id: "1", name: "Arto Hellas", number: "040-123456", }, { id: "2", name: "Ada Lovelace", number: "39-44-5323523", }, { id: "3", name: "Dan Abramov", number: "12-43-234345", }, { id: "4", name: "Mary Poppendieck", number: "39-23-6423122", },];
app.get("/api/persons", (request, response) => { response.json(persons);});
app.get("/info", (request, response) => { let respPersons; axios.get("http://localhost:3001/api/persons").then((resp) => { // console.log(resp) respPersons = resp.data; // console.log(respPersons)
response.send(` Phonebook has info for ${respPersons.length} ${ respPersons.length === 1 ? "person" : "people" } <br /> ${new Date().toString()} `); });});
app.get("/api/persons/:id", (request, response) => { const id = request.params.id; const person = persons.find((person) => person.id === id);
if (person) { response.json(person); } else { response.status(404).end(); }});
app.delete("/api/persons/:id", (request, response) => { const id = request.params.id; persons = persons.filter((person) => person.id !== id);
response.status(204).end();});
const generateId = () => { const maxId = persons.length > 0 ? Math.max(...persons.map((p) => Number(p.id))) : 0; return String(maxId + 1);};
app.post("/api/persons", (request, response) => { const body = request.body;
if (!body.name || !body.number) { return response.status(400).json({ error: "person name or number missing", }); }
const person = { name: body.name, number: body.number, id: generateId(), };
persons = persons.concat(person);
response.json(person);});
const PORT = 3001;app.listen(PORT, () => { console.log(`Server running on port ${PORT}`);});
3.6 error handling
- name and number can’t be missing
- name must be unique
pnpm i lodash
app.post("/api/persons", (request, response) => { const body = request.body;
if (!body.name || !body.number) { return response.status(400).json({ error: "person name or number missing", }); }
const personsNameArray = persons.map((p) => p.name);
if (_.includes(personsNameArray, body.name)) { return response.status(400).json({ error: "name must be unique", }); }
const person = { name: body.name, number: body.number, id: generateId(), };
persons = persons.concat(person);
response.json(person);});
Middleware
Middleware running position(app.use(…)) is important.
const requestLogger = (request, response, next) => { console.log("Method:", request.method); console.log("Path: ", request.path); console.log("Body: ", request.body); console.log("---"); next();};
app.use(requestLogger);
const unknownEndpoint = (request, response) => { response.status(404).send({ error: "unknown endpoint" });};
app.use(unknownEndpoint);
Exercises 3.7 - 3.8
3.7 Phonebook backend step 7
Add the morgan middleware to your application for logging. Configure it to log messages to your console based on the tiny configuration.
3.8* Phonebook backend step 8
Configure morgan so that it also shows the data sent in HTTP POST requests:
POST /api/persons 200 61 - 4.896 ms {"name":"Liisa Marttinen","number":"040-243563"}
This exercise can be completed in a few different ways. One of the possible solutions utilizes these two techniques:
- creating new tokens
- JSON.stringify
My solutions
My solutions:
(Please complete your own solutions before click here.)
3.7 use morgan middleware, tiny configuration
pnpm i morgan
const morgan = require("morgan");
app.use(morgan("tiny"));
3.8* add post request body to the morgan log
morgan.token('postBody', function getPostBody(req) { // console.log(req.method) // console.log(JSON.stringify(req.body) === JSON.stringify({})) // if (JSON.stringify(req.body) !== JSON.stringify({})) { if (req.method.toLowerCase() === "post".toLowerCase()) { return JSON.stringify(req.body) } return null})
app.use(express.json());// app.use(morgan("tiny"))app.use(morgan(':method :url :status :res[content-length] - :response-time ms :postBody'))