REST API in Express (ES6)
Published: 2021-10-16 13:17:08

What is a REST API


From [Redhat](https://www.redhat.com/en/topics/api/what-is-a-rest-api) 
A REST API (also known as RESTful API) is an application programming interface (API or web API) that conforms to the constraints of REST architectural style and allows for interaction with RESTful web services. REST stands for representational state transfer and was created by computer scientist Roy Fielding.

To create a Nodejs project (for a runtime environment) we will create a folder called rest-api and run the command.

```
npm init - y

```

Once that is done, we will install few packages

```
npm i --save express cors mongoose
```

Discussing the packages
- Express: It is used to write the main code for the REST API
- Cors: Used to make requests from a different domain. Eg: Request from frontend which is hosted in http://localhost:3000 to the backend which is http://localhost:5000
- Mongoose: Mongoose is an ORM package which we will need to communicate with MongoDB.

To run ES6 `import` code instead of `require` we will add this piece of code to our package.json

```
"type": "module"
```

Paste the following code

```
import express from 'express';
import mongoose from 'mongoose';
import cors from 'cors';

import authRoutes from './auth.routes.js';

const app = express();
const port = process.env.PORT || 8000

app.use(express.urlencoded({ extended: true }))
app.use(express.json())
app.use(cors())

authRoutes(app);

mongoose.connect(process.env.mongoURI, {
    useNewUrlParser: true,
    useUnifiedTopology: true
}).then(() => {
    console.log("Connected to Database");
}).catch(err => {
    console.log('Could not connect to the database', err);
    process.exit();
});

app.listen(port, () => {
    console.log('Backend is running on port: ' + port)
})
```

### Explaining the code step by step

```
import express from 'express';
import mongoose from 'mongoose';
import cors from 'cors';
```
First we are going to import the libraries that we have installed

```
import authRoutes from './auth.routes.js';
```
Here we are importing a file, which we will create soon.

```
const app = express();
const port = process.env.PORT || 8000
```

In the first line we are creating an instance of express to use through out the app
In the second line we are declaring a port variable to that takes value from an `.env` file or the value is 8000

```
app.use(express.urlencoded({ extended: true }))
app.use(express.json())
app.use(cors())
```

app.use(express.urlencoded({extended: true })) is a method inbuilt in express to recognize the incoming Request Object as strings or arrays. 

app.use(express.json()) is a method inbuilt in express to recognize the incoming Request Object as a JSON Object

app.use(cors()) is using cors as a middleware for incoming requests from a different origin.

```
authRoutes(app);
```
authRoutes(app) here we calling authRoutes function passing the app instance.

```
mongoose.connect(process.env.mongoURI, {
    useNewUrlParser: true,
    useUnifiedTopology: true
}).then(() => {
    console.log("Connected to Database");
}).catch(err => {
    console.log('Could not connect to the database', err);
    process.exit();
});

app.listen(port, () => {
    console.log('Backend is running on port: ' + port)
})
```

These lines of code are used to connect to the mongodb and also check if it's running on which port.


```
import { register, login } from './auth.controller.js';

const authRoutes = (app) => {
  app.route('/register')
    .post(register)
  app.route('/signin')
    .post(login)
}

export default authRoutes
```

Here we are routing the requests based on the method that is incoming.


```
import bcrypt from 'bcryptjs';
import User from './User.model.js';

export const register = (req, res) => {
  const { email, password, name, dob, gender } = req.body.userDetails
  const userData = {
    email, password, name, dob, gender
  }
  if (!email || !password || !name) {
    return res.status(422).json({ error: "Please add all the credentials" })
  }
  User.findOne({ email })
    .then((data) => {
      if (data) {
        res.send({ error: 'Email already registered' });
      } else {
        bcrypt.hash(password, 10, (err, hash) => {
          userData.password = hash;
          User.create(userData, (err, data) => {
            res.status(200).json({ msg: 'Successfully registered' });
          })
        })
      }
    })
    .catch((err) => res.send({ error: err }))
};

export const login = (req, res) => {

  const { email, password } = req.body.userDetails;
  User.findOne({ email: email })
    .then((user) => {
      if (!user) {
        res.send({ error: 'Account not found' })
      } else {
        if (!bcrypt.compareSync(password, user.password)) {
          res.send({ error: "You entered a wrong password" })
        } else if (bcrypt.compareSync(password, user.password)) {
          delete user.password;
          res.status(200).json({ user: user.toJSON() });

        }
      }
    })
    .catch((err) => res.json({ error: err }))
}
```

I will not go into the details too much but here we have written two function for login and register.

While registering we are doing basic check if email, password and name are present or not. Before registering to our app, we will check if he is already present or not in the database. If he isn't present we will register him and use bcrypt to encrypt his password and save to database.

While logging in we are checking if the user is present or not. If not, we send an 'Account not found' error. If present, we pull out his data from database, remove his password and send back the data to the frontend.

```
import mongoose from 'mongoose';

const Schema = mongoose.Schema;

const UserSchema = Schema({
  name: {
    type: String,
    maxlength: 50,
  },
  email: {
    type: String,
    trim: true,
    unique: true,
    required: true,
  },
  password: {
    type: String,
    required: true,
  },
  gender: {
    type: String
  },
  dob: {
    type: Date
  }
})

const User = mongoose.model('User', UserSchema)
export default User;
```
Lastly, this is the User schema for all the users.