| // Copyright 2024 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package intercept |
| |
| import ( |
| "errors" |
| "net/http" |
| "net/url" |
| ) |
| |
| // Interceptor is used to change the host, and maybe the client, |
| // for a request to point to a test host. |
| type Interceptor struct { |
| Scheme string |
| FromHost string |
| ToHost string |
| Client *http.Client |
| } |
| |
| // EnableTestHooks installs the given interceptors to be used by URL and Request. |
| func EnableTestHooks(interceptors []Interceptor) error { |
| if TestHooksEnabled { |
| return errors.New("web: test hooks already enabled") |
| } |
| |
| for _, t := range interceptors { |
| if t.FromHost == "" { |
| panic("EnableTestHooks: missing FromHost") |
| } |
| if t.ToHost == "" { |
| panic("EnableTestHooks: missing ToHost") |
| } |
| } |
| |
| testInterceptors = interceptors |
| TestHooksEnabled = true |
| return nil |
| } |
| |
| // DisableTestHooks disables the installed interceptors. |
| func DisableTestHooks() { |
| if !TestHooksEnabled { |
| panic("web: test hooks not enabled") |
| } |
| TestHooksEnabled = false |
| testInterceptors = nil |
| } |
| |
| var ( |
| // TestHooksEnabled is true if interceptors are installed |
| TestHooksEnabled = false |
| testInterceptors []Interceptor |
| ) |
| |
| // URL returns the Interceptor to be used for a given URL. |
| func URL(u *url.URL) (*Interceptor, bool) { |
| if !TestHooksEnabled { |
| return nil, false |
| } |
| for i, t := range testInterceptors { |
| if u.Host == t.FromHost && (u.Scheme == "" || u.Scheme == t.Scheme) { |
| return &testInterceptors[i], true |
| } |
| } |
| return nil, false |
| } |
| |
| // Request updates the host to actually use for the request, if it is to be intercepted. |
| func Request(req *http.Request) { |
| if t, ok := URL(req.URL); ok { |
| req.Host = req.URL.Host |
| req.URL.Host = t.ToHost |
| } |
| } |