0% found this document useful (0 votes)
9 views

Node ExpressJS

NodeJS is a JavaScript runtime built on Chrome's V8 engine that allows JavaScript to be run on the server side. It includes various APIs for building web servers and networking applications. ExpressJS is a web framework built on NodeJS that makes it easier to build servers by abstracting away a lot of the lower level code.

Uploaded by

Vũ Quang Duy
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
9 views

Node ExpressJS

NodeJS is a JavaScript runtime built on Chrome's V8 engine that allows JavaScript to be run on the server side. It includes various APIs for building web servers and networking applications. ExpressJS is a web framework built on NodeJS that makes it easier to build servers by abstracting away a lot of the lower level code.

Uploaded by

Vũ Quang Duy
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 101

Backend Programming

With NodeJS and


ExpressJS
NodeJS
NodeJS

NodeJS:
- A JavaScript runtime written in C++.
- Can interpret and execute JavaScript.
- Includes support for the NodeJS API.

NodeJS API:
- A set of JavaScript libraries that are useful for creating
server programs.

V8 (from Chrome):
- The JavaScript interpreter ("engine") that NodeJS uses
to interpret, compile, and execute JavaScript code
NodeJS

NodeJS:
- A JavaScript runtime written in C++.
Q: What does
- Can interpret and execute JavaScript. this mean?
- Includes support for the NodeJS API.

NodeJS API:
- A set of JavaScript libraries that are useful for creating
server programs.

V8 (from Chrome):
- The JavaScript interpreter ("engine") that NodeJS uses
to interpret, compile, and execute JavaScript code
First: Chrome

Chrome:
- A browser written in C++.
- Can interpret and execute JavaScript code.
- Includes support for the DOM APIs.

DOM APIs:
- JavaScript libraries to interact with a web page

V8:
- The JavaScript interpreter ("engine") that Chrome uses
to interpret, compile, and execute JavaScript code
Chrome, V8, DOM

Parser
JavaScript DOM API
Execution
Engine
runtime Implementation
(Call stack,
Garbage memory, etc.)
Collector
Parser
JavaScript DOM API
Execution runtime Implementation
Engine
(Call stack,
Garbage memory, etc.)
Collector

const name = 'V8';


"Please execute
console.log()"

Parser
JavaScript DOM API
Execution runtime Implementation
Engine
(Call stack,
Garbage memory, etc.)
Collector

console.log('V8');
NodeJS, V8, NodeJS APIs

Parser
JavaScript NodeJS API
Execution
Engine
runtime Implementation
(Call stack,
Garbage memory, etc.)
Collector
Parser
JavaScript
NodeJS API
Execution runtime
Engine
(Call stack,
Implementation
Garbage memory, etc.)
Collector

const x = 15;
x++;
"Please execute
http
.createServer()"

Parser
JavaScript NodeJS API
Execution runtime Implementation
Engine
(Call stack,
Garbage memory, etc.)
Collector

http.createServer();
Parser
JavaScript
NodeJS API
Execution runtime
Engine
(Call stack,
Implementation
Garbage memory, etc.)
Collector

What if you tried to call


document.querySelector('div')
; in the NodeJS runtime?
Parser
JavaScript
NodeJS API
Execution runtime
Engine
(Call stack,
Implementation
Garbage memory, etc.)
Collector

document.querySelector('div');
ReferenceError: document is not defined
Parser
JavaScript
NodeJS API
Execution runtime
Engine
(Call stack,
Implementation
Garbage memory, etc.)
Collector

What if you tried to call console.log('nodejs');


in the NodeJS runtime?
"Please execute
console.log()"

Parser
JavaScript NodeJS API
Execution runtime Implementation
Engine
(Call stack,
Garbage memory, etc.)
Collector

console.log('nodejs');

(NodeJS API implemented their own console.log)


NodeJS

NodeJS:
- A JavaScript runtime written in C++.
- Can interpret and execute JavaScript.
- Includes support for the NodeJS API.

NodeJS API:
- A set of JavaScript libraries that are useful for creating
server programs.

V8 (from Chrome):
- The JavaScript interpreter ("engine") that NodeJS uses
to interpret, compile, and execute JavaScript code
node command

Running node without a filename runs a REPL loop


- Similar to the JavaScript console in Chrome, or when
you run "python"

$ node
> let x = 5;
undefined
> x++
5
> x
6
NodeJS

NodeJS can be used for writing scripts in JavaScript,


completely unrelated to servers.

simple-script.js
function printPoem() {
console.log('Roses are red,');
console.log('Violets are blue,');
console.log('Sugar is sweet,');
console.log('And so are you.');
console.log();
}

printPoem();
printPoem();
node command

The node command can be used to execute a JS file:


$ node fileName

$ node simple-script.js
Roses are red,
Violets are blue,
Sugar is sweet,
And so are you.

Roses are red,


Violets are blue,
Sugar is sweet,
And so are you.
npm

An acronym for Node Package Manager, refers to the


Command line utility to install Node.js packages

• Install package locally:


$ npm install <module_name>

• Use --save at the end of the install command to add


dependency entry into package.json of your application

• The package.json file is a JSON file that is used to manage


dependencies in Node.js projects.
npm

• The packages.json file can be created by running the npm


init command.
$ npm init

• If all the project dependencies are placed in the


package.json file, all of them will be installed at once by
simply running npm install
$ npm install

• Can update or uninstall a package (see more on NPM


website)
Node for servers

Here is a very basic server written for NodeJS:

(WARNING: We will not actually be writing servers like this!!!


We will be using ExpressJS to help, but we haven't gotten there yet.
require()

The NodeJS require() statement loads a module, similar


to import in Java or include in C++.
- We can require() modules included with NodeJS, or
modules we've written ourselves.
- In this example, 'http' is referring to the HTTP
NodeJS module
require()

The http variable returned by require('http') can be


used to make calls to the HTTP API:
- http.createServer() creates a Server object
Emitter.on

The on() function is the NodeJS equivalent of


addEventListener.
Emitter.on

The request event is emitted each time there is a new


HTTP request for the NodeJS program to process.

Server
Emitter.on

The req parameter gives information about the incoming


request, and the res parameter is the response parameter
that we write to via method calls.
- statusCode: Sets the HTTP status code.
- setHeader(): Sets the HTTP headers.
- end(): Writes the message to the response body then
signals to the server that the message is complete.
listen() and listening

The listen() function will start accepting connections


on the given port number.
- The listening event will be emitted when the server
has been bound to a port.

Q: What's a port? What is binding?


Development server

For our development server, we can choose whatever port


number we want. In this example, we've chosen 3000.
Running the server

When we run node server.js in the terminal, we see


the following:

The process does not end after we run the command, as it is


now waiting for HTTP requests on port 3000.
Q: How do we send an HTTP request on port 3000?
Localhost

We can send an HTTP GET request running on one of the


ports on the local computer using the URL:

http://localhost:portNumber, e.g.
http://localhost:3000

Localhost is a hostname that means "this computer."


Server response

Here is the result of the request to our HTTP server:


Node for servers

This server
returns the same
response no
matter what the
request is.
Node for servers

The NodeJS server APIs


are actually pretty
low-level:
- You build the
request manually
- You write the
response manually
- There's a lot of
tedious processing
code
ExpressJS

We're going to use a library called ExpressJS on top of


NodeJS:
Express routing
ExpressJS

However, Express is not part of the NodeJS APIs.


If we try to use it like this, we'll get an error:

We need to install Express via npm.


Express example

$ npm install express


$ node server.js
Example app listening on port 3000!
Express routes

You can specify routes in Express:


Express routes

app.method(path, handler)
- Specifies how the server should handle HTTP method
requests made to URL/path
- This example is saying:
- When there's a GET request to
http://localhost:3000/hello, respond with the text
"GET hello!"
Handler parameters

Express has its own Request and Response objects:


- req is a Request object
- res is a Response object
- res.send() sends an HTTP response with the given
content
- Sends content type "text/html" by default
Querying our server
HTTP requests
Querying our server

fetch()

curl
curl

curl

curl --request

$ curl --request POST http://localhost:3000/hello


Querying with fetch()
fetch() to localhost

But if we try fetching to localhost from different origin:


Recall: CORS

fetch()

fetch()
a different origin:
Enable CORS
Enable CORS
Enable All CORS Requests
const express = require('express’)
const cors = require('cors’)
const app = express()
app.use(cors())

app.get('/products/:id', function (req, res, next) {


res.json({msg: 'This is CORS-enabled for all origins!’})
})

Configuring CORS
const express = require('express’)
const cors = require('cors’)
const app = express()
const corsOptions = {origin: 'http://example.com'}

app.use(cors(corsOptions))

app.get('/products/:id', function (req, res, next) {


res.json({msg: 'This is CORS-enabled for some origins!’})
})
Different fetch()methods
fetch()with POST

app.post() /hello

fetch()
Changing the fetch()method

fetch()

fetch()
method:
fetch()with POST
Sending data to the server
Route parameters

fetch()

https://api.spotify.com/v1/albums/7aDBFWp72P
z4NZEtVBANi9

7aDBFWp72Pz4NZEtVBANi9
Route parameters

req.params
Route parameters
Route parameters
Query parameters

https://api.spotify.com/v1/search?type=album
&q=beyonce

type album
q beyonce
Query parameters

req.query:
Query params with POST
Query params with POST
POST message body

fetch()
POST message body
body-parser

$ npm install body-parser


body-parser

jsonParser
POST message body
POST message body

req.body
POST message body

req.body

jsonParser
POST message body

fetch()
Recap
GET vs POST



Route params vs Query params




Example: Spotify API

https://api.spotify.com/v1/albums/7aDBFWp72Pz4NZEtVBA
Ni9
-

https://api.spotify.com/v1/search?type=album&q=the%20we
e knd&limit=10
-
package.json
Installing dependencies

$ npm install express


$ npm install body-parser

node_modules
Uploading server code

node_modules
node_modules
Managing dependencies

node_modules

npm

npm package.json
package.json

package.json

package.json
$ npm init

package.json
Auto-generated package.json
Saving deps to package.json

$ npm install --save express


$ npm install --save body-parser
Saving deps to package.json

$ rm -rf node_modules

$ npm install
npm scripts

$ npm

$ npm start
Improve the simple-blog
Change Posts Structure

Backend:
const BlogPosts = [
{
slug: "first-blog-post",
title: "First Blog Post",
description: "Lorem ipsum dolor sit amet, consectetur
adip.",
},
{
slug: "second-blog-post",
title: "Second Blog Post",
description: "Hello React Router v6",
},
];

module.exports = { BlogPosts };
Add New Post

Backend (index.js):
const express = require("express");
const app = express();
const cors = require("cors");
const BlogPosts = require("./BlogPosts");
const bodyParser = require("body-parser");
const jsonParser = bodyParser.json();
app.use(cors());

app.post("/api/post", jsonParser, (req, res) => {


const post = {
slug: req.body.slug,
title: req.body.title,
description: req.body.description,
};
BlogPosts.BlogPosts.push(post);
res.status(200).send({ message: "Posted successful" });
});
Add New Post

Frontend (NewPost.js):
function NewPost() {
const [newPost, setNewPost] = useState("");
const {register,handleSubmit,formState: { errors },} = useForm();
const onSubmit = async (data) => {
const post = JSON.stringify(data);
try {
const response = await fetch("https://qshsfj-8080.csb.app/api/post", {
method: "post", headers: {
'Accept': 'application /json’,
'Content-Type':'application/json’
},
body: post,
});
if (response.ok) setNewPost("Post created successfully!");
} catch (error) {
console.error("Error creating data:", error);
setNewPost("Post created failed!");
}
};
Add New Post

Frontend (NewPost.js):
return (
<form onSubmit={handleSubmit(onSubmit)}>
<div style={{ padding: 10 }}>{" "}<br />
<span>Slug:</span><br />
<input type="text" {...register("slug", { required: true })} /><br />
{errors.slug && <div style={{ color: "red" }}>Slug is required</div>}
<span>Title:</span><br />
<input type="text" {...register("title", { required: true })} /><br />
{errors.title && <div style={{ color: "red" }}>Title is required</div>}
<span>Description:</span><br />
<input type="text" {...register("description", { required: true })} />
<br />
{errors.description && <div style={{color:"red"}}>Description is
required</div>}
<br/><button type="submit">Add New</button>
<p className="text-success">{newPost}</p>
</div>
</form>
);
}
Login

Backend (index.js):
app.post("/api/login", jsonParser, (req, res) => {
const creds = {
username: req.body.username,
password: req.body.password,
};
if (creds.username === "admin" && creds.password === "123")
{
res.status(200)
.send({ message: "Login successful});
} else {
res.status(400).send({ message: "Login failed});
}
});
Login

Frontend (Login.js):
function Login({ onLogin }) {
const [creds, setCreds] = useState({});
const [error, setError] = useState("");
const navigate = useNavigate();
const handleLogin = async () => {
try {
const response = await fetch("https://qshsfj-8080.csb.app/api/login", {
method: "post",headers: {
'Accept': 'application /json’,
'Content-Type':'application/json’
},
body: JSON.stringify(creds),
});
if (response.ok){
onLogin && onLogin({username: creds.username});
navigate('/stats’);
}else setError("Invalid username or password!");
} catch (error) {
console.error("Login error:", error);
setError("Login failed!");
}
}
Login

Frontend (Login.js):
return (
<div style={{ padding: 10 }}> <br/>
<span>Username:</span><br/>
<input type="text" onChange={(e) => setCreds({...creds,
username:e.target.value})}/><br/>
<span>Password:</span><br/>
<input type="password" onChange={(e) =>setCreds({...creds,
password: e.target.value})}/><br/><br/>
<button onClick={handleLogin}>Login</button>
<p>{error}</p>
</div>
);
}
Get Post List And Post Detail

Backend (index.js):
app.get("/api/posts", function (req, res) {
res.send(JSON.stringify(BlogPosts.BlogPosts));
});

app.get("/api/post/:slug", function (req, res) {


const slug = req.params.slug;
const post =
BlogPosts.BlogPosts.find((element) => element.slug === slug);
if (post) res.send(JSON.stringify(post));
else res.status(404).send("Not found");
});
Get Post List

Frontend (PostLists.js):
export default function PostLists() {
const [data, setData] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch("https://qshsfj-8080.csb.app/api/posts”);
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);}
const result = await response.json();
setData(result);
setLoading(false);
} catch (error) {
console.error("Error fetching data:", error);
setError("An error occurred while fetching the data.");
setLoading(false);
}
};
fetchData();
}, []);
Get Post List

Frontend (PostLists.js):
return (
<ul>
{data.map((d) => (
<li key={d.slug}>
<Link to={`/posts/${d.slug}`}>
<h3>{d.title}</h3>
</Link>
</li>
))}
</ul>
);
}
Get Post Detail
Frontend (Post.js):
export default function Post() {
const { slug } = useParams();
const [post, setPost] = useState("");
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch("https://qshsfj-
8080.csb.app/api/post/"+slug);
const result = await response.json();
setPost(result);
} catch (error) { console.error("Error fetching data:", error);}
};
fetchData();
}, []);
const { title, description } = post;
return (
<div style={{ padding: 20 }}>
<h3>{title}</h3>
<p>{description}</p>
</div>);
}
Layout and Routes
Frontend (ProtectedRoute.js):
import {Navigate} from "react-router-dom";

function ProtectedRoute({user, children}) {


if(!user) {
return (
<Navigate to="/login" replace/>
);
}

return children;
}

export default ProtectedRoute;


Layout and Routes
Frontend (AppLayout.js):
return (
<>
<nav style={{margin: 10}}>
<Link to="/" style={{padding: 5}}> Home </Link>
<Link to="/posts" style={{padding: 5}}> Posts </Link>
<Link to="/about" style={{padding: 5}}> About </Link>
<span> | </span>
{user && <Link to="/stats" style={{padding: 5}}> Stats
</Link>}
{user && <Link to="/newpost" style={{padding: 5}}> New Post
</Link>}
{!user && <Link to="/login" style={{padding: 5}}> Login
</Link>}
{user && <span onClick={logOut} style={{padding: 5, cursor:
'pointer’}}> Logout </span>}
</nav>
Layout and Routes
Frontend (AppLayout.js):
<Routes>
<Route path="/" element={<Home/>}/>
<Route path="/posts" element={<Posts/>}>
<Route index element={<PostLists/>}/>
<Route path=":slug" element={<Post/>}/>
</Route> <Route path="/about" element={<About/>}/>
<Route path="/login" element={<Login onLogin={setUser}/>}/>
<Route path="/stats" element={<ProtectedRoute
user={user}><Stats/></ProtectedRoute>} />
<Route path="/newpost" element={<ProtectedRoute
user={user}><NewPost/></ProtectedRoute>} />
<Route path="*" element={<NoMatch/>}/>
</Routes>
</>
);
Layout and Routes
Frontend (App.js):
function App() {
return (
<Router>
<AppLayout/>
</Router>
);
}

export default App;


Layout and Routes
Frontend (Stats.js):
• Bỏ check user khi đã dùng ProtectedRoute

import {Navigate} from "react-router-dom";

function Stats() {
return (
<div style={{ padding: 20 }}>
<h2>Stats View</h2>
<p>Lorem ipsum dolor sit amet, consectetur adip.</p>
</div>
);
}

export default Stats;

You might also like