The Express + Node.js Handbook – Learn the Express JavaScript Framework for Beginners
Express is a Web Framework built upon Node.js. Node.js is an amazing tool for building networking services and applications. Express builds on top of its features to provide easy to use functionality that satisfies the needs of the Web Server use-case. It's Open Source, free, easy to extend, and very performant. There are also lots and lots of pre-built packages you can just drop in and use to do all kinds of things. You can get a PDF and ePub version of this Express Handbook How to Install Express The first "Hello, World" example Request Parameters How to Send a Response to the Client How to Send a JSON Response How to Manage Cookies How to Work with HTTP Headers How to Handle Redirects Routing in Express Templates in Express Express Middleware How to Serve Static Assets with Express How to Send Files to the Client Sessions in Express How to Validate Input in Express How to Sanitize Input in Express How to Handle Forms in Express How to Handle File Uploads in Forms in Express You can install Express into any project with npm. If you're in an empty folder, first create a new Node.js project with this command: then run this: to install Express into the project. The first example we're going to create is a simple Express Web Server. Copy this code: Save this to an You can open the browser to port 3000 on localhost and you should see the Those 4 lines of code do a lot behind the scenes. First, we import the We instantiate an application by calling the Once we have the application object, we tell it to listen for GET requests on the There is a method for every HTTP verb: Those methods accept a callback function – which is called when a request is started – and we need to handle it. We pass in an arrow function: Express sends us two objects in this callback, which we called Both are standards and you can read more on them here and here. Request is the HTTP request. It gives us all the request information, including the request parameters, the headers, the body of the request, and more. Response is the HTTP response object that we'll send to the client. What we do in this callback is send the 'Hello World!' string to the client, using the This method sets that string as the body, and it closes the connection. The last line of the example actually starts the server, and tells it to listen on port I mentioned how the Request object holds all the HTTP request information. These are the main properties you'll likely use: In the Hello World example, we used the If you pass in a string, it sets the If you pass in an object or an array, it sets the After this, An alternative way to send the response, without any body, is by using the Use the or When you listen for connections on a route in Express, the callback function will be invoked on every network call with a Request object instance and a Response object instance. Example: Here we used the You can send JSON to the client by using It accepts an object or array, and converts it to JSON before sending it: Use the Examples: This method accepts a third parameter, which contains various options: The most useful parameters you can set are: A can be cleared with: You can access all the HTTP headers using the Use the You can change any HTTP header value using There is a shortcut for the Content-Type header, however: Redirects are common in Web Development. You can create a redirect using the This creates a 302 redirect. A 301 redirect is made in this way: You can specify an absolute path ( You can also redirect back to the Referrer HTTP header value (defaulting to Routing is the process of determining what should happen when a URL is called, or also which parts of the application should handle a specific incoming request. In the Hello World example we used this code: This creates a route that maps accessing the root domain URL What if we want to listen for custom requests? Maybe we want to create a service that accepts a string and returns it as uppercase – and we don't want the parameter to be sent as a query string, but as part of the URL. In a case like that, we use named parameters: If we send a request to You can use multiple named parameters in the same URL, and they will all be stored in You can use regular expressions to match multiple paths with one statement: will match Express is capable of handling server-side template engines. Template engines allow us to add data to a view, and generate HTML dynamically. Express uses Jade as the default. Jade is the old version of Pug, specifically Pug 1.0. Note that the name was changed from Jade to Pug due to a trademark issue in 2016, when the project released version 2. You can still use Jade, aka Pug 1.0, but going forward, it's best to use Pug 2.0 Although the last version of Jade is getting old, it's still the default in Express for backward compatibility reasons. In any new project, you should use Pug or another engine of your choice. The official site of Pug is https://pugjs.org/. You can use many different template engines, including Pug, Handlebars, Mustache, EJS and more. To use Pug we must first install it: and when initializing the Express app, we need to set it: We can now start writing our templates in Create an about view: and the template in This template will create a You can interpolate a variable using this code: Look at the Pug guide for more information on how to use Pug. This online converter from HTML to Pug will be a great help: https://html-to-pug.com/. A middleware is a function that hooks into the routing process, performing an arbitrary operation at some point in the chain (depending on what we want it to do). It's commonly used to edit the request or response objects, or terminate the request before it reaches the route handler code. Middleware is added to the execution stack like so: This is similar to defining a route, but in addition to the Request and Response objects instances, we also have a reference to the nextmiddleware function, which we assign to the variable We always call You typically use pre-made middleware, in the form of One example is We can also set a middleware function to run for specific routes only (not for all), by using it as the second parameter of the route definition: If you need to store data that's generated in a middleware to pass it down to subsequent middleware functions, or to the request handler, you can use the It's common to have images, CSS, and more in a If you have an Express provides a handy method to transfer a file as an attachment: Once a user hits a route that sends a file using this method, browsers will prompt the user to download. The In the context of an app: You can set the file to be sent with a custom filename: This method provides a callback function which you can use to execute code once the file has been sent: By default Express requests are sequential and no request can be linked to another. There is no way to know if this request comes from a client that already performed a request previously. Users cannot be identified unless using some kind of mechanism that makes it possible. That's what sessions are. When implemented, every user of your API or website will be assigned a unique session, and this allows you to store the user's state. We'll use the You can install it using this command: and once you're done, you can instantiate it in your application with this one: This is a middleware, so you installit in Express using the following: After this is done, all the requests to the app routes are now using sessions. The session is attached to the request, so you can access it using This object can be used to get data out of the session, and also to set data: This data is serialized as JSON when stored, so you are safe to use nested objects. You can use sessions to communicate data to middleware that's executed later, or to retrieve it later on, on subsequent requests. Where is the session data stored? It depends on how you set up the It can store session data in: memory, not meant for production a databaselike MySQL or Mongo a memory cachelike Redis or Memcached There is a big list of 3rd packages that implement a wide variety of different compatible caching stores in https://github.com/expressjs/session. All solutions store the session id in a , and keep the data server-side. The client will receive the session id in a , and will send it along with every HTTP request. We'll reference that server-side to associate the session id with the data stored locally. Memory is the default, and it requires no special setup on your part. It's the simplest thing but it's meant only for development purposes. The best choice is a memory cache like Redis, for which you need to setup its own infrastructure. Another popular package to manage sessions in Express is I do not recommend doing that because storing data in s means that it's stored client-side, and sent back and forth in every single request made by the user. It's also limited in size, as it can only store 4 kilobytes of data. Cookies also need to be secured, but by default they are not, since secure Cookies are possible on HTTPS sites and you need to configure them if you have proxies. Let's see how to validate any data coming in as input in your Express endpoints. Say you have a POST endpoint that accepts the name, email, and age parameters: How do you perform server-side validation on those results to make sure that: name is a string of at least 3 characters? email is a real email? age is a number, between 0 and 110? The best way to handle validation on any kind of input coming from outside in Express is by using the You require the We pass an array of Notice I used: There are many more of these methods, all coming from validator.js, including: You can validate the input against a regular expression using Dates can be checked using: For exact details on how to use those validators, refer to the docs here. All those checks can be combined by piping them: If there is any error, the server automatically sends a response to communicate the error. For example if the email is not valid, this is what will be returned: This default error can be overridden for each check you perform, using What if you want to write your own special, custom validator? You can use the In the callback function you can reject the validation either by throwing an exception, or by returning a rejected promise: The custom validator: can be rewritten like this: You've seen how to validate input that comes from the outside world to your Express app. There's one thing you quickly learn when you run a public-facing server: never trust the input. Even if you sanitize and make sure that people can't enter weird things using client-side code, you'll still be subject to people using tools (even just the browser devtools) to POST directly to your endpoints. Or bots trying every possible combination of exploit known to humans. What you need to do is sanitize your input. The Say you have a POST endpoint that accepts the name, email, and age parameters: You might validate it using: You can add sanitization by piping the sanitization methods after the validation ones: Here I used the methods: Other sanitization methods: Force conversion to a format: Like with custom validators, you can create a custom sanitizer. In the callback function you just return the sanitized value: This is an example of an HTML form: When the user presses the submit button, the browser will automatically make a Forms can also send data using the The form data will be sent in the POST request body. To extract it, you will need to use the Now, you need to create a Don't forget to validate the data before using it with This is an example of an HTML form that allows a user to upload a file: Don't forget to add When the user press the submit button, the browser will automatically make a On the server-side, handling multipart data can be tricky and error prone, so we are going to use a utility library called formidable. Here's the GitHub repo – it has over 4000 stars and is well-maintained. You can install it using: Then include it in your Node.js file: Now, in the After doing so, we need to be able to parse the form. We can do so synchronously by providing a callback, which means all files are processed. Once formidable is done, it makes them available: Or, you can use events instead of a callback. For example, you can be notified when each file is parsed, or other events such as completion of file processing, receiving a non-file field, or if an error occurred: Whichever way you choose, you'll get one or more Formidable.File objects, which give you information about the file uploaded. These are some of the methods you can call: The path defaults to the temporary folder and can be modified if you listen for the That's it for this handbook. And don't forget that you can get a PDF and ePub version of this Express Handbook if you'd like.What is Express?
How to Install Express
npm init -ynpm install expressThe First "Hello, World" Example
const express = require('express')const app = express()app.get('/', (req, res) => res.send('Hello World!'))app.listen(3000, () => console.log('Server ready'))index.jsfile in your project root folder, and start the server using this command:node index.jsHello World!message.expresspackage to the expressvalue.express()method./path, using the get()method.get(), post(), put(), delete(), and patch():app.get('/', (req, res) => { /* */ })app.post('/', (req, res) => { /* */ })app.put('/', (req, res) => { /* */ })app.delete('/', (req, res) => { /* */ })app.patch('/', (req, res) => { /* */ })(req, res) => res.send('Hello World!')reqand res. They represent the Request and the Response objects.Response.send()method.3000. We pass in a callback that is called when the server is ready to accept new requests.Request Parameters
Property Description .app holds a reference to the Express app object .baseUrl the base path on which the app responds .body contains the data submitted in the request body (must be parsed and populated manually before you can access it) .s contains the s sent by the request (needs the -parsermiddleware).hostname the hostname as defined in the Host HTTP header value .ip the client IP .method the HTTP method used .params the route named parameters .path the URL path .protocol the request protocol .query an object containing all the query strings used in the request .secure true if the request is secure (uses HTTPS) .signedCookies contains the signed s sent by the request (needs the -parsermiddleware).xhr true if the request is an XMLHttpRequest How to Send a Response to the Client
send()method of the Response object to send a simple string as a response, and to close the connection:(req, res) => res.send('Hello World!')Content-Typeheader to text/html.application/jsonContent-Typeheader, and parses that parameter into JSON.send()closes the connection.send()automatically sets the Content-LengthHTTP response header, unlike end()which requires you to do that.How to use end() to send an empty response
Response.end()method:res.end()How to set the HTTP response status
status()method on the response object:res.status(404).end()res.status(404).send('File not found')sendStatus()is a shortcut:res.sendStatus(200)// === res.status(200).send('OK')res.sendStatus(403)// === res.status(403).send('Forbidden')res.sendStatus(404)// === res.status(404).send('Not Found')res.sendStatus(500)// === res.status(500).send('Internal Server Error')How to Send a JSON Response
app.get('/', (req, res) => res.send('Hello World!'))Response.send()method, which accepts any string.Response.json(), a useful method.res.json({ username: 'Flavio' })How to Manage Cookies
Response.()method to manipulate your s.res.('username', 'Flavio')res.('username', 'Flavio', { domain: '.flaviocopes.com', path: '/administrator', secure: true })res.('username', 'Flavio', { expires: new Date(Date.now() + 900000), httpOnly: true })Value Description domainThe domain name expiresSet the expiration date. If missing, or 0, the is a session httpOnlySet the to be accessible only by the web server. See HttpOnly maxAgeSet the expiry time relative to the current time, expressed in milliseconds pathThe path. Defaults to '/' secureMarks the HTTPS only signedSet the to be signed sameSiteValue of SameSiteres.clearCookie('username')How to Work with HTTP Headers
How to access HTTP headers values from a request
Request.headersproperty:app.get('/', (req, res) => { console.log(req.headers)})Request.header()method to access one individual request header's value:app.get('/', (req, res) => { req.header('User-Agent')})How to change any HTTP header value for a response
Response.set():res.set('Content-Type', 'text/html')res.type('.html')// => 'text/html'res.type('html')// => 'text/html'res.type('json')// => 'application/json'res.type('application/json')// => 'application/json'res.type('png')// => image/png:How to Handle Redirects
Response.redirect()method:res.redirect('/go-there')res.redirect(301, '/go-there')/go-there), an absolute URL (https://anothersite.com), a relative path (go-there) or use the ..to go back one level:res.redirect('../go-there')res.redirect('..')/if not set) usingres.redirect('back')Routing in Express
app.get('/', (req, res) => { /* */ })/using the HTTP GET method to the response we want to provide.Named parameters
app.get('/uppercase/:theValue', (req, res) => res.send(req.params.theValue.toUpperCase()))/uppercase/test, we'll get TESTin the body of the response.req.params.How to use a regular expression to match a path
app.get(/post/, (req, res) => { /* */ })/post, /post/first, /thepost, /posting/something, and so on.Templates in Express
npm install pugconst express = require('express')const app = express()app.set('view engine', 'pug').pugfiles.app.get('/about', (req, res) => { res.render('about')})views/about.pug:p Hello from Flavioptag with the content Hello from Flavio.app.get('/about', (req, res) => { res.render('about', { name: 'Flavio' })})p Hello from #{ name}Express Middleware
app.use((req, res, next) => { /* */ })next.next()at the end of our middleware function, in order to pass the execution to the next handler. That is unless we want to prematurely end the response and send it back to the client.npmpackages. You can find a big list of the available ones here.-parser, which is used to parse s into the req.sobject. You can install it using npm install -parserand you use it like this:const express = require('express')const app = express()const Parser = require('-parser')app.get('/', (req, res) => res.send('Hello World!'))app.use(Parser())app.listen(3000, () => console.log('Server ready'))const myMiddleware = (req, res, next) => { /* ... */ next()}app.get('/', myMiddleware, (req, res) => res.send('Hello World!'))Request.localsobject. It will attach that data to the current request:req.locals.name = 'Flavio'How to Serve Static Assets with Express
publicsubfolder, and expose them to the root level:const express = require('express')const app = express()app.use(express.static('public'))/* ... */app.listen(3000, () => console.log('Server ready'))index.htmlfile in public/, that will be served if you now hit the root domain URL (http://localhost:3000)How to Send Files to the Client
Response.download().Response.download()method allows you to send a file attached to the request, and the browser, instead of showing it in the page, will save it to disk.app.get('/', (req, res) => res.download('./file.pdf'))const express = require('express')const app = express()app.get('/', (req, res) => res.download('./file.pdf'))app.listen(3000, () => console.log('Server ready'))res.download('./file.pdf', 'user-facing-filename.pdf')res.download('./file.pdf', 'user-facing-filename.pdf', (err) => { if (err) { //handle error return } else { //do something }})Sessions in Express
express-sessionmodule, which is maintained by the Express team.npm install express-sessionconst session = require('express-session')const express = require('express')const session = require('express-session')const app = express()app.use(session({ 'secret': '343ji43j4n3jn4jk3n'}))secretis the only required parameter, but there are many more you can use. It should be a randomly unique string for your application.req.sessionhere:app.get('/', (req, res, next) => { // req.session}req.session.name = 'Flavio'console.log(req.session.name) // 'Flavio'express-sessionmodule.-session, which has a big difference: it stores data client-side in the .How to Validate Input in Express
const express = require('express')const app = express()app.use(express.json())app.post('/form', (req, res) => { const name = req.body.name const email = req.body.email const age = req.body.age})express-validatorpackage:npm install express-validatorcheckand validationResultobjects from the package:const { check, validationResult } = require('express-validator');check()calls as the second argument of the post()call. Every check()call accepts the parameter name as argument. Then we call validationResult()to verify there were no validation errors. If there are any, we tell them to the client:app.post('/form', [ check('name').isLength({ min: 3 }), check('email').isEmail(), check('age').isNumeric()], (req, res) => { const errors = validationResult(req) if (!errors.isEmpty()) { return res.status(422).json({ errors: errors.array() }) } const name = req.body.name const email = req.body.email const age = req.body.age})isLength()isEmail()isNumeric()contains(), checks if value contains the specified valueequals(), checks if value equals the specified valueisAlpha()isAlphanumeric()isAscii()isBase64()isBoolean()isCurrency()isDecimal()isEmpty()isFQDN(), checks if it's a fully qualified domain nameisFloat()isHash()isHexColor()isIP()isIn(), checks if the value is in an array of allowed valuesisInt()isJSON()isLatLong()isLength()isLowercase()isMobilePhone()isNumeric()isPostalCode()isURL()isUppercase()isWhitelisted(), checks the input against a whitelist of allowed charactersmatches().isAfter(), checks if the entered date is after the one you passisBefore(), checks if the entered date is before the one you passisISO8601()isRFC3339()check('name') .isAlpha() .isLength({ min: 10 }){ "errors": [{ "location": "body", "msg": "Invalid value", "param": "email" }]}withMessage():check('name') .isAlpha() .withMessage('Must be only alphabetical chars') .isLength({ min: 10 }) .withMessage('Must be at least 10 chars long')customvalidator.app.post('/form', [ check('name').isLength({ min: 3 }), check('email').custom(email => { if (alreadyHaveEmail(email)) { throw new Error('Email already registered') } }), check('age').isNumeric()], (req, res) => { const name = req.body.name const email = req.body.email const age = req.body.age})check('email').custom(email => { if (alreadyHaveEmail(email)) { throw new Error('Email already registered') }})check('email').custom(email => { if (alreadyHaveEmail(email)) { return Promise.reject('Email already registered') }})How to Sanitizing Input in Express
express-validatorpackage you already use to validate input can also conveniently be used to perform sanitization.const express = require('express')const app = express()app.use(express.json())app.post('/form', (req, res) => { const name = req.body.name const email = req.body.email const age = req.body.age})const express = require('express')const app = express()app.use(express.json())app.post('/form', [ check('name').isLength({ min: 3 }), check('email').isEmail(), check('age').isNumeric()], (req, res) => { const name = req.body.name const email = req.body.email const age = req.body.age})app.post('/form', [ check('name').isLength({ min: 3 }).trim().escape(), check('email').isEmail().normalizeEmail(), check('age').isNumeric().trim().escape()], (req, res) => { //...})trim()trims characters (whitespace by default) at the beginning and at the end of a stringescape()replaces <, >, &, ', "and /with their corresponding HTML entitiesnormalizeEmail()canonicalizes an email address. Accepts several options to lowercase email addresses or subaddresses (for example [email protected])blacklist()removes characters that appear in the blacklistwhitelist()removes characters that do not appear in the whitelistunescape()replaces HTML encoded entities with <, >, &, ', "and /ltrim()like trim(), but only trims characters at the start of the stringrtrim()like trim(), but only trims characters at the end of the stringstripLow()removes ASCII control characters, which are normally invisibletoBoolean()converts the input string to a boolean. Everything except for '0', 'false' and '' returns true. In strict mode only '1' and 'true' return true.toDate()converts the input string to a date, or null if the input is not a datetoFloat()converts the input string to a float, or NaN if the input is not a floattoInt()converts the input string to an integer, or NaN if the input is not an integerconst sanitizeValue = value => { //sanitize...}app.post('/form', [ check('value').customSanitizer(value => { return sanitizeValue(value) }),], (req, res) => { const value = req.body.value})How to Handle Forms in Express
<form method="POST" action="/submit-form"> <input type="text" name="username" /> <input type="submit" /></form>POSTrequest to the /submit-formURL on the same origin of the page. The browser sends the data contained, encoded as application/x-www-form-urlencoded. In this particular example, the form data contains the usernameinput field value.GETmethod, but the vast majority of the forms you'll build will use POST.express.urlencoded()middleware:const express = require('express')const app = express()app.use(express.urlencoded({ extended: true}))POSTendpoint on the /submit-formroute, and any data will be available on Request.body:app.post('/submit-form', (req, res) => { const username = req.body.username //... res.end()})express-validator.How to Handle File Uploads in Forms in Express
<form method="POST" action="/submit-form" enctype="multipart/form-data"> <input type="file" name="document" /> <input type="submit" /></form>enctype="multipart/form-data"to the form, or files won't be uploaded.POSTrequest to the /submit-formURL on the same origin of the page. The browser sends the data contained, not encoded as as a normal form application/x-www-form-urlencoded, but as multipart/form-data.npm install formidableconst express = require('express')const app = express()const formidable = require('formidable')POSTendpoint on the /submit-formroute, we instantiate a new Formidable form using formidable.IncomingForm():app.post('/submit-form', (req, res) => { new formidable.IncomingForm()})app.post('/submit-form', (req, res) => { new formidable.IncomingForm().parse(req, (err, fields, files) => { if (err) { console.error('Error', err) throw err } console.log('Fields', fields) console.log('Files', files) for (const file of Object.entries(files)) { console.log(file) } })})app.post('/submit-form', (req, res) => { new formidable.IncomingForm().parse(req) .on('field', (name, field) => { console.log('Field', name, field) }) .on('file', (name, file) => { console.log('Uploaded file', name, file) }) .on('aborted', () => { console.error('Request aborted by the user') }) .on('error', (err) => { console.error('Error', err) throw err }) .on('end', () => { res.end() })})file.size, the file size in bytesfile.path, the path the file is written tofile.name, the name of the filefile.type, the MIME type of the filefileBeginevent:app.post('/submit-form', (req, res) => { new formidable.IncomingForm().parse(req) .on('fileBegin', (name, file) => { file.path = __dirname + '/uploads/' + file.name }) .on('file', (name, file) => { console.log('Uploaded file', name, file) }) //...})Thank you for reading!
相关推荐
-
CSS Color Functions
-
Learn React – A Handbook for Beginners
-
How to Learn to Code and Get a Developer Job [Full Book]
-
Python Code Example Handbook – Sample Script Coding Tutorial for Beginners
-
Open Source Tools Every STEM Student Should Know About
-
The Express + Node.js Handbook – Learn the Express JavaScript Framework for Beginners
- 最近发表
-
- Refund Management Workflow
- Front End JavaScript Development Handbook – React, Angular, and Vue Compared
- Learn Clustering in Python – A Machine Learning Engineering Handbook
- How to Get Started with NodeJS – a Handbook for Beginners
- How to Choose the Best Stock Market API for FinTech Projects and AI Agents
- The Python Handbook – Learn Python for Beginners
- How to Build CRUD Operations with .NET Core – A Todo API Handbook
- Learn Clustering in Python – A Machine Learning Engineering Handbook
- How to Understand the Safe Integer Limit in JavaScript
- The Java Handbook – Learn Java Programming for Beginners
- 随机阅读
-
- Data Integration Platform
- How to Learn to Code and Get a Developer Job [Full Book]
- The Software Architecture Handbook
- How to Get Started with NodeJS – a Handbook for Beginners
- The Java Handbook – Learn Java Programming for Beginners
- The Python Handbook – Learn Python for Beginners
- Front End JavaScript Development Handbook – React, Angular, and Vue Compared
- The Java Handbook – Learn Java Programming for Beginners
- The Golang Handbook – A Beginner's Guide to Learning Go
- The Python Handbook – Learn Python for Beginners
- How to Get Started with NodeJS – a Handbook for Beginners
- How to Become a Full
- software architecture
- How to Become a Full
- How to Learn Python for JavaScript Developers [Full Handbook]
- Learn Linux for Beginners: From Basics to Advanced Techniques [Full Book]
- AI Paper Review: Language Models are Unsupervised Multitask Learners (GPT
- The Java Handbook – Learn Java Programming for Beginners
- The Python Handbook – Learn Python for Beginners
- Learn React – A Handbook for Beginners
- 搜索
-