Remembering the difference between GET and POST 💡
Tags: todayilearned, express, postman
Published: 2020-08-30 18:14:39

---
title: Remembering the difference between GET and POST 💡
published: true
description: A short story of how I came to be reminded of the difference between GET and POST requests, featuring Express and Postman
tags: todayilearned, express, postman
cover_image: https://images.unsplash.com/photo-1462899006636-339e08d1844e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1650&q=80
---

I was reminded recently of the difference between GET and POST requests, after joining a colleague of mine on a project that uses Express, while knowing exactly nothing about Express. I thought this write-up will serve as a good reminder of the differences between those two HTTP methods and how to use them.

## Going in blind

![Developer focusing](https://dev-to-uploads.s3.amazonaws.com/i/wq7sbjn72473f5l0ww1g.png)

Being a learn-by-doing type, I got to work seeing the existing code and trying to follow along. My first task was to retrieve a user's profile details. This was obviously a GET method since we'll just be retrieving data and not creating anything new. I went to the `users` route file and added the following endpoint `router.get('/profile', users.getProfile);`

Then, I went to the `users` controller and created the following `getProfile` function, which was basically copied and pasted from an existing POST endpoint:

```js
getProfile: async (req, res) => {
    let user_id = req.body.id;
    if(!user_id) 
        res.send("Invalid id");

    let profile;
    try {
        profile = await User.getProfile(user_id);
    } catch (error) {
        res.send(500, error);
    }

    res.send(profile);
}
```

In this function, we first get the user's id from the request's body, then pass it to the model which will check for it in the database and hopefully return some data to us. Next I tried to connect to this endpoint by providing a valid user id using Postman.

![Sending a GET request to /profile using Postman, on Body tab](https://dev-to-uploads.s3.amazonaws.com/i/m2whlvznlvxgbf6vzasv.png)
_Notice how I'm sending data in the GET request's body, we'll come back to this later._

and I got the following response:

```json
{
    "id": "11",
    "mobile": "050-5555555",
    "email": "example@example.com",
    "full_name": "Jane Doe",
    "bio": "Live Laugh Love!"
}
```

Great! 👏 Naturally, the next step is to show this data in the view layer. 

```js
<script>
    $(document).ready(function() { 
        let id = '11';
        $.ajax({
            url: '/users/profile',
            type: 'GET',
            data: {id: id},
            async: false,
            success: function (data) {
                console.log(data);
            }
        });
    });
</script>
```

Now when I refresh the page, this AJAX request should hit the endpoint we specified and log the data. Perhaps unsurprisingly, this logs _Invalid id_. Let's try to send the id another way.

```js
<script>
    $(document).ready(function() { 
        let id = '11';
        $.ajax({
            url: '/users/profile?id=' + id,
            type: 'GET',
            async: false,
            success: function (data) {
                console.log(data);
            }
        });
    });
</script>
```

Hmmm, this also logs _Invalid id_. Weird. At this point, and because I was in a hurry, I just changed the route method from GET to POST, and changed it in the AJAX request as well, and I started seeing a result in the console.

```js
router.post('/profile', users.getProfile); // changed to post
```

```js
<script>
    $(document).ready(function() { 
        let id = '11';
        $.ajax({
            url: '/users/profile',
            type: 'POST', // changed to post
            data: {id: id},
            async: false,
            success: function (data) {
                console.log(data);
            }
        });
    });
</script>
```

Since this worked and I was short on time, I moved on to other endpoints which incidentally were all retrieving data but ended up being written as POST requests. A couple of weeks later, I had some time off and I was still thinking about this behavior, so I decided to revise HTTP methods and properly learn Express.

## Learning

![Lightbulb moment](https://dev-to-uploads.s3.amazonaws.com/i/3atmnlobo9wpakj58wss.png)

What I had forgotten was the main difference between GET and POST methods. Per MDN, GET requests should **not** have a body. Instead, the data should be sent in the request URL, in contrast to POST requests which hide the data in the request body and are therefore more secure. This great example from freeCodeCamp illustrates the concept:

```js
// GET request using query strings
route_path: '/library'
actual_request_URL: '/library?userId=546&bookId=6754' 
req.query: {userId: '546', bookId: '6754'}

// GET request using route parameters
route_path: '/user/:userId/book/:bookId'
actual_request_URL: '/user/546/book/6754' 
req.params: {userId: '546', bookId: '6754'}

// POST request
route_path: '/library'
actual_request_URL: '/library'
req.body: {userId: '546'}
```

However, Postman allowed us to embed data in a GET request's body which caused the confusion. Let's see the correct way to pass data with a GET request in Postman.

![Sending a GET request to /profile using Postman, on Params tab](https://dev-to-uploads.s3.amazonaws.com/i/x1q2nlcd97qi8a45eqc4.png)

_Note: make sure you're on the 'Params' tab instead of the 'Body' tab which I was on earlier. Force of habit!_

## Refactoring

![Light the fire](https://dev-to-uploads.s3.amazonaws.com/i/zrrc02uyewiw8zk1upfp.png)

Now, let's refactor our function to use a GET request as it was intended to. First, let's turn back our AJAX request to use the GET method.

```js
<script>
$(document).ready(function() {
    let id = '11'; 
    $.ajax({
        url: '/users/profile',
        type: 'GET', // change this back to GET
        data: {id: id},
        async: false,
        success: function (data) {
            console.log(data);
        }
    });
});
</script>
```

And update our route to use GET as well: 
```js
router.get('/profile', users.getProfile);
```

Next, on to our controller

```js
getProfile: async (req, res) => {
    let user_id = req.query.id; // use req.query, instead of req.body
    if(!user_id) 
        res.send("Invalid id");

    let profile;
    try {
        profile = await User.getProfile(user_id);
    } catch (error) {
        res.send(500, error);
    }

    res.send(profile);
}
```

And voila! We're successfully getting a response in our AJAX GET request 🎉

```json
{
    "id": "11",
    "mobile": "050-5555555",
    "email": "example@example.com",
    "full_name": "Jane Doe",
    "bio": "Live Laugh Love!"
}
```

## TL;DR
* GET requests **do not** have request bodies while POST requests do.
* Be careful when testing a GET endpoint using Postman. Make sure you pass the data in the 'Params' tab instead of the 'Body' tab that is used with POST requests.
* Use `req.query` to view the data sent with the GET request, if you're not using route parameters or named segments. If you are using route parameters, use `req.params` to view your data.

Thanks for reading! Let me know how I can make this article better. Until next time 👋
_Cover photo by Samson on Unsplash_. _Other photos from [Undraw](http://undraw.co)_.

## Resources
* https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods
* https://stackoverflow.com/questions/10298899/how-to-send-data-in-request-body-with-a-get-when-using-jquery-ajax
* https://www.freecodecamp.org/learn/apis-and-microservices/basic-node-and-express/