Hey anon đź‘‹ Welcome to my blog!
I'm really excited to share this with you—it's my very first blog post! 🎉 This one is based on a project i created a few months ago.
As the title suggests, today we're diving into Reverse Proxies. Now, you might be thinking, "What even are proxies?" or "How do they work?" or maybe even "Why would I need one?" Don't worry—I've got you covered! I'll break it all down for you, step by step.
In this post, you'll learn:
- What a Proxy is and the different types.
- How Reverse Proxies work, and why they're essential in web infrastructure.
- How to create your very own Reverse Proxy from scratch using JavaScript!
So, Let's get started! 🚀
So, what even is a Proxy?
Before diving into reverse proxies, let's first understand what a proxy is. At its core, a proxy is like a middleman that stands between two entities—in most cases, a client (like your browser) and a server (where websites or applications live). Instead of the client directly talking to the server, the proxy handles the communication.
Types of Proxies
There are two main types of proxies you'll come across:
Forward Proxy
A forward proxy sits in front of the client. It takes requests from the client, sends them to the server, and then returns the server's response to the client. Forward proxies are commonly used for:
- Hiding client identity: They mask the client's IP address for anonymity.
- Content filtering: For example, blocking certain websites in a corporate or educational network. Think of a forward proxy as a personal assistant who makes calls on your behalf.
Reverse Proxy
A reverse proxy, on the other hand, sits in front of the server. When a client sends a request, it goes to the reverse proxy first, which then forwards it to the appropriate server. The server’s response is then sent back to the client via the proxy.
A reverse proxy acts like a gatekeeper, deciding how and where requests should be handled. It provides several advantages, which we'll explore next.
Why Use a Reverse Proxy?
Reverse proxies are incredibly powerful and have become a staple in modern web infrastructure. Here are some key use cases:
-
Load Balancing
A reverse proxy can distribute incoming traffic across multiple servers, ensuring no single server is overwhelmed. This improves reliability and helps scale applications to handle more users.
-
Caching
Reverse proxies can cache responses from servers, so repeated requests for the same content (like images or static pages) can be served faster without hitting the server.
-
Security
By acting as an intermediary, a reverse proxy hides the details of the backend servers from the client. This can protect the servers from direct attacks and add an extra layer of security. They can also handle SSL termination, offloading the encryption and decryption workload from the backend servers.
-
Simplified Maintenance
Backend services can be updated or replaced without disrupting client traffic, as the proxy can seamlessly reroute requests.
TL;DR
A forward proxy acts as an intermediary for the client, helping it communicate with the server. A reverse proxy, on the other hand, manages client requests on behalf of the server. Now that you know what proxies are and how they work, it's time for the fun part, building one from scratch! Let's dive in! 🚀
It's BUILD Time!
We'll be building our reverse proxy using Node.js for the runtime, Express to create a server and Commander to handle command-line functionality.
Step 1: Prerequisites
First, ensure you have Node.js and npm installed on your system. If not, you can download them from nodejs.org.
Step 2: Set Up Your Project
Next, create a directory, cd
into it and initialize a node project:
This creates a new package.json file with default values, which we'll use to manage dependencies.
Step 3: Install Dependencies
Install the required libraries using npm:
Step 4: Configure the bin Field
To turn this into a proper CLI tool, we need to configure the bin field in package.json. Add this section below the dependencies:
What's the bin Field?
When building a CLI tool, the bin field allows users to run your command directly from the terminal, without needing to specify the full script path. Here's what it does:
- Key reverse-proxy: Defines the name of the CLI command users will run.
- Value ./bin/index.js: Points to the script that contains the tool's logic.
Once this is set up, users can run your tool by typing reverse-proxy in the terminal.
Step 5: Organize Your Project
- Create a folder named bin
- Inside the bin folder, create a file named index.js
And that's it for the setup! Now, we'll dive into writing the actual logic.
1. Shebang and Imports
At the very top of the file, we add:
- #!/usr/bin/env node: This shebang line tells the operating system to execute the file using Node.js. It ensures that our CLI tool works as expected when run directly from the terminal.
- Command: We import Command from the Commander library to handle CLI arguments and options.
- express: We import Express to create our proxy server.
2. Setup for Commander and Express
Next, we initialize the necessary modules:
- program: This initializes a new CLI command using Commander.
- app: This creates an Express application instance.
- currentURL: This variable will store the origin URL provided by the user.
3. Defining the CLI Command
We use Commander to configure our CLI tool:
4. Adding CLI Options
We specify the options that users can pass to the CLI.
The above code defines CLI options for --port (proxy server's port) and --origin (target URL), both required to start the proxy. The last line defines the description for the command.
5. Defining the Logic
Now, add a method called 'action' to the above chain of methods and add this code to it. What's happening here is we have created two constants port
and origin
taking values from the options
parameter. The options variable is what captures the values we enter when we run the command.
Next, we just check if port
and origin
exists or not. if they don't, an error message is printed and command execution is stopped. Then, The port
value is converted to an integer using parseInt()
and stored in portNum
for further use. The origin
URL is stored in currentURL
, which will be used later in the proxy logic.
Now, inside the action method itself, add the following code.
-
app.use("*")
This middleware intercepts all HTTP requests, regardless of the URL or HTTP method.
-
Constructing the Target URL
The proxy combines the currentURL with the incoming request's baseUrl to create the targetUrl. For example, if currentURL is https://jsonplaceholder.typicode.com and the request is for /posts, the targetUrl becomes https://jsonplaceholder.typicode.com/posts.
-
Forwarding the Request
Uses the Fetch API to send the request to the targetUrl. Copies the original request's HTTP method, headers, and (if applicable) body.
-
Handling the Response
The response from the target server is forwarded back to the client. GET requests don't include a body, but for other methods (e.g., POST, PUT), the body is forwarded as well.
-
Error Handling
If something goes wrong while forwarding the request, it logs the error and sends a 500 status code with an error message back to the client.
6. Starting the Server
Still inside the action method, we start the Express server on port portNum
.
7. Parsing the CLI Input
Add this line at the bottom of the code.
This processes the command-line input and triggers the appropriate action defined in the program.action block
Example Usage
With this, your reverse proxy is live, forwarding requests from http://localhost:3000 to https://jsonplaceholder.typicode.com.
Conclusion
And it's DONE! 🎉 Congratulations on building your very own Reverse Proxy from scratch. You've not only gained a deeper understanding of how proxies work, but you've also written a fully functional CLI tool using Node.js, Express, and Commander.
The full codebase is available on my GitHub Repo. Feel free to explore it, suggest improvements, or even contribute! 🫡
Since this is my first blog post, I'd really appreciate any feedback or suggestions you have by sending me an email. Whether it's about the code, the blog structure, or just general advice, feel free to let me know.
Stay tuned for the next blog!