Feathers.js: A guide to quickly build a RESTful API server
Core points:
This article will guide you to build a RESTful API server in Node.js using Feathers.js.
API server, also known as application server, is a program that provides data to front-end applications. It also processes business logic on the backend and provides restricted access to the organization's database. Not only does it prevent unauthorized people from accessing data; it can also restrict their access or change data if logged in users do not have permission.
Every application you build needs to provide services to the end user. To do this, your application needs to process the data. You can use the remote API to create a new service. However, for most applications, you need to manage your own data storage. A popular option is to use online data storage services such as Firebase. This way, you don't have to deal with the tedious details of running a distributed database server. However, your project requirements may require a fully-featured internal database management system, such as MongoDB or Oracle. In order for your front-end application to access the data stored in the database, you need a server application located between the database and the front-end application.
As shown in the above image, the job of an application server is to access data from a database using SQL or NoSQL commands and convert it into a format that a front-end application (client browser) can understand - such as JSON. In addition, application servers can use various security protocols—such as HTTPS encryption and token authorization—to ensure that communication between database and client applications is secure and reliable. One of the main advantages of using this architecture is that you can use the same application server to deploy applications for different platforms—desktop, mobile, web, and more. Moreover, it is also easy to scale your application horizontally in order to provide services to more users efficiently and achieve fast response times.
We will build a simple API server and demonstrate the various features that Feathers provides.
Prerequisite:
Before starting this tutorial, you need to have a solid foundation on the following topics:
Feathers are built on top of Express, a minimalist web framework for Node.js. If you complete the tutorial demonstrated in the link, you will find it very laborious to build the RESTful API using Express only. With Feathers, most of the repetitive work is done for you. You just need to focus on configuring and customizing your code. Let's dig into the code and learn how this web framework works.
Project creation:
To start using Feathers, you need to install its command line application globally:
npm install -g @feathersjs/cli
Next, create a new API project using the following command:
mkdir contacts-api cd contacts-api feathers generate app
The following are my choices, you can choose any test framework you like. Unfortunately, the test is not within the focus of this article, so it will not be covered here. I personally like simplicity, which is why I chose Jest.
After the installation is complete, you can open your favorite code editor to view the project file.
If you complete the Express tutorial I listed in the Prerequisites section, the generated code should not scare you. Here is a short summary describing folders and files.
Now don't worry too much about the role of each file. As you go through this tutorial, you will learn more about how they work. Now, let's confirm that the test is working properly.
Code style check (Linting):
To make sure our project complies with the defined ESLint rules, just run the command npm test
. If you are using a Unix or Linux platform, this should work fine. If you are using Windows, you need to tweak something to run the test successfully.
First, go to package.json
and view the scripts
section. Change the test
line to:
"scripts": { "test": "npm run eslint && SET NODE_ENV= npm run jest", },
Next, if you have Prettier installed in Visual Studio Code, you need to change the single quote setting to true in the Workspace Settings tab:
{ "prettier.singleQuote": true }
Lastly, make sure that when creating or editing any file, the newline is LF. If you are using Visual Studio Code or similar editors, you can check the current newline style in the status bar. If CRLF is displayed, change to LF. Making these changes will help you pass the code style check test. Unfortunately, it takes more work to get the test to pass, and will not be introduced here.
Let's see how to generate the CRUD RESTful interface.
Generate service:
Building a RESTful CRUD API interface in Express requires some work. In Feathers, you can generate code by simply executing a single command and answering a few questions:
npm install -g @feathersjs/cli
In this tutorial, we will use the NeDB database. Feathers does support SQL databases (such as MySQL) and NoSQL databases (such as MongoDB). However, installing a database system — whether on your machine or on a cloud server — takes some time to configure it. NeDB, on the other hand, is an in-memory database written entirely in JavaScript, supporting a subset of the MongoDB API. No configuration is required; you just need to install it. It is perfect for prototyping and testing new applications. This is the database we will use in this tutorial.
Let's take a brief look at some of the files generated using this command:
services/contacts/contact.service.js
. This is a Feathers service that provides CRUD API endpoints for /contacts
. Very small, isn't it? This is because Feathers have done the heavy lifting for us. It saves us from writing boilerplate CRUD code. services/contacts/contact.hooks.js
. Here we customize the behavior of CRUD logic. We have the before
section where we can check or change the data before Feathers read or write to the database. We also have a after
section where we can check or change the results in the database before sending them to the client application. We can perform operations such as restricting access, data verification, performing join operations, and calculating the values of additional fields or columns. models/contacts.model.js
. Here we define a model and append it to the database table. This is also where we define a pattern that can be used to verify fields when a new record is inserted or updated. Unfortunately, NeDB does not support mode. However, I have provided an example of a model connected to MongoDB which supports mode functionality via mongoose adapter: mkdir contacts-api cd contacts-api feathers generate app
Despite some limitations with NeDB, it is still a very suitable database for prototyping. Most NoSQL databases allow you to submit data using any structure without defining the schema first. It is best to implement the model after implementing project requirements. With the pattern, Feathers will perform field validation for you using the rules you defined. You need a production-ready database (such as MongoDB) to define the schema. Please note that the configuration definition of the development database is in config/default.json
:
"scripts": { "test": "npm run eslint && SET NODE_ENV= npm run jest", },
This is where the database credentials are provided. We have another configuration file config/production.json
. This is the production database configuration used when deploying the Feathers application. It is important to use a separate database during development. Otherwise, you are at risk of deleting or damaging business operational data in your production database.
Now that we have set up the contact's CRUD service, it's time to give it a try. You can start the Feather server using the command npm start
. Please note that this server does not support hot reloading. Therefore, it needs to be restarted every time you change the code. To interact with our Feathers application, we need an API browser tool such as Postman or Insomnia. In this tutorial, I'll use Insomnia, but you can easily do it with Postman or any other tool.
Create a new GET request (press Ctrl N) and name it "List Contacts". In the URL section, enter http://localhost:3030/contacts
. When you click the "Send" button, you should see the following view:
Nothing! Our database is currently empty, so we need to create some new contacts. Create a new request called Create Contact. Fill in the remaining fields as follows:
If you forget to change the method in the above form to POST, you can change it later. Change the method to POST and change the Body tab to JSON. Copy the following data into the JSON tab:
npm install -g @feathersjs/cli
When you click the "Send" button, you should receive the following response. Please note that a _id
has been generated for your new contact.
Return to "List Contacts", and click the "Send" button again. You should get the following results:
mkdir contacts-api cd contacts-api feathers generate app
Return to "Create Contact" and publish several new records:
"scripts": { "test": "npm run eslint && SET NODE_ENV= npm run jest", },
{ "prettier.singleQuote": true }
Let us perform the update operation now. For this purpose, we will not use the UPDATE HTTP method. This method will completely overwrite the record. All we want to do is overwrite a single field, not the entire record. To do this, we will use PATCH. Create a new request, "Update Contact", as shown below:
In the URL field, enter http://localhost:3030/contacts/{_id}
. Replace {_id}
with the ID of the first record. Paste the following data into the JSON tab:
feathers generate service
Click the "Send" button. You should see the following results:
Please note that the remaining fields remain unchanged. Next, we will delete a record. It's easy. Simply create a new DELETE request and name it "Delete Contact". In the URL field, use the format http://localhost:3030/contacts/{_id}
. Just like before, replace {_id}
with the ID of the record you want to delete. Clicking "Send" will delete the record for you. You can confirm by running the List Contacts request again.
We just verified that all CRUD operations are running properly. In the next section, we will learn how to set up authentication.
(The following content is similar to the original text, but some statement adjustments and paragraph merging have been made to improve readability and fluency and keep the original intention unchanged. The image format remains unchanged.)
Authentication:
Currently, our /contacts
API endpoints are not protected. If we deploy the application to a cloud server, anyone with the URL can access and operate our records. To restrict access, we need to set up authentication. We will use JSON Web Tokens to implement authentication for our API applications. Run the following command to set it:
npm install -g @feathersjs/cli
As you can see, Feathers supports different user authentication methods. The "Local Username Password" option is easiest to set.
Select the following options:
Next, we need to create a new user. We can do this using Insomnia or any other API browser tool. Create a new request and name it "Create User".
In the JSON tab, send the following data:
mkdir contacts-api cd contacts-api feathers generate app
You should receive a response similar to the following:
We now have a user. Let's confirm this by creating a new request "List Users" and sending the URL http://localhost:3030/users
. Unfortunately, you will receive the following response:
We need to authenticate to access this data. Since we don't have a front-end application that we can use to log in, we will continue to use the API browser. Create a new request and name it "Get JWT Token". Fill in the form as follows:
This request uses the POST method. For more clarity, you can rename it to "Login". In the JSON tab, copy the following data:
"scripts": { "test": "npm run eslint && SET NODE_ENV= npm run jest", },
After clicking the Send button, you should receive the following response:
Copy the token code (without double quotes). Go to the List User Request page, select the Auth tab and select Bearer. Paste this token code into the TOKEN field.
After clicking the "Send" button, you should see the user list. Please note that our authentication system is not completely secure. Anyone with a /users
URL endpoint can create a new account and access our system. To prevent unauthorized creation of new accounts, we also need to restrict this endpoint. Open the file services/users/users.hooks.js
and update the following code snippet:
This will ensure that only authenticated users can create new accounts. The next step is to protect the /contacts
endpoint. Simply open the file services/contacts/contacts.hooks.js
and update accordingly:
Restart the Feathers server for code changes to take effect. If you try to run the List Contacts request, you will receive the following response:
To authenticate, you need to set up the Bearer token as before. Once you have done this, you can send a request and you should receive your contact list. Please note that the token you obtained earlier will expire in one day. For efficiency, it is best to use environment variables to make it easier to update all API request parameters at once. When building a front-end application, you need to store this token in local storage. Do not use cookies. Otherwise, your application will be vulnerable to CSRF attacks. Check out the Feathers security documentation for other security risks you should be aware of.
Now that you have set up authentication, any new services you create later will give you the option to protect new endpoints. Let's check out the last topic of this tutorial in the next section.
Hooks:
Hook is a middleware function attached to a service method before, after, or when an error occurs. They are often used to handle logging, restrict access, protect fields, fill related entities, send notifications, and more. If you look at services/users/users.hooks.js
, you can see some built-in Feathers hooks are in use. We will create our own custom hooks. First, stop the server and delete the data/contacts.db
database table. Next, use the following command to generate a new hook:
npm install -g @feathersjs/cli
Create custom hooks with the following optionsprocess-contact
:
What we want to do in this hook is to inject two new fields before processing the "Create Contact" request.
createdBy
: Link to the currently logged in user through _id
createdOn
hooks/process-contact.js
populate-user
hooks/populate-user
I hope you have now learned how to quickly build your own RESTful API server. We've only touched on the basics and you should read the full guide to discover more features Feathers can offer that can help you achieve advanced features with minimal effort. You should also check out the Awesome Feathers page, which contains a lot of resources. Whether you need plugins, project examples, or tutorials, you may find the link there. You should also check out the Feathers-plus CLI, which is an enhanced version of Feathers. It adds new features on top of what the Feathers CLI has already provided, such as generating code for seeding and GraphQL support.
If you want to improve the contacts-api
project further, I recommend that you create a new front-end application using the framework of your choice. Build login screens and CRUD pages for /contacts
and /users
endpoints. Enjoy the fun of implementing challenges.
Frequently Asked Questions about Feathers.js:
What is Feathers.js? Feathers.js is a web framework for building real-time applications. Designed to be lightweight, flexible and easy to use, it provides a suite of tools and patterns for building scalable and maintainable server-side applications.
What programming languages are supported by Feathers.js? Feathers.js mainly uses JavaScript on the server and client side. It can be used with Node.js on the server and supports various JavaScript frameworks on the client, including frameworks such as React, Angular and Vue.js.
What are the key features of Feathers.js? Feathers.js includes real-time features (through WebSocket and RESTful API), service-oriented architecture, support for various databases (MongoDB, PostgreSQL, etc.), authentication and authorization mechanisms, and plug-in systems for extensions.
How does Feathers.js handle real-time communication? Feathers.js uses the functions of WebSockets to achieve real-time communication. It provides a real-time API out of the box that allows clients to receive real-time updates when data on the server changes.
Can I use Feathers.js for server-side rendering (SSR)? Although Feathers.js is mainly used to build APIs and real-time applications, it can be used in conjunction with other frameworks such as Next.js or Nuxt.js to implement server-side rendering (SSR) of web applications.
All image links retain the original format.
The above is the detailed content of A Beginner's Guide to Feathers.js. For more information, please follow other related articles on the PHP Chinese website!