rewriteResponse replaces the upstream host with the gateway host everywhere it appears, so that clients following URLs the API handed them stay on the gateway.
(resp *http.Response, upstreamHost, gatewayHost string)
| 191 | // it appears, so that clients following URLs the API handed them stay on the |
| 192 | // gateway. |
| 193 | func rewriteResponse(resp *http.Response, upstreamHost, gatewayHost string) error { |
| 194 | for key, values := range resp.Header { |
| 195 | for i, value := range values { |
| 196 | if strings.Contains(value, upstreamHost) { |
| 197 | values[i] = strings.ReplaceAll(value, upstreamHost, gatewayHost) |
| 198 | } |
| 199 | } |
| 200 | resp.Header[key] = values |
| 201 | } |
| 202 | |
| 203 | body, err := io.ReadAll(resp.Body) |
| 204 | if err != nil { |
| 205 | return fmt.Errorf("reading upstream body: %w", err) |
| 206 | } |
| 207 | if err := resp.Body.Close(); err != nil { |
| 208 | return fmt.Errorf("closing upstream body: %w", err) |
| 209 | } |
| 210 | |
| 211 | body = bytes.ReplaceAll(body, []byte(upstreamHost), []byte(gatewayHost)) |
| 212 | |
| 213 | resp.Body = io.NopCloser(bytes.NewReader(body)) |
| 214 | resp.ContentLength = int64(len(body)) |
| 215 | resp.Header.Set("Content-Length", strconv.Itoa(len(body))) |
| 216 | // The upstream was asked for an identity encoding, but drop any stale |
| 217 | // encoding header rather than describe the rewritten body incorrectly. |
| 218 | resp.Header.Del("Content-Encoding") |
| 219 | |
| 220 | return nil |
| 221 | } |
| 222 | |
| 223 | func generateCertificates(gatewayHost string) ([]byte, tls.Certificate, error) { |
| 224 | caKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) |