Understanding Node.js Backend Input: Query Parameters, Headers, and Request Body Payloads

Decoding Query Parameters, Headers, and Request Body Payloads

Understanding Node.js Backend Input: Query Parameters, Headers, and Request Body Payloads

In this post, we'll delve into why there are primarily three methods—query parameters, headers, and body payloads—for obtaining input on a server. We'll explore why relying on just one method isn't sufficient and why these three distinct approaches exist. By the end of this discussion, you'll grasp the differences between these methods, and their significance, and gain insights into when to opt for each one.

So, let's dive deeper into this topic.

introduction

In the world of creating websites, servers need different ways to get the info they need. They use three main ways: query parameters, headers, and body payloads. Knowing why these exist and how they work can really help servers do their job better.

This post is all about explaining why we have these ways to get info. We'll look at each one, see how they're different, and figure out when it's best to use each method. By understanding these methods, you'll see how important it is to use a mix of them to get the right info for servers.

Let's dive into this journey and uncover how these methods are super important in how servers communicate.

query parameters:

Query parameters are a way to pass information to a server by attaching key-value pairs to the end of a URL. These parameters come after a question mark '?' in a URL and are separated by an ampersand '&'. They are commonly used for filtering, sorting, or adding additional context to a request.

For example, consider a scenario where you're searching for books on a bookstore website. When you type a search term like "fiction" into the search bar and hit enter, the URL might look something like this: https://examplebookstore.com/search?category=fiction.

In this case:

The server understands that you're looking for books in the "fiction" category based on the query parameter provided.

Here's a breakdown of the components:

  • ? denotes the start of the query parameters.

  • category is the key that describes what type of information is being requested.

  • fiction is the value of the category key, specifying the specific category of books you're interested in.

Let's understand this with a simple sum example:

URL: http://localhost:4000/handleSum?value1=4&value2=5
import express from 'express';

const app = express();

// Function to calculate the sum of two values
const getSum = (value1, value2) => {
    return value1 + value2;
}

// Endpoint to handle calculating the sum of two numbers provided as query parameters
app.get('/handleSum', (req, res) => {
    const value1 = parseFloat(req.query.value1); // Retrieving the first value from the query parameters
    const value2 = parseFloat(req.query.value2); // Retrieving the second value from the query parameters

    // Checking if both provided values are valid numbers
    if (isNaN(value1) || isNaN(value2)) {
        return res.status(400).send('Invalid values'); // Sending a 400 Bad Request status if any value is not a number
    }

    // Calculating the sum of the parsed values
    const calculatedSum = getSum(value1, value2);
    // Constructing the response string with the calculated sum
    const responseString = `Calculated sum: ${calculatedSum}`;
    // Sending the calculated sum as a response
    res.status(200).send(responseString); // Converting the calculated sum to a string before sending
});

// Starting the server on port 4000
app.listen(4000, () => {
    console.log(`Server is running on port 4000`);
});

Output:

Real-world example:

Consider an e-commerce application that allows users to create custom orders and calculate the total cost of their selected items. The application's backend might provide an API endpoint for calculating the total cost based on the quantities and prices of selected items.

Let's understand with an example:

Suppose the e-commerce application has a shopping cart feature where users can add items along with their quantities. Each item has an associated price.

API Endpoint: /calculateTotal

The backend exposes an API endpoint /calculateTotal that accepts query parameters for itemId and quantity to calculate the total cost.

Example request: GET /calculateTotal?itemId=123&quantity=2

  • itemId: The unique identifier for an item.

  • quantity: The quantity of that item that the user wants to purchase.

import express from 'express';

const app = express();

// Function to calculate the total cost
const calculateTotalCost = (itemId, quantity) => {
    const item = items.find(item => item.id === itemId);
    if (!item) return -1; // Return -1 if the item is not found
    return item.price * quantity;
}

// Endpoint to calculate the total cost based on itemId and quantity
app.get('/calculateTotal', (req, res) => {
    const itemId = req.query.itemId;
    const quantity = parseInt(req.query.quantity);

    if (!itemId || isNaN(quantity) || quantity <= 0) {
        return res.status(400).send('Invalid request parameters');
    }

    const totalCost = calculateTotalCost(itemId, quantity);
    if (totalCost === -1) {
        return res.status(404).send('Item not found');
    }

    res.status(200).send(`Total cost for ${quantity} of Item ${itemId}: $${totalCost}`);
});

// Start the Express server
app.listen(4000, () => {
    console.log('Server running on port 3000');
});

Usage:

  • A client (frontend or another service) makes a GET request to /calculateTotal with itemId and quantity as query parameters.

  • The Express server fetches the item details from the database or in-memory data, calculates the total cost, and responds with the calculated total cost as a string message.

Headers

Headers are additional information sent along with an HTTP request or response. They contain metadata about the request or response and play a crucial role in communication between a client and a server.

Let's understand with a simple example where we use Postman for sending headers:

import express from 'express';

const app = express();

// Function to calculate the sum of two values
const getSum = (value1, value2) => {
    return value1 + value2;
}

// Endpoint to handle calculating the sum of two numbers provided as query parameters
app.get('/handleSum', (req, res) => {
    const value1 = parseFloat(req.headers.value1); // Retrieving the first value from the query parameters
    const value2 = parseFloat(req.headers.value2); // Retrieving the second value from the query parameters

    // Checking if both provided values are valid numbers
    if (isNaN(value1) || isNaN(value2)) {
        return res.status(400).send('Invalid values'); // Sending a 400 Bad Request status if any value is not a number
    }

    // Calculating the sum of the parsed values
    const calculatedSum = getSum(value1, value2);
    // Constructing the response string with the calculated sum
    const responseString = `Calculated sum: ${calculatedSum}`;
    // Sending the calculated sum as a response
    res.status(200).send(responseString); // Converting the calculated sum to a string before sending
});

// Starting the server on port 4000
app.listen(4000, () => {
    console.log(`Server is running on port 4000`);
});

Real-World Example for Headers:

Consider an online banking application that employs an API to interact with its backend server. The API endpoints manage various banking functionalities, including retrieving account details, processing transactions, and ensuring secure access to sensitive information.

Use Case: Authorization with Bearer Token

  • Scenario: The banking application's mobile app sends requests to the server to fetch the user's account details.

  • Authorization Header: To ensure secure access, the application includes an Authorization header in each request. Specifically, it uses a Bearer token obtained during the user's login process.

      // Example usage of an Authorization header in a banking API
      app.get('/userAccounts', (req, res) => {
          const authToken = req.headers.authorization;
    
          // Validate the authToken before providing access to user account details
          if (isValidAuthToken(authToken)) {
              const userAccounts = fetchUserAccounts(authToken);
              res.status(200).json(userAccounts);
          } else {
              res.status(401).send('Unauthorized');
          }
      });
    
    • Explanation:

      • /userAccounts represents an endpoint to retrieve user account details.

      • req.headers.authorization fetches the Authorization header sent with the request, containing the Bearer token.

      • The server validates the authToken to ascertain whether the user is authorized to access the account information.

      • If the token is valid, the server fetches the user's accounts and responds with the account details in JSON format.

    • Usage:

      • The banking application's mobile app sends requests to /userAccounts with the Bearer token included in the Authorization header.

      • The server verifies the token's authenticity, ensuring that only authorized users can access the account information.

In this scenario, the Authorization header acts as a key mechanism for ensuring secure access to sensitive user data. It exemplifies the practical use of headers in an API, specifically for authentication and authorization purposes, safeguarding the user's financial information.

Body Payloads:

The body payload constitutes the content conveyed within the body of an HTTP request or response. It enables the transmission of diverse data types, including JSON, form data, or binary data, between clients and servers.

Most of the time we deal with body payloads for sending data from frontend to backend with the help of form.

Let's understand with a simple example where we use Postman for sending Body Payloads:

import express from 'express';
import bodyParser from 'body-parser';

const app = express();

// Using body-parser middleware for parsing JSON and URL-encoded bodies
app.use(bodyParser.json()); // Parse JSON bodies
app.use(bodyParser.urlencoded({ extended: true })); // Parse URL-encoded bodies

// Function to calculate the sum of two values
const getSum = (value1, value2) => {
    return value1 + value2;
}

// Endpoint to handle calculating the sum of two numbers provided in the request body
app.post('/handleSum', (req, res) => {
    const { value1, value2 } = req.body; // Retrieving values from the request body

    // Checking if both provided values are valid numbers
    if (isNaN(value1) || isNaN(value2)) {
        return res.status(400).send('Invalid values'); // Sending a 400 Bad Request status if any value is not a number
    }

    // Parsing values as floats
    const parsedValue1 = parseFloat(value1);
    const parsedValue2 = parseFloat(value2);

    // Calculating the sum of the parsed values
    const calculatedSum = getSum(parsedValue1, parsedValue2);
    // Constructing the response string with the calculated sum
    const responseString = `Calculated sum: ${calculatedSum}`;
    // Sending the calculated sum as a response
    res.status(200).send(responseString); // Converting the calculated sum to a string before sending
});

// Starting the server on port 4000
app.listen(4000, () => {
    console.log(`Server is running on port 4000`);
});

Real-World Example for Headers:

Most of the time we deal with body payloads for sending data from frontend to backend with the help of form.

Use Case: Creating a New User Account

  • Scenario: An online platform allows users to register and create new accounts. When a user signs up on the platform, their details, such as username, email, and password, are sent to the backend server for account creation.

  • Body Payload: The user registration form collects information such as username, email, and password. This data is bundled into a body payload and sent to the server using the POST method.

Frontend

// Frontend: Sending user registration data to the backend
const userData = {
    username: 'example_user',
    email: 'user@example.com',
    password: 'securePassword123'
};

fetch('/register', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json', // Indicating JSON payload
    },
    body: JSON.stringify(userData) // Packaging user data into the request body
})
.then(response => {
    // Handle response from the server
})
.catch(error => {
    // Handle error, if any
});

Backend

import express from 'express';
const app = express();

// Endpoint to handle user registration
app.post('/register', (req, res) => {
    const { username, email, password } = req.body; // Retrieving user data from the request body

    // Process and create a new user account


    res.status(201).json({ message: 'User account created successfully' });
});

// Starting the server on port 3000
app.listen(3000, () => {
    console.log('Server running on port 3000');
});

Explanation:

  • The frontend collects user registration data (username, email, password) and sends it to the server using the fetch API with a POST request.

  • The Content-Type header is set to application/json to indicate that the payload sent in the body is in JSON format.

  • On the backend, the Express server receives the POST request at the /register endpoint, extracts the user data from the request body using middleware like body-parser or Express's built-in JSON parser, and then processes the data to create a new user account.

Of course, here's a more conversational and simplified conclusion about query parameters, headers, and body payloads in HTTP requests:


Conclusion:

Think of query parameters like handy notes scribbled at the end of a URL—useful for asking specifics or explaining what you want from a website. They help filter, sort, or describe the information you're seeking. For example, in a web link like https://example.com/search?type=videos, type=videos tells the website you're after video content.

Headers are like secret messages tucked inside your browser's request or the server's response. They carry crucial info, such as what kind of data you're sending, if you're logged in, or what language you prefer. For instance, an "Authorization" header might carry a special passcode letting you access a members-only area.

Body payloads are like sending a detailed letter or a package instead of just jotting down a quick note. They carry bigger, more organized information—like when you fill out an online form with your name, address, and preferences. This could be sending your login details or submitting a whole form on a website.

Each of these ways of communicating holds its own job:

  • Query parameters stick to the URL and are great for asking specific things.

  • Headers are like secret messages that carry important details.

  • Body payloads are for sending bigger, more organized information, like filling out forms or sharing detailed data.

Thank you for reading till the end ❤️