How to build a Node.js proxy for HTTP GET?

How can I create a simple Node.js proxy server to forward HTTP GET requests?

I’m trying to build a proxy server in Node.js that forwards incoming HTTP GET requests to a third-party website, such as Google. The proxy should mirror the request path so that if a client requests:

127.0.0.1/images/srpr/logo11w.png

The proxy should serve the corresponding resource from:

http://www.google.com/images/srpr/logo11w.png

Here’s the code I tried:

const http = require('http');

http.createServer(onRequest).listen(80);

function onRequest(client_req, client_res) {
    client_req.addListener("end", function() {
        var options = {
            hostname: 'www.google.com',
            port: 80,
            path: client_req.url,
            method: client_req.method,
            headers: client_req.headers
        };
        
        var req = http.request(options, function(res) {
            var body;
            res.on('data', function(chunk) {
                body += chunk;
            });
            res.on('end', function() {
                client_res.writeHead(res.statusCode, res.headers);
                client_res.end(body);
            });
        });
        
        req.end();
    });
}

It works fine for HTML pages, but for other file types, it either returns a blank page or an error message from the target site.

What could be causing this issue, and how can I properly handle different response types in my Node.js proxy server?

Hey! Looks like you’re running into issues because you’re storing binary data in a string (var body). That messes up non-text responses like images. The trick is to use buffers instead.

Here’s a better approach for a Node.js proxy server that properly handles binary data:

const http = require('http');

http.createServer((client_req, client_res) => {
    const options = {
        hostname: 'www.google.com',
        port: 80,
        path: client_req.url,
        method: client_req.method,
        headers: client_req.headers
    };

    const proxy = http.request(options, (res) => {
        client_res.writeHead(res.statusCode, res.headers);
        res.pipe(client_res); // Directly pipe the response
    });

    client_req.pipe(proxy); // Pipe client request to the proxy server
}).listen(8080, () => console.log("Proxy running on port 8080"));

What’s Fixed?

:heavy_check_mark: Binary-safe streaming – No more corrupted images or PDFs.

:heavy_check_mark: Efficient data handling – No need to concatenate response chunks manually.

:heavy_check_mark: Cleaner, more reliable – Everything is piped as-is.

Give it a shot—this should work smoothly for any Node.js proxy server setup! :rocket:

Great start, @devan-skeem! But if you want an even cleaner and more reliable approach, I’d recommend using http-proxy. It saves you from manually handling headers, request methods, or response types.

Here’s how to do it with http-proxy:

:one: Install the package first:

npm install http-proxy

:two: Replace your code with this:

const httpProxy = require('http-proxy');
const proxy = httpProxy.createProxyServer({});

require('http').createServer((req, res) => {
    proxy.web(req, res, { target: 'http://www.google.com' });
}).listen(8080, () => console.log("Proxy running on port 8080"));

Why This is Better?

:heavy_check_mark: Zero manual handlinghttp-proxy takes care of everything.

:heavy_check_mark: Works with all file types – No more worrying about images, CSS, or JavaScript.

:heavy_check_mark: Lightweight & efficient – Handles requests automatically.

If you’re looking for the easiest way to set up a Node.js proxy server, this is the way to go! :tada:

Awesome, Toby! But there’s one thing missing—this works great for HTTP, but what about HTTPS? If you try to proxy https://www.google.com, it won’t work because http.request() doesn’t support secure connections.

Here’s how you can support both HTTP & HTTPS in your Node.js proxy server:

const http = require('http');
const https = require('https');

http.createServer((client_req, client_res) => {
    const target = client_req.url.startsWith('/https/') ? https : http;
    const url = client_req.url.replace('/https/', ''); // Adjust path for HTTPS

    const options = {
        hostname: 'www.google.com',
        port: target === https ? 443 : 80,
        path: url,
        method: client_req.method,
        headers: client_req.headers
    };

    const proxy = target.request(options, (res) => {
        client_res.writeHead(res.statusCode, res.headers);
        res.pipe(client_res);
    });

    client_req.pipe(proxy);
}).listen(8080, () => console.log("Proxy running on port 8080"));

What’s New?

:heavy_check_mark: Handles both HTTP & HTTPS requests.

:heavy_check_mark: Secure sites (Google, Facebook, etc.) work seamlessly.

:heavy_check_mark: Future-proofing – No need to worry about protocol mismatches.

With this, your Node.js proxy server can now handle secure requests without any issues! :earth_africa::rocket: