What Is RESTful API? How to Create and Use RESTful APIs?

Alper Tellioglu
The Startup
Published in
5 min readNov 1, 2020

--

an architectural style for an API that uses HTTP requests to access and use data

What is REST?

REpresentational State Transfer is the architectural design of APIs. What do I mean by that? It’s a protocol that contains several rules. An API has to meet all all the conditions to be a RESTful API. We will discuss these rules just in a minute on this article. Before we do that, keep in mind that REST is not the only architectural style for APIs. There are many other concepts such as GraphQL and Soap.

Some architectural styles for APIs

2 Most Known Rules for an API to be RESTful

  • Use http request verbs
  • Allow RESTful routing while using http language

What Exactly are HTTP Verbs?

  1. Get
app.get(function(req, res){});
  • Get is for reading data from the server and it should only be used for retrieval. It can not be used for create or update.

2. Post

app.post(function(req, res){});
  • Post is for creating new documents. If a data exists before, don’t use Post. It should only be used when you are going to create a new one.

3. Put and Patch

app.put(function(req, res){});
app.patch(function(req, res){});
  • Put and patch are for updating documents. There is a small difference though.
  • When you use put for updating, you are updating the document by sending a new one. It creates a new document and sends that to update the existing document. That’s why, you should declare all the fields of the document while using put.
  • Patch on the other hand, updates only the mentioned fields and leaves the rest as it is. Patch updates the document by literally changing the document.

4. Delete

app.delete(function(req, res){});
  • It should be used for only deleting.

Let’s put it in practice and see them in real code examples. I will use mongoose model and methods for CRUD operations . You can check this article if you are not familiar with mongoose or CRUD.

  1. Read
app.get("/dogs", function(req, res){
Dog.find(function(err, foundList){
if (!err) {
console.log(foundList);
}
});
});
  • Inside app.get( ), we used find method to retrieve documents. If there is no error while retrieving we should be able to see them in the console.
  • We didn’t give any filter so that we can find all of the documents. We could find with query by passing {query} as the first parameter.

2. Post

app.post("/dogs", function(req, res){  const newDog = new Dog({
name: "Rex",
age: 1,
breed: "Golden Retriever"
});

newDog.save();
});
  • Since we are posting a new document, we first created one. Then we used save method to save it to the database.

3. Delete

app.delete("/dogs", function(req, res){
Dog.deleteMany(function(err){
if (!err) {
console.log("successfully deleted all the documents");
}
});
});
  • You can use deleteMany( ) method to delete multiple documents, or deleteOne( ) method to delete a single document.

What is RESTful Routing?

You all are already familiar with routing. It’s working under the hood every time you surf on the internet. The url is changing every time you click some link. We are sending requests to that url every time we want to access a website and it responses us with data or action.

If you don’t like theoretical definitions, here is an example for you:

Let’s say we have a database full of dogs and we can use the following url to request data about all the dogs:

localhost:3000/dogs

When we want to be more specific, say we need to get only golden retrievers, we should be able to specify it in request url.

localhost:3000/dogs/golden-retrievers

This concept is known as routing. Your APIs should adapt this protocol in order to be RESTful API.

How to do that? With chainable routes. Route chaining is like method chaining. Syntax looks like this:

route chaining

You can make the url dynamic for the client and pass the input as express parameter to the get, post and delete functions.

Express Parameter:

app.route("/dogs/:dogsBreed")
  • In the above line dogsBreed is a dynamic value. If client types beagle in there, dogsBreed will become beagle. If client types labrador, it will become labrador. You got the point!
  • We can reach it like this: req.params.dogsBreed
  • Now we can use that dynamic value to get what we want.

An example case:

app.route("/dogs/:dogsBreed").get(function(req, res){
Dog.find({breed: req.params.dogsBreed}, function(err, foundList)){
if (foundList) {
res.send(foundList);
}
}
});

We could also call .put:

app.route("/dogs/:dogsBreed").put(function(req, res){
Dog.update(
{name: "Rex"},
{name: "Rufus"},
{overwrite: true},
function(err){
if (!err) {
res.send("successfully updated the article");
}
}
);
});
  • First parameter: the document that will be updated
    - (the documents that has a name “Rex”)
  • Second parameter: what we want to update.
    - the name field will be changed to “Rufus” from “Rex”
  • Note: remember when you use put, you are updating the document by sending new one. So, all of the undeclared field will be removed. There will be only one field of the document which is name.

If you don’t want to change the entire document use .patch instead.

app.route("/dogs/:dogsBreed").patch(function(req, res){
Dog.update(
{name: "Rex"},
{$set: {name: "Rufus"}},
function(err){
if (!err) {
res.send("successfully updated the article");
}
}
);
});
  • In this case we only updated the name field and the rest will be still same.

What if we want to keep it dynamic as well? What if we want to update as many fields as client requests to?

{$set: req.body}
  • We could do that by passing req.body as a set parameter.
  • Since req.body is a dynamic javascript object it will only change the fields that clients request for.

Thanks for reading,

Take care,

--

--