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
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:
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.
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:
{
"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.
<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.
<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.
router.post('/profile', users.getProfile); // changed to post
<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
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:
// 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.
Note: make sure you're on the 'Params' tab instead of the 'Body' tab which I was on earlier. Force of habit!
Refactoring
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.
<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:
router.get('/profile', users.getProfile);
Next, on to our controller
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 🎉
{
"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, usereq.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.
Top comments (2)
Thanks for the writeup. Learning express right now and this really helped me differentiate between the two.
POST is for send data, GET is for receive data.