elazarl/goproxy: an HTTP proxy library for Go, not a proxy product
An HTTP proxy library for Go
At a glance
- What is it?
- elazarl/goproxy is a Go library for building a customized HTTP/HTTPS proxy server, including a MITM mode that generates TLS certificates. It is a net/http handler you embed in your own binary, so the work starts where the README stops.
- Who is it for?
- Adopt elazarl/goproxy when you need proxy behaviour inside a Go program you already control: request rewriting, host filtering, certificate generation, or raw connection access. Do not adopt it if you want a finished proxy daemon with a config file, since the README describes a library and the examples are the closest thing to a product.
- Can I use it commercially?
- Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 2 days ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What elazarl/goproxy actually is, and who it is for
The README opens by calling GoProxy "a library to create a customized HTTP/HTTPS proxy server using Go." That sentence is the whole scope. There is no binary to download, no config file to edit, no service to start. You import github.com/elazarl/goproxy into a Go program, and the proxy becomes one more handler in your own process. The README states the proxy itself is simply a net/http handler, so middleware for panic recovery, logging or compression can be layered over it, and it can be integrated with any other HTTP network library.
The audience follows from that. This is for Go engineers who need proxy behaviour as a component: a test harness that rewrites responses, an internal tool that filters traffic by host, a service that terminates TLS on behalf of a client to inspect what passes through. The README names the intended trade-off directly, describing the target as an optimized proxy server usable with a reasonable amount of traffic, yet customizable and programmable. Customizable and programmable are the operative words. If you want a proxy that someone else configured, this is the wrong shelf.
Four modes are listed. Regular HTTP proxying, HTTPS through CONNECT, HTTPS MITM where the server generates TLS certificates to parse request and response data, and a hijacked connection mode where your handler receives the raw net.Conn. The first two are plumbing. The last two are the reason people pick this library over writing a handler from scratch.
How the request pipeline and MITM certificates work
The mechanism is callback registration. You create a server with goproxy.NewProxyHttpServer(), then attach functions to request and response phases. The README's own example adds a header to every request before it is sent to the destination:
proxy.OnRequest().DoFunc(
func(r *http.Request,ctx *goproxy.ProxyCtx)(*http.Request,*http.Response) {
r.Header.Set("X-GoProxy","yxorPoG-X")
return r,nil
})The function receives the request and a ProxyCtx, and returns either a modified request or a response. Returning a response short-circuits the upstream call, which is how redirects and local handlers work. The README describes redirecting normal HTTP traffic to a custom handler when the target is a relative path such as /ping, and it describes selecting handlers by host using a single equality comparison or a regex evaluation. So the dispatch layer is yours to define, not a routing table the library imposes.
For MITM, the library generates certificates so it can read request and response bodies. The README mentions a MITM certificates cache that reuses certificates for later requests to the same host, saving CPU, and states plainly that it is not enabled by default but should be used in production. That is the single most important operational detail in the README, and it is easy to miss because the default path works without it.
The repository layout backs this up. There are separate files for HTTP, HTTPS, HTTP/2, websockets, certificates and the dispatcher, plus a transport directory and an internal directory. Release v1.9.0 is titled "HTTP/2 MITM Full Support", so HTTP/2 interception is a recent addition rather than something present since the beginning. The go.mod requires Go 1.24.0, which sets a floor on the toolchain you need.
Installing elazarl/goproxy and running a first proxy
There is no installer. You add the module to a Go project and write a main function. The README's "taste of GoProxy" example is a complete forwarding proxy in about a dozen lines:
package main
import (
"log"
"net/http"
"github.com/elazarl/goproxy"
)
func main() {
proxy := goproxy.NewProxyHttpServer()
proxy.Verbose = true
log.Fatal(http.ListenAndServe(":8080", proxy))
}Run that, and the process listens on port 8080. The README says the base example uses localhost:8080 as the proxy URL, so point a browser or client at it. Setting Verbose to true turns on logging, which is what you want on the first run and probably not in production.
For HTTPS interception you must trust the proxy's CA certificate, otherwise clients will reject the generated certificates. The README links to examples/customca/README.md for that step and does not restate it in the main file. The repository ships ca.pem and key.pem at the top level, and there is a certs/ directory, so the material for a custom CA is present, but the instructions live in the example.
If you plan to contribute rather than consume, the README documents the lint step. Install the linter with:
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latestThat places an executable in $GOPATH/bin, which the README notes is usually ~/go. The repository also carries a .golangci.yml, so the configuration is checked in. The README warns that a pull request named refactoring with 5,000 lines changed will not be merged.
Where the library model costs you
The most concrete limitation is stated by the project itself. The MITM certificate cache is off by default, and the README tells you to enable it in production. That means a naive deployment regenerates certificates per request to the same host, and the README attributes CPU cost to exactly that. Nothing warns you at runtime. You find out from load.
The second cost is that you own everything the library does not do. There is no access log format, no metrics endpoint, no health check, no graceful shutdown, no config file. Those are ordinary things a proxy daemon provides and a library does not. The README's list of features is a list of hooks, not a list of operational behaviour. If your team needs a proxy that a non-Go operator can configure, this is the wrong tool, and the gap will not close by reading more of the README.
The third is the trust boundary. MITM interception requires clients to trust a CA you generate. The README points at the customca example for that, and it is a real deployment step on every client, not a code change. On managed devices this is an administrative task. On unmanaged ones it is often not acceptable at all.
Finally, the README states this is an open source project managed by volunteers. The last push was on 2026-09-04, and v1.9.1 carries the same date, so the code is current. Volunteer maintenance is still a support model to plan around, and the README offers a paid consulting route through the current maintainer for integration work or custom features to maintain in your fork.
goproxy alternatives and how the approach differs
The obvious alternative is to write the proxy yourself on top of net/http. A basic forwarding proxy is not much code, and Go's standard library gives you the CONNECT handling and the reverse proxy plumbing. What you would be rebuilding is the MITM certificate generation, the per-host certificate cache, the HTTP/2 interception, and the websocket path. The repository has dedicated files for websockets and HTTP/2, and v1.9.0 is titled "HTTP/2 MITM Full Support", so that surface is broad enough that reimplementing it is a project, not an afternoon. If your requirement is plain forwarding with header edits, the standard library is the smaller dependency.
A second direction is a standalone proxy server that you configure rather than program. Those tools give you a config file and an operations story out of the box, and they take away the ability to run arbitrary Go logic in the request path. The README's feature list is entirely about running your own logic: custom http.Transport, custom handlers for relative paths, a Logger interface you implement, and a PreventCanonicalization flag for HTTP header canonicalization. None of that maps onto a config file. Choose the standalone route when your rules are expressible as configuration, and this library when they are expressible only as code.
A third option worth naming is the goproxy name collision itself. Several unrelated things share the name, including a Go module proxy environment variable and other proxies. When you search for help, expect to filter results by the repository path github.com/elazarl/goproxy rather than the bare word.
Licence, upgrade cost and what to verify
The code is released under BSD 3-Clause, and the README notes this makes it useful for commercial uses as well. That is a permissive licence with a standard attribution requirement, and it is the reason a library like this can be embedded in a closed product. This is a description of what the repository states, not legal advice; read LICENSE before you ship.
Upgrade cost is tied to the Go version floor. go.mod declares go 1.24.0, so a project on an older toolchain cannot take the current release without moving its own Go version first. Direct dependencies are few: github.com/coder/websocket v1.8.14 and golang.org/x/net v0.50.0, with testify and a few indirect modules. A small dependency graph is easier to audit and less likely to force transitive upgrades.
Before you commit, verify three things in your own environment. Confirm the CA trust step from examples/customca/README.md works on every client platform you support. Confirm whether you need the MITM certificate cache and turn it on if you do, since the README says it is not the default. And check the HTTP/2 behaviour against your traffic, because full HTTP/2 MITM support arrived in v1.9.0 and older releases will not match the current documentation.
Editorial conclusion
Adopt elazarl/goproxy when you need proxy behaviour inside a Go program you already control: request rewriting, host filtering, certificate generation, or raw connection access. Do not adopt it if you want a finished proxy daemon with a config file, since the README describes a library and the examples are the closest thing to a product. Before writing code, verify the MITM certificate cache setting, because the README states it is not enabled by default and recommends it for production.
Frequently asked questions
What does elazarl/goproxy do?
It is a Go library for building a customized HTTP/HTTPS proxy server. The README states the proxy is simply a net/http handler, so you embed it in your own program and add middleware around it.
How do you use elazarl/goproxy?
You create a server with goproxy.NewProxyHttpServer(), attach handlers such as proxy.OnRequest().DoFunc(...), and serve it with http.ListenAndServe on a port. The README's base example uses localhost:8080 as the proxy URL.
What is elazarl/goproxy used for?
The README lists four modes: a regular HTTP proxy, HTTPS through CONNECT, an HTTPS MITM proxy that generates TLS certificates to parse request and response data, and a hijacked connection where the handler gets the raw net.Conn.
Is there an alternative to elazarl/goproxy?
You can write the proxy on top of Go's net/http yourself, which is reasonable for plain forwarding with header edits. The library's value is the parts you would otherwise rebuild: MITM certificate generation, the per-host certificate cache, HTTP/2 and websocket handling.
What is elazarl/goproxy?
It is the Go module at github.com/elazarl/goproxy, described in its README as a library to create a customized HTTP/HTTPS proxy server using Go, with several configurable settings and a net/http handler at its core.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/elazarl-goproxy)