Home > Web Front-end > JS Tutorial > Basic CRUD API with express

Basic CRUD API with express

Linda Hamilton
Release: 2025-01-04 22:38:43
Original
476 people have browsed it

Content

  • Introduction
  • Project creation and initialization
  • Create a simple server and a GET route
  • Routes and Request handlers
  • Request and Response
  • Watch for changes
  • Create POST, GET, UPDATE, and DELETE routes
  • API Clients
  • Request body, params, query, header, ...
  • Manipulating memory data
  • Conclusion

Introduction

Basic CRUD API with express

JavaScript Essentials: Part 7

Michael Otu ・ Nov 2 '24

#javascript #api #beginners #node

Basic CRUD API with express

What is an API

Michael Otu ・ Feb 24 '24

#javascript #typescript #node #api

Basic CRUD API with express

What is REST API

Michael Otu ・ Mar 1 '24

#javascript #typescript #node #api

Basic CRUD API with express

JavaScript Essentials: Part 6 (Mastermind in Javascript)

Michael Otu ・ Oct 28 '24

#javascript #beginners #api #node

Basic CRUD API with express

What is Nodejs

Michael Otu ・ Jul 31 '24

#javascript #typescript #node #api

Basic CRUD API with express

Request and Response

Michael Otu ・ Mar 14 '24

#javascript #node #programming #tutorial

Basic CRUD API with express

What is JSON

Michael Otu ・ Mar 9 '24

#javascript #typescript #node #api

In JavaScript Essentials: Part 7, I hinted that we'd look into developing APIs ([0] [1]) and this is where we start. We will have a taste of what it takes to develop a simple API to track expenditures.

Project Description

For this expense tracker, we will need to keep track of the item purchased, the amount and the date the item was purchased. An expense will look like this:

{
    "name": "Legion Tower 7i Gen 8 (Intel) Gaming Desktop",
    "amount": 2099.99,
    "date": "2024-31-12"
}
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login

At this point, since a real database has not been added yet, we can use a list (an array) to hold the data that we will create. In this excerpt, we will go through each major concept surrounding creating APIs and add some ways to improve this app later.

Know that we will be building on top of this project, so, keep it clean and explore, experiment, fidget, etc as much as you can.

Project creation and initialization

As usual, we need a fresh working environment for each project, so we will begin by creating and initializing a Node JS project. If you are not sure, check out JavaScript Essentials: Part 6 (Mastermind in Javascript).

Now we have to create the parent folder for our API by doing:

# create a folder for the project at the path of your choice
mkdir expense-tracker-simple-api

# open the project with vscode
# code expense-tracker-simple-api
code -r expense-tracker-simple-api

# open the built-in terminal and init node
npm init -y
# this should create the package.json file

# create the entry file, index.js
echo "console.log(\"expense-tracker-simple-api\");" > index.js

# run the index.js file
node index.js
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login

All we are doing with this script is quite direct.

  • We create a folder for our project
  • We opened the folder in vscode
  • We initialized a nodejs project
  • We added a console log into the index.js file. This creates the file and adds some content
  • We execute the index.js file

An alternative is to go to wherever you want to create this folder and create it over there then open the folder in vscode and init node project - check out, JavaScript Essentials: Part 6 (Mastermind in Javascript).

At this point, we need to install a nodejs package called express. Express is a library that will help us create our APIs.

We can install this package by running, npm i express. This should modify the package.json file, and create the package-lock.json file and node_modules folder. Consult the excerpt, What is Nodejs, for further understanding and information regarding how to use npm to install packages.

Create a simple server and a GET route

In our index.js file, we can add this code.

console.log("expense-tracker-simple-api");

// import the express lib
const express = require("express");

// create an express application
const app = express();

// create a GET request on the base endpoint
app.get("/", (req, res) => res.send("Hello world"));

// create a server that listens to requests on port 3000
app.listen(3000, () =>
  console.log(`Api running on ${"http://localhost:3000"}`)
);
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login

All that we did was to create an express application, use the application to create a GET request to send a message and let the application listen in on requests coming from port 3000.

const app = express();
Copy after login
Copy after login
Copy after login
Copy after login

Creates an express application (? that how to create an express application)

app.get("/", (req, res) => res.send("Hello world"));
Copy after login
Copy after login
Copy after login

We used the express application instance to create a GET request. app has several methods and properties that include the HTTP methods. Check out the except about http methods here.

{
    "name": "Legion Tower 7i Gen 8 (Intel) Gaming Desktop",
    "amount": 2099.99,
    "date": "2024-31-12"
}
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login

We used the express application to listen on a port and used an arrow function to tell us, tell developers, that our application is running. For the port, we can alter it to another port of our choice. However, some special ports are already meant or used for some particular task and they are well known in the community and as such servers as default when such applications or programs are running on our PC. Check these out - 0 1 2

Note: There are some that are no-go because your system comes with them and there are some that come with applications we install such as some servers and databases and others. Fret not, when we use a port that is already in use, our application will let us know. All we have to do is add one or subtract one. No sweat.

Routes and Request handlers

To create a GET request, use app.get(...), for POST use app.post(...) and so on. For each route we want to create, the app.SomeMethod(...), will take a route or path, indicating which resource the user client desires or action they want to execute. As part of the route, it can take at least one request handler. This means we can have app.SomeMethod(path, hanlder1, handler2, ..., handlern);.

For the GET request above, the path or route is / (a string) and the single request handler we have is (req, res) => res.send("Hello world"), a handler function (a callback or a simple arrow function). The request handlers can be middleware and controllers.

Request and Response

A request handler normally takes in two arguments, the request and the response which are shortened as req and res respectively (you don't have to call them that but the first is always request and the second is the response). The request holds the data (or some information) about who made the request and what they want. The response is a means to provide feedback to the user who made the request. In this case, we send "Hello world" when the client makes a GET request to the / path.

Here you notice that the client and user are interchangeable, in the sense of which device makes the HTTP request to our api server and not a user, as in a user account.

Usually, the request handler will take a third argument which will point to the next handler after the previous handler has done its job. We call this next. It looks more or less like:

# create a folder for the project at the path of your choice
mkdir expense-tracker-simple-api

# open the project with vscode
# code expense-tracker-simple-api
code -r expense-tracker-simple-api

# open the built-in terminal and init node
npm init -y
# this should create the package.json file

# create the entry file, index.js
echo "console.log(\"expense-tracker-simple-api\");" > index.js

# run the index.js file
node index.js
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login

The next argument is useful, it points to the request handler and at times it takes an argument, an error. We will implement an error handler to generally handle errors we did not handle or errors that we "pass" to the next request handler.

Now let's cancel the running nodejs process that was running (in the terminal), using control c. Then run it again. This time with the updated content from Create a simple server and a GET route section, we should see an output in the console (terminal) similar to,

{
    "name": "Legion Tower 7i Gen 8 (Intel) Gaming Desktop",
    "amount": 2099.99,
    "date": "2024-31-12"
}
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login

Open http://localhost:3000 in the browser. What do you see? A text saying, Hello world ?

Watch for changes

Rome was not built in one day as the saying goes. The same applies to software development. Maybe here what we mean is that we will gradually add more features as we develop and in this continuous process, it becomes irritating to start and stop the server all the time.

Go on, add another GET request (route) with /hello path and a request handler that says something you would want to say. Be happy.

You'd have to restart the server (the running nodejs process) and visit, http://localhost:3000/hello in the browser to see the response from that endpoint.

This,GET http://localhost:3000/hello, is an endpoint. You share this with api consumers. Among ourselves, we say route, because we don't have to know the whole URL (including protocol - http, domain - localhost, port - 3000, and path - /hello). Route is METHOD PATH, more or less, GET /hello.

On macOS or Windows, we can do node --watch index.js or we can look out for changes not just in our entry file but in the whole folder path by, node --watch-path=./ index.js to watch for changes in the file path and also the file itself.

Currently, this is the content of my package.json file:

# create a folder for the project at the path of your choice
mkdir expense-tracker-simple-api

# open the project with vscode
# code expense-tracker-simple-api
code -r expense-tracker-simple-api

# open the built-in terminal and init node
npm init -y
# this should create the package.json file

# create the entry file, index.js
echo "console.log(\"expense-tracker-simple-api\");" > index.js

# run the index.js file
node index.js
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login

We can add a script called dev under the script section.

console.log("expense-tracker-simple-api");

// import the express lib
const express = require("express");

// create an express application
const app = express();

// create a GET request on the base endpoint
app.get("/", (req, res) => res.send("Hello world"));

// create a server that listens to requests on port 3000
app.listen(3000, () =>
  console.log(`Api running on ${"http://localhost:3000"}`)
);
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login

We can stop the running server with control c and now execute npm run dev. This will monitor saved changes in our files and reload the server.

So if this is not working for you, we have an alternative. We will install nodemone, npm i nodemon -g. We'd use it everywhere as a utility tool so we don't have to install it as part of our packages. We can watch changes by executing, nodemon index.js. There are cases where this won't work and when it doesn't, dom nodemon --exec node index.js

We can modify our dev script to use nodemon by,

const app = express();
Copy after login
Copy after login
Copy after login
Copy after login

At this point, you can freely modify your .js files and on save, the server will restart to reload the load changes applied.

Create POST, GET, UPDATE, DELETE routes

We have already created a GET request. In this section, we will look into what each method means briefly since we have discussed them at length in Request and Response.

In this application, we are only serving one kind of resource to our clients, and that is expenditures. Assuming we are serving several resources, then we'd group requests under each resource.

So let's say we have user and expenditure, we have GET, POST, PUT, DELETE, etc for both users and expenditures.

For now, we'd use the /expenditures route to represent the expenditure resource.

  • GET: This means we will create a route to list, get all, fetch all, etc the records we have on expenditures. We can have a GET request that fetches one of the records. We have created a similar GET

  • POST: The post method is often used for creating resources

  • PUT: The put method is used to update recourses

  • DELETE: The delete method is used to delete resource

Now we can add the following lines of code to the index.js file but above app.listen(3000,...).

{
    "name": "Legion Tower 7i Gen 8 (Intel) Gaming Desktop",
    "amount": 2099.99,
    "date": "2024-31-12"
}
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login

When you save your file, do you notice the logs in the terminal? Test the GET route for the expenditure in the browser.

We can only run the GET requests in the browser. We will discuss api clients next.

API Clients

An API client in this context is a tool, a program or an application that is used to interact (consume, integrate, or test) APIs. Most commonly used are Postman, Insomnia, curl, etc...

In vscode and alongside some other IDEs, there is an extension that provides extensions to api clients. vscode has some of these extensions for that matter. However, we will be considering an api client known as REST Client. For our use case, it will be simpler to use Rest Client as such don't fret. We are covered.

Note: postman or any other api client of your choice is okay to use

How to use REST Client

  • First, install, REST Client.
  • We are creating an HTTP request as such we can create a file with .http or .rest extension - touch expense-tracker-api.http
  • In expense-tracker-api.http we can define our request
  • To create a GET request, add the following to the .http file
{
    "name": "Legion Tower 7i Gen 8 (Intel) Gaming Desktop",
    "amount": 2099.99,
    "date": "2024-31-12"
}
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
  • The endpoint is passed as seen above. For a post, put or delete a request to update the endpoint. Remember the difference between an endpoint and a route?
  • For a request that requires that data be passed to the api, we can pass the data as part of the route as a parameter or a string query, or we can pass it in the body.
# create a folder for the project at the path of your choice
mkdir expense-tracker-simple-api

# open the project with vscode
# code expense-tracker-simple-api
code -r expense-tracker-simple-api

# open the built-in terminal and init node
npm init -y
# this should create the package.json file

# create the entry file, index.js
echo "console.log(\"expense-tracker-simple-api\");" > index.js

# run the index.js file
node index.js
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
  • Content-Type: application/json is a header key-value. This means that's how you pass headers using rest-client.
  • For the request body, we pass it as a json object - a newline is expected between the headers and the body though
  • Each request can be separated by three pound or ash signs, ###. A text can be added at the end of ### to make it look as if it is a title.
console.log("expense-tracker-simple-api");

// import the express lib
const express = require("express");

// create an express application
const app = express();

// create a GET request on the base endpoint
app.get("/", (req, res) => res.send("Hello world"));

// create a server that listens to requests on port 3000
app.listen(3000, () =>
  console.log(`Api running on ${"http://localhost:3000"}`)
);
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login

As an exercise, create the request for the expenditure endpoints. Refer to when you are having any difficulties. We have more to do.

Request body, params, query, header

At this point, I don't have to stress that we'd be using JSON to communicate with our api using the API client.

As mentioned earlier, we can pass data to our api using the body, header, or URL of our request. We have seen how to pass data via the request body and the header (We will look into passing some specific data at another time). Check the POST request created. What we have not looked at is how to pass data as part of the URL.

Let's say we want to read an expenditure which has an id of 4, we can pass the add a parameter (as part of the URL) as, /expenditures/2. For the request which will be handling this requirement, we do, /expenditures/:id, where :id refers to the id of the expenditure. Assuming it is something else other than an id, let's say a name, then we'd do :name. Express will process this a provide us with a means to extract this value without sweat.

Now, for a query string, the idea is similar to request parameters however, it comes after a question, followed by a key1=value1&key2=value2...&keyN=valueN, where the key is the identifier of the value you want to pass. A very direct example is the REST-Client URL, https://marketplace.visualstudio.com/items?itemName=humao.rest-client. The question mark marks the beginning of the query string and whatever follows it maps a key to a value. Eg: ?itemName=humao.rest-client.

It will be a good time to test all your api endpoints and experience playing with it.

Request Body

Now we are going to process a request that passes data using the request body - The POST endpoint.

{
    "name": "Legion Tower 7i Gen 8 (Intel) Gaming Desktop",
    "amount": 2099.99,
    "date": "2024-31-12"
}
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login

The request object has a property, body, and on this property, are the values that we passed in the request body of our request - req.body.

This is the request that will be running.

# create a folder for the project at the path of your choice
mkdir expense-tracker-simple-api

# open the project with vscode
# code expense-tracker-simple-api
code -r expense-tracker-simple-api

# open the built-in terminal and init node
npm init -y
# this should create the package.json file

# create the entry file, index.js
echo "console.log(\"expense-tracker-simple-api\");" > index.js

# run the index.js file
node index.js
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login

This is our endpoint implementation that will just log the request body to the console.

console.log("expense-tracker-simple-api");

// import the express lib
const express = require("express");

// create an express application
const app = express();

// create a GET request on the base endpoint
app.get("/", (req, res) => res.send("Hello world"));

// create a server that listens to requests on port 3000
app.listen(3000, () =>
  console.log(`Api running on ${"http://localhost:3000"}`)
);
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login

What happened? We had the usual response but... undefined was logged in the console. Well, it means everything is alright however, our api server doesn't know that it should parse the incoming as json. Remember json?

Let's add this one line below the const app = express(); which should solve parse the incoming data as json.

const app = express();
Copy after login
Copy after login
Copy after login
Copy after login

Now, let's test the POST endpoint again. What did you get this time? Did you get something similar to this?

app.get("/", (req, res) => res.send("Hello world"));
Copy after login
Copy after login
Copy after login

Now you know how to get the data from the body. Now as exercise, destructure the body and pass an object in the response. So instead of logging it, return it as the response.

Request parameter

We will create a new GET endpoint to read an expenditure by id.

This will be our API request:

app.listen(3000, () =>
  console.log(`Api running on ${"http://localhost:3000"}`)
);
Copy after login
Copy after login

The request object has a property, params and on this property, are the values that we passed in the request param of our request - req.params.

Now the implementation will be similar to what we have done so far but a little different.

app.get("/", (req, res, next) => ...);
Copy after login
Copy after login

We can access the id directly too. I hope you noticed that the :id key or name passed as part of the route matches the key in the logged object. Try renaming the params key in the route and see the output logged.

Request query (query string)

For the query strings, there is a property on the request object, query, which exposes the query strings passed.

To demonstrate this will pass a query string to filter the records to return. This endpoint should do enough.

expense-tracker-simple-api
Api running on http://localhost:3000
Copy after login
Copy after login

Now the implementation will be something similar to:

{
  "name": "expense-tracker-simple-api",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "description": "",
  "dependencies": {
    "express": "^4.21.2"
  }
}
Copy after login
Copy after login

Now run your api and check your logs. Experiment with this.

Manipulating memory data

At this point, we are not connecting to a database yet so we have to manipulate data from memory. What we intend to do is create an array, add to the array, update an element in it, and remove an element. It sounds feasible as such that's what we are going to do.

We will be doing some modifications to some previously written code as such, feel free to alter your too. The final excerpt will be shared at the end.

Initialize in-memory data

Let's create an array of expenditures (dummy data) below const express = require("express");

{
    "name": "Legion Tower 7i Gen 8 (Intel) Gaming Desktop",
    "amount": 2099.99,
    "date": "2024-31-12"
}
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login

List expenditures

The current endpoint returns just a message using the res.send(message) but what we want to return is json. Though the .send can also take in an object or json, we will use res.json(obj).

I didn't mention but the default status code returned is 200. Have you noticed that? Except that another occurs or there is an issue with the request, the status code remains the same. There is a section under status codes, glance through.

We can alter the status code by passing the desired status code in res.status(desireStatusCode).json(obj). I will maintain the 200 status code throughout.

Make sure the server is still running

We can pass the list of expenditures directly.

# create a folder for the project at the path of your choice
mkdir expense-tracker-simple-api

# open the project with vscode
# code expense-tracker-simple-api
code -r expense-tracker-simple-api

# open the built-in terminal and init node
npm init -y
# this should create the package.json file

# create the entry file, index.js
echo "console.log(\"expense-tracker-simple-api\");" > index.js

# run the index.js file
node index.js
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login

What was the response received? Check the status code as well as the response payload.

From experience and also to avoid ambiguity, I prefer to return status code 200 by default and have a either success property, message or data property to return a message or requested resource. By default, when status is false, message will be passed else, message or data may be passed.

console.log("expense-tracker-simple-api");

// import the express lib
const express = require("express");

// create an express application
const app = express();

// create a GET request on the base endpoint
app.get("/", (req, res) => res.send("Hello world"));

// create a server that listens to requests on port 3000
app.listen(3000, () =>
  console.log(`Api running on ${"http://localhost:3000"}`)
);
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login

We need to display the id (index of each row)

const app = express();
Copy after login
Copy after login
Copy after login
Copy after login

Apply filtering with

app.get("/", (req, res) => res.send("Hello world"));
Copy after login
Copy after login
Copy after login

Why was the filter done after the mapping?

Read expenditure

app.listen(3000, () =>
  console.log(`Api running on ${"http://localhost:3000"}`)
);
Copy after login
Copy after login

Does this implementation hint to you about, Why was the filter done after the mapping? ?

Create expenditure

app.get("/", (req, res, next) => ...);
Copy after login
Copy after login

Update expenditure

expense-tracker-simple-api
Api running on http://localhost:3000
Copy after login
Copy after login

Delete expenditure

{
  "name": "expense-tracker-simple-api",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "description": "",
  "dependencies": {
    "express": "^4.21.2"
  }
}
Copy after login
Copy after login

Conclusion

We have covered the root of most API developments. This project is as basic as it comes. Relax and glance through again. There is more to look into such as

  • validation
  • authentication and authorization
  • middleware
  • error handling
  • SQL
  • database integration

Practice project

crud api = create, list, read, update, and delete. It is how you approach these problems.

To-Do List

  • todo object: { id: int, task: string, status: boolean }
  • crud api
  • add an endpoint to mark all tasks as completed, success is true or not completed

Calculator⁠

  • you have to decide, whether you'd create an endpoint for all the operations (addition, subtraction, multiplication, division)
  • or you would create a single endpoint with different functions that correspond to each operation. The user should be able to pass the operator and the two operands

Currency Converter⁠
You are converting from one currency to another. Do for as many currencies as you can (3 is enough)

  • Unit Converter⁠ ⁠- Notes App⁠ ⁠- Personal Blog⁠ ⁠- Quiz App⁠

Snippets

Know that the excess was removed.

{
    "name": "Legion Tower 7i Gen 8 (Intel) Gaming Desktop",
    "amount": 2099.99,
    "date": "2024-31-12"
}
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login

API requests

# create a folder for the project at the path of your choice
mkdir expense-tracker-simple-api

# open the project with vscode
# code expense-tracker-simple-api
code -r expense-tracker-simple-api

# open the built-in terminal and init node
npm init -y
# this should create the package.json file

# create the entry file, index.js
echo "console.log(\"expense-tracker-simple-api\");" > index.js

# run the index.js file
node index.js
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login
Copy after login

The above is the detailed content of Basic CRUD API with express. For more information, please follow other related articles on the PHP Chinese website!

source:dev.to
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Latest Articles by Author
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template