
Express Module: Building API Endpoints with Node.js
"Learn how Express, a module built on top of Node.js, helps in building API endpoints and running backend JavaScript code. Explore concepts like basic startup, routing, ES6 vs. JS, and organizing handlers within routers to enhance your backend development skills."
Download Presentation

Please find below an Image/Link to download the presentation.
The content on the website is provided AS IS for your information and personal use only. It may not be sold, licensed, or shared on other websites without obtaining consent from the author. If you encounter any issues during the download, it is possible that the publisher has removed the file from their server.
You are allowed to download the files provided on this website for personal or commercial use, subject to the condition that they are used lawfully. All files are the property of their respective owners.
The content on the website is provided AS IS for your information and personal use only. It may not be sold, licensed, or shared on other websites without obtaining consent from the author.
E N D
Presentation Transcript
What is it? Express is a module built on top of Node (which runs server side js) Its purpose is to help build API endpoints aka Routes and run Javascript as your backend code Express and ExpressRouter are typically used together to serve endpoints (APIs or pages) Referencing how we used python and Flask Express provides much of the Flask capability and adds some functions for managing multiple API routes
Basic startup in Express .. import express from 'express'; import bodyParser from 'body-parser'; import cors from 'cors'; import { initDB} from './src/initdb.js ; import manf_router from './routers/manf_router.js' import manf_router_v2 from './routers/manf_router_v2.js'; const app = express(); app.use(cors()); //Enable cors for client-server APIs app.use(express.json());//Enables simple data extraction for RESTful API data app.use('/manf/api', manf_router) app.use('/manf/api/v2', manf_router_v2) //Will return 'pong' on the endpoint /ping //curl http://localhost:5005/ping app.get('/ping', function (req, res) { return res.send('pong'); }); //Starts the server, listening on the specified PORT and prints a message when it starts app.listen(process.env.PORT, ()=> { console.log(">>> Node Express Server listening on port: " + process.env.PORT); } ); //Initialize the Database -- server will run and wait for requests initDB();
Concepts Express starts and listens on a defined port We create the express app; add cors; add some json utilities and then add routes You can define endpoints for each verb app.get( ); app.post( ) etc. These can go right in the server file OR You can have multiple files and add them to express via app.use The 2ndapproach is much better organized!
Class JS vs ES6 To include JS modules, you can use the classic js mechanisms require , or use the newer ES6 (ECMAScript v6) syntax Classic: const fs = require('fs'); const readline = require('readline ); ES6: (package.jsonadd "type": "module ) import * as fs from 'fs'; import * as readline from 'readline ; We have no preference use whichever you prefer. Our examples use mostly ES6, but sometimes classic
Routers You can place all the endpoint handlers in a routers folder Each router will be redirect by Express, and the handler has an anonymous function to pick up the request and response arguments e.g. manf_router_v2.get('/teams', async function(req, response) { let result = await get_v2_teams(req); return response.send(result); } )
Handling APIs Similar, but different from Python The method and the verb combined, define the endpoint for the API. The .get method (for example) includes the endpoint path (from the root the server (/teams) AND the handler function The root was defined in the use statement app.use('/manf/api/v2', manf_router_v2) Note how I use an async inline function to handle the API method e.g. manf_router_v2.get('/teams', async function(req, response) { let result = await get_v2_teams(req); return response.send(result); } ) root of .get or .put or .post
Parameters from web requests my_dept_router.get('/costs', async function(req, response) { console.log(req.baseUrl,req.url); console.log(req.query);//Look at all query string params let coll1 = req.query[ query1'].toString(); }
Express and the DB We will use the JS module mongodb to interact with the database import { MongoClient } from 'mongodb For our project, this is imported in the db_utils file, and it returns a db object. Since all DB actions are done on the backend, this will be our key interface
Initializing the DB Each department is provided a datafile (or two) with seed data You will need to use mongo (on the server side code) to read, parse and load the DB It is your choice on how many collections you create It is your choice on how you arrange the data (embed lists, multiple collections, references ) i.e. DB Design! You may also add more data on your own but start with the data files provided (this is a typical example of how Data is initialized in industry situations) PS If you choose to add more data, you are free to use GPT or some other LLM to generate the data
Design tips Configuration will be an ongoing theme and you want to think about configuration for Running locally Running the CI Running on a production server Note that the CI and Server are considered production configurations Avoid hardcoding paths Use environment variables wherever possible to enable quick/ easy changes to configurations
Environment variables Even though we use JS for the full tech stack, the way environment variables are treated is difference between client and server Client React has a built in environment management system. If the variable name begins with REACT_APP_ , the React framework automatically loads the variables into process.env.REACT_APP_MY_VAR e.g. REACT_APP_MY_VAR=foo let theVariable = process.env.REACT_APP_MY_VAR It uses two files (the usage is pretty obvious) .env.dev .env.production When you do npm start , the variables are loaded from .env.dev When you do npm run build the variables are loaded from .env.production
Server env variables React has built in capability for env. variables, but Node and Express do not So what do we do? We use the module dotenv , and define our variables in a file named .env . Files do not need a prefix (REACT_APP) You just need to import 'dotenv/config'; Access to the variables is still process.env.VARIABLE_NAME
For example, in swen_343_db_utils we use: const url = `mongodb://${process.env.DB_USER}:${process.env.D B_PWD}@${process.env.URL}/${process.env.DBNAME}` URL=127.0.0.1:27017 PORT=5005 DBNAME=swen343db DB_USER=swen343 DB_PWD=****** If we change ports, or the DB name, or even the server location we don t need to hunt through the code, just change in one place!
Testing APIs Beyond using Jest, a convenient tool (that is very popular in industry) is Curl . C Client URL You can issue Web API requests directly from your command line and the server will respond This cleanly exercises the API and gives some freedom from having to run unit tests (although you still want to have the unit tests
Basic usage > curl <url endpoint> PS C:\Users\kalra> curl http://localhost:5005/ping pong PS C:\Users\kalra> Command Response
PS C:\Users\kalra> curl http://localhost:5005/ping -v * Host localhost:5005 was resolved. Verbose (-v) * IPv6: ::1 * IPv4: 127.0.0.1 * Trying [::1]:5005... * Connected to localhost (::1) port 5005 > GET /ping HTTP/1.1 > Host: localhost:5005 > User-Agent: curl/8.8.0 > Accept: */* > < HTTP/1.1 200 OK < X-Powered-By: Express < Access-Control-Allow-Origin: * < Content-Type: text/html; charset=utf-8 < Content-Length: 4 < ETag: W/"4-DlFKBmK8tp3IY5U9HOJuPUDoGoc" < Date: Mon, 09 Sep 2024 19:55:59 GMT < Connection: keep-alive < Keep-Alive: timeout=5 < pong* Connection #0 to host localhost left intact
Reading the output PS C:\Users\kalra> curl http://localhost:5005/coffeestore/api/menu [{"_id":"66de602202578fde6a78756e","menu number":3,"name":"Iced","hot":"f","season":"all year","category":"specialty"},{"_id":"66de602202578fde6a78756c","menu number":1,"name":"Drip","hot":"t","season":"all year","category":"basic"},{"_id":"66de602202578fde6a78756d","menu number":2,"name":"Pour Over","hot":"t","season":"all year","category":"basic"},{"_id":"66de602202578fde6a78756f","menu number":4,"name":"Orange Mocha Frappuccino","hot":"f","season":"all year","category":"premium"},{"_id":"66de602202578fde6a787570","menu number":5,"name":"gingerbread latte","hot":"t","season":"winter","catego PS C:\Users\kalra> curl http://localhost:5005/coffeestore/api/menu|json % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 2158 100 2158 0 0 97k 0 --:--:-- --:--:-- --:--:-- 100k [ { "_id": "66de602202578fde6a78756e", "menu number": 3, "name": "Iced", "hot": "f", "season": "all year", "category": "specialty" }, { "_id": "66de602202578fde6a78756c", "menu number": 1, "name": "Drip", "hot": "t", |json
Sending parameters Query string PS C:\Users\kalra> curl http://localhost:5005/coffeestore/api/menu?hot=t % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 2158 100 2158 0 0 84329 0 --:--:-- --:--:-- --:--:-- 86320 [ { "_id": "66de602202578fde6a78756e", "menu number": 3, "name": "Iced", "hot": "f", "season": "all year", "category": "specialty" }, { "_id": "66de602202578fde6a78756c", "menu number": 1, "name": "Drip", "hot": "t", "season": "all year", ?hot=t|json
Sending params - Body PS C:\Users\kalra> curl http://localhost:5005/coffeestore/api/menu/count {"count":16} PS C:\Users\kalra> curl --header "Content-Type: application/json" --request POST -- data '{"menu number":"17","name":"killah cannoli", "hot":"t","season":"all year", "category":"premium"}' http://localhost:5005/coffeestore/api/menu Ok PS C:\Users\kalra> curl http://localhost:5005/coffeestore/api/menu/count {"count":17}
Using curl vs. Jest Jest When you have reasonably working code, you can construct Unit tests to run on-demand/ automated tests to verify the code always works While you are still developing the code (not finished), curl is a quick way to checkout the behaviour and debug
curl alternatives curl is always there (for Windows esp.) and is a very quick/ easy command-line check For bigger tools (most with GUIs) some others are: postman( used to be great, and free now cloud profiles required with many limitations w/o payment) Free: Insomnia Apidog Postcode (VSCode plugin)