<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Another</title>
    <description>The latest articles on DEV Community by Another (@lemper29).</description>
    <link>https://dev.to/lemper29</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3790126%2Fc72845a0-769d-4a9b-b403-b21173b5d8a1.jpeg</url>
      <title>DEV Community: Another</title>
      <link>https://dev.to/lemper29</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lemper29"/>
    <language>en</language>
    <item>
      <title>Reverse proxy in Go</title>
      <dc:creator>Another</dc:creator>
      <pubDate>Thu, 26 Feb 2026 07:50:19 +0000</pubDate>
      <link>https://dev.to/lemper29/reverse-proxy-in-go-3g5f</link>
      <guid>https://dev.to/lemper29/reverse-proxy-in-go-3g5f</guid>
      <description>&lt;p&gt;&lt;strong&gt;Reverse proxy&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A &lt;a href="https://en.wikipedia.org/wiki/Reverse_proxy" rel="noopener noreferrer"&gt;reverse proxy&lt;/a&gt; is a type of proxy server that receives a request from a client, forwards it to one or more servers, and relays the response back to the client.&lt;/p&gt;

&lt;p&gt;The distinguishing feature of a reverse proxy is that it acts as the entry point for the user's connection to the servers, with which the proxy itself is connected by business logic. It determines which servers the client's request will be forwarded to. The logic of the network behind the proxy remains hidden from the user.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnk8f27i1lei7nqiwz8g3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnk8f27i1lei7nqiwz8g3.png" alt="Reverse Proxy" width="652" height="192"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For comparison, a regular (or forward) proxy connects its clients to any server they need. In this case, the proxy sits in front of the user and simply acts as an intermediary in executing the request.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr5zcgk82sayt18nbr227.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr5zcgk82sayt18nbr227.png" alt="Forward Proxy" width="631" height="152"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For what purpose to use it&lt;/strong&gt;&lt;br&gt;
The reverse proxy concept can be applied in various situations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Load balancing&lt;/li&gt;
&lt;li&gt;A/B testing&lt;/li&gt;
&lt;li&gt;Resource caching&lt;/li&gt;
&lt;li&gt;Request data compression&lt;/li&gt;
&lt;li&gt;Traffic filtering&lt;/li&gt;
&lt;li&gt;Authorization&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Of course, the scope of application is not limited to these six points. The very fact that it's possible to process a request both before and after proxying provides ample room for creativity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Realization&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;target := "https://jsonplaceholder.typicode.com"
remote, err := url.Parse(target)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Setting up the target:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We define where requests will be forwarded to (JSONPlaceholder API)&lt;/li&gt;
&lt;li&gt;url.Parse() converts the string URL into a *url.URL struct
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;proxy := httputil.NewSingleHostReverseProxy(remote)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Creating the proxy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;NewSingleHostReverseProxy creates a reverse proxy that forwards requests to the specified URL&lt;/li&gt;
&lt;li&gt;It handles all the complex stuff: copying headers, managing connections, streaming responses&lt;/li&gt;
&lt;li&gt;This one line gives us a fully functional reverse proxy
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
r.Host = remote.Host
proxy.ServeHTTP(w, r)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The request handler:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;http.HandleFunc("/", ...) - registers a handler for all routes (/ matches everything)&lt;/li&gt;
&lt;li&gt;r.Host = remote.Host - CRITICAL LINE! Changes the Host header to match the target server. Without this, the target server sees the request as coming from localhost:4000 and may reject it.&lt;/li&gt;
&lt;li&gt;proxy.ServeHTTP(w, r) - forwards the modified request to the target and sends the response back
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http.ListenAndServe(":4000", nil)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Starting the server:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;http.ListenAndServe(":4000", nil) - starts HTTP server on port 4000&lt;/li&gt;
&lt;li&gt;The nil means "use the default router" (where we registered our handler)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Demonstration of Operation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let's start our proxy server and verify its operation. In the first screenshot, we see the startup process and request handling:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fogduls6m5lpl5xg9dxfr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fogduls6m5lpl5xg9dxfr.png" alt="Reverse proxy server " width="800" height="488"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The proxy has successfully started, is listening on port 4000, and is ready to forward requests to the JSONPlaceholder test API.&lt;/p&gt;

&lt;p&gt;Now let's make a request to our proxy using curl:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj2tmkqyvq742nsvzq8i5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj2tmkqyvq742nsvzq8i5.png" alt="Reverse proxy client" width="800" height="512"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It can be seen that the request has been received&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In this article, we have thoroughly explored what a reverse proxy is, why it's needed, and how to implement it in Go. In practice, we created a working proxy server that forwards requests to an external API, logs them, and returns the response to the client.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The source code&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The full project code is available on GitHub: &lt;a href="https://github.com/Lemper29/ReverseProxyGo" rel="noopener noreferrer"&gt;https://github.com/Lemper29/ReverseProxyGo&lt;/a&gt;&lt;/p&gt;

</description>
      <category>go</category>
    </item>
  </channel>
</rss>
