Leveraging Chrome DevTools for HTTP middleware observability and building a HTTP reverse|forward proxy with Go.

TLDR

cdp-proxy project is 2 things:

a reverse|forward proxy with cdp-proxy executable an http.Handler middleware to plug your Go project to Chrome DevTools

cdp-proxy is short for Chrome DevTools protocol.

cdp-proxy: a reverse|forward proxy

cdp-proxy executable is just like any other mitm style proxy: configure it as your HTTP proxy and you’ll get the requests showing up in Chrome DevTools. If you’re a developer and using Chrome you have likely used the UI before and proxy will be very familiar to you.

Running the proxy

download: go get github.com/gmarik/cdp-proxy/main/cdp-proxy install: go install github.com/gmarik/cdp-proxy/main/cdp-proxy run: cdp-proxy proxy is now listening on port 8080 inspector is now listening on port 9229

$ cdp-proxy 2019/10/07 17:12:55 http.devtools: ListenAndServe.address="localhost:9229" 2019/10/07 17:12:55 http.proxy: ListenAndServe.address="localhost:8080"

type chrome://inspect in Chrome’s address bar locate cdp-proxy in the list of the inspect-able targets, press inspect

Proxy-ing requests

using the curl:

for HTTP: http_proxy=localhost:8080 curl http://www.google.com

for HTTPS https_proxy=localhost:8080 curl https://www.google.com

If you feel more courageous you can set it as system-wide proxy in your OSX – (TODO: details)

Inspecting requests

At this point you should be able to see the requests showing up in Chrome DevTools

cdp-proxy: a Go HTTP middleware

Using the HTTP middleware in your project is as easy as:

adding cdp-proxy as a dependency hooking up to your middleware exposing the inspector endpoint

here’s a hello world snippet from an example

// ... // an event bus to forward data to Chrome var eb = httpcdp. NewEventBus () go func () { handler := http. HandlerFunc ( func (w http.ResponseWriter, r *http.Request) { w. Header (). Set ( "Content-Type" , "text/plain" ) fmt. Fprintf (w, "hello world" ) }) log. Printf ( "http.proxy: ListenAndServe.address=%q" , HTTP_Server_Addr) if err := http. ListenAndServe (HTTP_Server_Addr, cdphttp. Handler (eb, handler)); err != nil { log. Fatalf ( "http.proxy: ListenAndServe.error=%q" , err) } }() // ...

Similarly to proxy, requests made to the handler will show up in Chrome DevTools simplifying observability.

Known issues

TLDR: alpha quality!

Chrome DevTools doesn’t reconnect automatically Everything is stored in memory and inspection is equally a memory leak if done for too long No sampling: not recommended on high traffic endpoints yet TLS proxy is WIP logs are a mess

References

PS

Give it a try and let me know know what you think. For updates and questions follow @gmarik on twitter