Repository: go
Issue: doc: net/http/httputil: add example for reuse of Director
Labels: Documentation,NeedsDecision

**Not a bug, it's a ~~API change proposal~~ documentation enhancement**:

# Rationale

Since go1.12 enhanced further the ReverseProxy implementation a closed source library (and many more open-source ones) that provide a reverse proxy for HTTP and WS can be deprecated.

The only difference between the closed source library was that I had a more convenient hook to modify a request that allowed me to focus only on the VHOST logic.

The change here would noticeably reduce the boilerplate and make developers avoid re-implementing logic and private function(s) that Directory already implements/uses.

**Update:** As per discussion, documentation is going to be enhanced. Ref: https://github.com/golang/go/issues/31406#issuecomment-482354227

# So, in terms of Golang code

## Current state:

```go
forwardProxy := httputil.NewSingleHostReverseProxy(target)
forwardProxy.Director = func(req *http.Request) {
    // NOTE: Just a copy of `ReverseProxy`'s default `Director`
    req.URL.Scheme = target.Scheme
    req.URL.Host = target.Host
    // NOTE: `singleJoiningSlash` must also be defined again by developer
    req.URL.Path = singleJoiningSlash(target.Path, req.URL.Path)
    if targetQuery == "" || req.URL.RawQuery == "" {
        req.URL.RawQuery = targetQuery + req.URL.RawQuery
    } else {
        req.URL.RawQuery = targetQuery + "&" + req.URL.RawQuery
    }
    if _, ok := req.Header["User-Agent"]; !ok {
        // explicitly disable User-Agent so it's not set to default value
        req.Header.Set("User-Agent", "")
    }
    // NOTE: End of copied

    // NOTE: Custom developer logic just begins to start here
    ...
}
forwardProxy.Transport = &http.Transport{
    TLSClientConfig: &tls.Config{
        InsecureSkipVerify: true,
    },
}
```

## (**Not needed**) With an addition of `ModifyRequest` hook

```go
forwardProxy := httputil.NewSingleHostReverseProxy(target)
forwardProxy.ModifyRequest = func(req *http.Request) {
    // NOTE: Custom developer logic just begins to start here
    ...
}
forwardProxy.Transport = &http.Transport{
    TLSClientConfig: &tls.Config{
        InsecureSkipVerify: true,
    },
}
```

## Documentation to be updated with

```go
forwardProxy := httputil.NewSingleHostReverseProxy(target)
originalDirector := forwardProxy.Director
forwardProxy.Director = func(req *http.Request) {
    originalDirector(req)
    // NOTE: Custom developer logic just begins to start here
    ...
}
...
```

# In pros/cons based on what I see (with respect to the fact that I'm just a Golang-using developer):

## Pros

* Less boilerplate
* No need to re-implement logic and re-define private functions used in `reverse_proxy`.
* Less error-prone since the developer only needs to think what logic to add instead of checking the existing implementation of `Director`.
* Not a breaking-change in API.

## Cons

~~* More than one way to do things.~~
~~* Needs a bit better documentation to signify the difference between `Director` and `ModifyRequest`.~~


ref: #31393

cc: @agnivade