internal/proxy/proxytest: proxy test code

Most of the code in internal/proxy was only for testing. Move it to a
separate package for clarity.

Change-Id: Ie9d241bc8a12923b579a7dd69ae7b36aaa1fd42a
Reviewed-on: https://go-review.googlesource.com/c/pkgsite/+/343209
Trust: Jonathan Amsterdam <jba@google.com>
Run-TryBot: Jonathan Amsterdam <jba@google.com>
TryBot-Result: kokoro <noreply+kokoro@google.com>
Reviewed-by: Julie Qiu <julie@golang.org>
diff --git a/internal/fetch/fetch_test.go b/internal/fetch/fetch_test.go
index 68baa86..dd260e3 100644
--- a/internal/fetch/fetch_test.go
+++ b/internal/fetch/fetch_test.go
@@ -25,7 +25,7 @@
 	"golang.org/x/pkgsite/internal/godoc"
 	"golang.org/x/pkgsite/internal/godoc/dochtml"
 	"golang.org/x/pkgsite/internal/licenses"
-	"golang.org/x/pkgsite/internal/proxy"
+	"golang.org/x/pkgsite/internal/proxy/proxytest"
 	"golang.org/x/pkgsite/internal/source"
 	"golang.org/x/pkgsite/internal/stdlib"
 	"golang.org/x/pkgsite/internal/testing/sample"
@@ -35,14 +35,14 @@
 
 var (
 	templateSource = template.TrustedSourceFromConstant("../../static/doc")
-	testModules    []*proxy.Module
+	testModules    []*proxytest.Module
 )
 
-type fetchFunc func(t *testing.T, withLicenseDetector bool, ctx context.Context, mod *proxy.Module, fetchVersion string) (*FetchResult, *licenses.Detector)
+type fetchFunc func(t *testing.T, withLicenseDetector bool, ctx context.Context, mod *proxytest.Module, fetchVersion string) (*FetchResult, *licenses.Detector)
 
 func TestMain(m *testing.M) {
 	dochtml.LoadTemplates(templateSource)
-	testModules = proxy.LoadTestModules("../proxy/testdata")
+	testModules = proxytest.LoadTestModules("../proxy/testdata")
 	licenses.OmitExceptions = true
 	os.Exit(m.Run())
 }
diff --git a/internal/fetch/fetchdata_test.go b/internal/fetch/fetchdata_test.go
index 6ddf089..aef7177 100644
--- a/internal/fetch/fetchdata_test.go
+++ b/internal/fetch/fetchdata_test.go
@@ -11,15 +11,15 @@
 	"golang.org/x/pkgsite/internal"
 	"golang.org/x/pkgsite/internal/derrors"
 	"golang.org/x/pkgsite/internal/godoc"
-	"golang.org/x/pkgsite/internal/proxy"
+	"golang.org/x/pkgsite/internal/proxy/proxytest"
 	"golang.org/x/pkgsite/internal/source"
 	"golang.org/x/pkgsite/internal/stdlib"
 	"golang.org/x/pkgsite/internal/testing/testhelper"
 )
 
 type testModule struct {
-	mod        *proxy.Module
-	modfunc    func() *proxy.Module // call to get module if mod field is nil
+	mod        *proxytest.Module
+	modfunc    func() *proxytest.Module // call to get module if mod field is nil
 	fr         *FetchResult
 	docStrings map[string][]string
 }
@@ -92,8 +92,8 @@
 }
 
 var moduleOnePackage = &testModule{
-	modfunc: func() *proxy.Module {
-		return proxy.FindModule(testModules, "example.com/single", "v1.0.0")
+	modfunc: func() *proxytest.Module {
+		return proxytest.FindModule(testModules, "example.com/single", "v1.0.0")
 	},
 	fr: &FetchResult{
 		HasGoMod: true,
@@ -110,8 +110,8 @@
 }
 
 var moduleNoGoMod = &testModule{
-	modfunc: func() *proxy.Module {
-		return proxy.FindModule(testModules, "example.com/basic", "v1.0.0").
+	modfunc: func() *proxytest.Module {
+		return proxytest.FindModule(testModules, "example.com/basic", "v1.0.0").
 			ChangePath("example.com/nogo").
 			DeleteFile("go.mod")
 	},
@@ -153,7 +153,7 @@
 }
 
 var moduleMultiPackage = &testModule{
-	modfunc: func() *proxy.Module { return proxy.FindModule(testModules, "example.com/multi", "v1.0.0") },
+	modfunc: func() *proxytest.Module { return proxytest.FindModule(testModules, "example.com/multi", "v1.0.0") },
 	fr: &FetchResult{
 		HasGoMod: true,
 		Module: &internal.Module{
@@ -232,14 +232,14 @@
 }
 
 var moduleEmpty = &testModule{
-	mod: &proxy.Module{
+	mod: &proxytest.Module{
 		ModulePath: "emp.ty/module",
 	},
 	fr: &FetchResult{Module: &internal.Module{}},
 }
 
 var moduleNoGo = &testModule{
-	mod: &proxy.Module{
+	mod: &proxytest.Module{
 		ModulePath: "no.go/files",
 		Files:      map[string]string{"go.mod": "module no.go/files"},
 	},
@@ -247,7 +247,7 @@
 }
 
 var moduleBadPackages = &testModule{
-	mod: &proxy.Module{
+	mod: &proxytest.Module{
 		ModulePath: "bad.mod/module",
 		Files: map[string]string{
 			"LICENSE": testhelper.BSD0License,
@@ -334,7 +334,9 @@
 }
 
 var moduleBuildConstraints = &testModule{
-	modfunc: func() *proxy.Module { return proxy.FindModule(testModules, "example.com/build-constraints", "") },
+	modfunc: func() *proxytest.Module {
+		return proxytest.FindModule(testModules, "example.com/build-constraints", "")
+	},
 	fr: &FetchResult{
 		Status:   derrors.ToStatus(derrors.HasIncompletePackages),
 		HasGoMod: true,
@@ -433,7 +435,7 @@
 
 // The package in this module is broken for one build context, but not all.
 var moduleBadBuildContext = &testModule{
-	mod: &proxy.Module{
+	mod: &proxytest.Module{
 		ModulePath: "github.com/bad-context",
 		Files: map[string]string{
 			"pkg/linux.go": `
@@ -475,7 +477,7 @@
 }
 
 var moduleNonRedist = &testModule{
-	modfunc: func() *proxy.Module { return proxy.FindModule(testModules, "example.com/nonredist", "") },
+	modfunc: func() *proxytest.Module { return proxytest.FindModule(testModules, "example.com/nonredist", "") },
 	fr: &FetchResult{
 		HasGoMod: true,
 		Module: &internal.Module{
@@ -580,7 +582,7 @@
 }
 
 var moduleBadImportPath = &testModule{
-	mod: &proxy.Module{
+	mod: &proxytest.Module{
 		ModulePath: "bad.import.path.com",
 		Files: map[string]string{
 			"good/import/path/foo.go": "package foo",
@@ -636,7 +638,7 @@
 }
 
 var moduleDocTest = &testModule{
-	mod: &proxy.Module{
+	mod: &proxytest.Module{
 		ModulePath: "doc.test",
 		Files: map[string]string{
 			"LICENSE": testhelper.BSD0License,
@@ -692,7 +694,7 @@
 }
 
 var moduleDocTooLarge = &testModule{
-	mod: &proxy.Module{
+	mod: &proxytest.Module{
 		ModulePath: "bigdoc.test",
 		Files: map[string]string{
 			"LICENSE": testhelper.BSD0License,
@@ -739,7 +741,7 @@
 }
 
 var moduleWasm = &testModule{
-	mod: &proxy.Module{
+	mod: &proxytest.Module{
 		ModulePath: "github.com/my/module/js",
 		Files: map[string]string{
 			"README.md": "THIS IS A README",
@@ -797,7 +799,7 @@
 }
 
 var moduleAlternative = &testModule{
-	mod: &proxy.Module{
+	mod: &proxytest.Module{
 		ModulePath: "github.com/my/module",
 		Files:      map[string]string{"go.mod": "module canonical"},
 	},
@@ -807,7 +809,7 @@
 }
 
 var moduleStdMaster = &testModule{
-	mod: &proxy.Module{
+	mod: &proxytest.Module{
 		ModulePath: stdlib.ModulePath,
 		Version:    "master",
 		// No files necessary because the internal/stdlib package will read from
@@ -883,7 +885,7 @@
 }
 
 var moduleStd = &testModule{
-	mod: &proxy.Module{
+	mod: &proxytest.Module{
 		ModulePath: stdlib.ModulePath,
 		Version:    "v1.12.5",
 		// No files necessary because the internal/stdlib package will read from
@@ -2682,7 +2684,7 @@
 }
 
 var moduleMaster = &testModule{
-	mod: &proxy.Module{
+	mod: &proxytest.Module{
 		ModulePath: "github.com/my/module",
 		Files: map[string]string{
 			"foo/foo.go": "// package foo exports a helpful constant.\npackage foo\nconst Bar = 1",
@@ -2732,7 +2734,7 @@
 }
 
 var moduleLatest = &testModule{
-	mod: &proxy.Module{
+	mod: &proxytest.Module{
 		ModulePath: "github.com/my/module",
 		Files: map[string]string{
 			"foo/foo.go": "// package foo exports a helpful constant.\npackage foo\nconst Bar = 1",
@@ -2789,7 +2791,7 @@
 // The substrings are separated by a '~' character.
 func moduleWithExamples(path string, api []*internal.Symbol, source, test string, docSubstrings ...string) *testModule {
 	return &testModule{
-		mod: &proxy.Module{
+		mod: &proxytest.Module{
 			ModulePath: path,
 			Files: map[string]string{
 				"LICENSE": testhelper.BSD0License,
diff --git a/internal/fetch/helper_test.go b/internal/fetch/helper_test.go
index 161f3b6..b158924 100644
--- a/internal/fetch/helper_test.go
+++ b/internal/fetch/helper_test.go
@@ -17,6 +17,7 @@
 	"golang.org/x/pkgsite/internal/licenses"
 	"golang.org/x/pkgsite/internal/log"
 	"golang.org/x/pkgsite/internal/proxy"
+	"golang.org/x/pkgsite/internal/proxy/proxytest"
 	"golang.org/x/pkgsite/internal/source"
 	"golang.org/x/pkgsite/internal/stdlib"
 	"golang.org/x/pkgsite/internal/testing/sample"
@@ -129,7 +130,7 @@
 
 // proxyFetcher is a test helper function that sets up a test proxy, fetches
 // a module using FetchModule, and returns fetch result and a license detector.
-func proxyFetcher(t *testing.T, withLicenseDetector bool, ctx context.Context, mod *proxy.Module, fetchVersion string) (*FetchResult, *licenses.Detector) {
+func proxyFetcher(t *testing.T, withLicenseDetector bool, ctx context.Context, mod *proxytest.Module, fetchVersion string) (*FetchResult, *licenses.Detector) {
 	t.Helper()
 
 	modulePath := mod.ModulePath
@@ -141,7 +142,7 @@
 		fetchVersion = version
 	}
 
-	proxyClient, teardownProxy := proxy.SetupTestClient(t, []*proxy.Module{{
+	proxyClient, teardownProxy := proxytest.SetupTestClient(t, []*proxytest.Module{{
 		ModulePath: modulePath,
 		Version:    version,
 		Files:      mod.Files,
@@ -159,7 +160,7 @@
 // localFetcher is a helper function that creates a test directory to hold a module,
 // fetches the module from the directory using FetchLocalModule, and returns a fetch
 // result, and a license detector.
-func localFetcher(t *testing.T, withLicenseDetector bool, ctx context.Context, mod *proxy.Module, fetchVersion string) (*FetchResult, *licenses.Detector) {
+func localFetcher(t *testing.T, withLicenseDetector bool, ctx context.Context, mod *proxytest.Module, fetchVersion string) (*FetchResult, *licenses.Detector) {
 	t.Helper()
 
 	directory, err := testhelper.CreateTestDirectory(mod.Files)
diff --git a/internal/fetch/latest_test.go b/internal/fetch/latest_test.go
index 0e9ce4d..b5368ff 100644
--- a/internal/fetch/latest_test.go
+++ b/internal/fetch/latest_test.go
@@ -9,7 +9,7 @@
 	"testing"
 
 	"golang.org/x/pkgsite/internal/derrors"
-	"golang.org/x/pkgsite/internal/proxy"
+	"golang.org/x/pkgsite/internal/proxy/proxytest"
 	"golang.org/x/pkgsite/internal/stdlib"
 )
 
@@ -17,7 +17,7 @@
 	// latestVersion is tested above.
 	// Contents of the go.mod file are tested in proxydatasource.
 	// Here, test retractions and presence of a go.mod file.
-	prox, teardown := proxy.SetupTestClient(t, testModules)
+	prox, teardown := proxytest.SetupTestClient(t, testModules)
 	defer teardown()
 
 	stdlib.UseTestData = true
@@ -52,12 +52,12 @@
 func TestLatestModuleVersionsNotFound(t *testing.T) {
 	// Verify that we get (nil, nil) if there is no version information.
 	const modulePath = "example.com/no-versions"
-	server := proxy.NewServer(testModules)
-	server.AddModuleNoVersions(&proxy.Module{
+	server := proxytest.NewServer(testModules)
+	server.AddModuleNoVersions(&proxytest.Module{
 		ModulePath: modulePath,
 		Version:    "v0.0.0-20181107005212-dafb9c8d8707",
 	})
-	client, teardown, err := proxy.NewClientForServer(server)
+	client, teardown, err := proxytest.NewClientForServer(server)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -75,7 +75,7 @@
 func TestLatestModuleVersionsBadGoMod(t *testing.T) {
 	// Verify that we get a BadModule error if the go.mod file is bad.
 	const modulePath = "example.com/bad-go-mod"
-	server := proxy.NewServer([]*proxy.Module{
+	server := proxytest.NewServer([]*proxytest.Module{
 		{
 			ModulePath: modulePath,
 			Version:    "v1.0.0",
@@ -84,7 +84,7 @@
 			},
 		},
 	})
-	client, teardown, err := proxy.NewClientForServer(server)
+	client, teardown, err := proxytest.NewClientForServer(server)
 	if err != nil {
 		t.Fatal(err)
 	}
diff --git a/internal/fetch/readme_test.go b/internal/fetch/readme_test.go
index 4e41619..714d575 100644
--- a/internal/fetch/readme_test.go
+++ b/internal/fetch/readme_test.go
@@ -12,7 +12,7 @@
 
 	"github.com/google/go-cmp/cmp"
 	"golang.org/x/pkgsite/internal"
-	"golang.org/x/pkgsite/internal/proxy"
+	"golang.org/x/pkgsite/internal/proxy/proxytest"
 	"golang.org/x/pkgsite/internal/stdlib"
 )
 
@@ -92,7 +92,7 @@
 					t.Fatal(err)
 				}
 			} else {
-				proxyClient, teardownProxy := proxy.SetupTestClient(t, []*proxy.Module{
+				proxyClient, teardownProxy := proxytest.SetupTestClient(t, []*proxytest.Module{
 					{ModulePath: test.modulePath, Files: test.files}})
 				defer teardownProxy()
 				reader, err = proxyClient.Zip(ctx, test.modulePath, "v1.0.0")
diff --git a/internal/frontend/fetch_test.go b/internal/frontend/fetch_test.go
index 1dbc389..4463ece 100644
--- a/internal/frontend/fetch_test.go
+++ b/internal/frontend/fetch_test.go
@@ -15,7 +15,7 @@
 	"golang.org/x/pkgsite/internal"
 	"golang.org/x/pkgsite/internal/derrors"
 	"golang.org/x/pkgsite/internal/postgres"
-	"golang.org/x/pkgsite/internal/proxy"
+	"golang.org/x/pkgsite/internal/proxy/proxytest"
 	"golang.org/x/pkgsite/internal/testing/sample"
 	"golang.org/x/pkgsite/internal/testing/testhelper"
 	"golang.org/x/pkgsite/internal/version"
@@ -26,7 +26,7 @@
 	testModulePath      = "github.com/module"
 	testSemver          = "v1.5.2"
 	testFetchTimeout    = 300 * time.Second
-	testModulesForProxy = []*proxy.Module{
+	testModulesForProxy = []*proxytest.Module{
 		{
 			ModulePath: testModulePath,
 			Version:    testSemver,
diff --git a/internal/frontend/server_test.go b/internal/frontend/server_test.go
index 8c1f13b..2c61084 100644
--- a/internal/frontend/server_test.go
+++ b/internal/frontend/server_test.go
@@ -28,7 +28,7 @@
 	"golang.org/x/pkgsite/internal/experiment"
 	"golang.org/x/pkgsite/internal/middleware"
 	"golang.org/x/pkgsite/internal/postgres"
-	"golang.org/x/pkgsite/internal/proxy"
+	"golang.org/x/pkgsite/internal/proxy/proxytest"
 	"golang.org/x/pkgsite/internal/queue"
 	"golang.org/x/pkgsite/internal/source"
 	"golang.org/x/pkgsite/internal/testing/htmlcheck"
@@ -1547,9 +1547,9 @@
 	}
 }
 
-func newTestServer(t *testing.T, proxyModules []*proxy.Module, redisClient *redis.Client, experimentNames ...string) (*Server, http.Handler, func()) {
+func newTestServer(t *testing.T, proxyModules []*proxytest.Module, redisClient *redis.Client, experimentNames ...string) (*Server, http.Handler, func()) {
 	t.Helper()
-	proxyClient, teardown := proxy.SetupTestClient(t, proxyModules)
+	proxyClient, teardown := proxytest.SetupTestClient(t, proxyModules)
 	sourceClient := source.NewClient(sourceTimeout)
 	ctx := context.Background()
 
diff --git a/internal/proxy/client.go b/internal/proxy/client.go
index 4428f67..4240b15 100644
--- a/internal/proxy/client.go
+++ b/internal/proxy/client.go
@@ -33,7 +33,7 @@
 	url string
 
 	// Client used for HTTP requests. It is mutable for testing purposes.
-	httpClient *http.Client
+	HTTPClient *http.Client
 
 	// Whether fetch should be disabled.
 	disableFetch bool
@@ -54,7 +54,7 @@
 
 // Setting this header to true prevents the proxy from fetching uncached
 // modules.
-const disableFetchHeader = "Disable-Module-Fetch"
+const DisableFetchHeader = "Disable-Module-Fetch"
 
 // New constructs a *Client using the provided url, which is expected to
 // be an absolute URI that can be directly passed to http.Get.
@@ -62,7 +62,7 @@
 	defer derrors.WrapStack(&err, "proxy.New(%q)", u)
 	return &Client{
 		url:          strings.TrimRight(u, "/"),
-		httpClient:   &http.Client{Transport: &ochttp.Transport{}},
+		HTTPClient:   &http.Client{Transport: &ochttp.Transport{}},
 		disableFetch: false,
 	}, nil
 }
@@ -156,11 +156,11 @@
 func (c *Client) ZipSize(ctx context.Context, modulePath, resolvedVersion string) (_ int64, err error) {
 	defer derrors.WrapStack(&err, "proxy.Client.ZipSize(ctx, %q, %q)", modulePath, resolvedVersion)
 
-	url, err := c.escapedURL(modulePath, resolvedVersion, "zip")
+	url, err := c.EscapedURL(modulePath, resolvedVersion, "zip")
 	if err != nil {
 		return 0, err
 	}
-	res, err := ctxhttp.Head(ctx, c.httpClient, url)
+	res, err := ctxhttp.Head(ctx, c.HTTPClient, url)
 	if err != nil {
 		return 0, fmt.Errorf("ctxhttp.Head(ctx, client, %q): %v", url, err)
 	}
@@ -174,7 +174,7 @@
 	return res.ContentLength, nil
 }
 
-func (c *Client) escapedURL(modulePath, requestedVersion, suffix string) (_ string, err error) {
+func (c *Client) EscapedURL(modulePath, requestedVersion, suffix string) (_ string, err error) {
 	defer derrors.WrapStack(&err, "Client.escapedURL(%q, %q, %q)", modulePath, requestedVersion, suffix)
 
 	if suffix != "info" && suffix != "mod" && suffix != "zip" {
@@ -200,7 +200,7 @@
 func (c *Client) readBody(ctx context.Context, modulePath, requestedVersion, suffix string) (_ []byte, err error) {
 	defer derrors.WrapStack(&err, "Client.readBody(%q, %q, %q)", modulePath, requestedVersion, suffix)
 
-	u, err := c.escapedURL(modulePath, requestedVersion, suffix)
+	u, err := c.EscapedURL(modulePath, requestedVersion, suffix)
 	if err != nil {
 		return nil, err
 	}
@@ -254,9 +254,9 @@
 		return err
 	}
 	if c.disableFetch {
-		req.Header.Set(disableFetchHeader, "true")
+		req.Header.Set(DisableFetchHeader, "true")
 	}
-	r, err := ctxhttp.Do(ctx, c.httpClient, req)
+	r, err := ctxhttp.Do(ctx, c.HTTPClient, req)
 	if err != nil {
 		return fmt.Errorf("ctxhttp.Do(ctx, client, %q): %v", u, err)
 	}
diff --git a/internal/proxy/client_test.go b/internal/proxy/client_test.go
index 5ab2455..7d84c3e 100644
--- a/internal/proxy/client_test.go
+++ b/internal/proxy/client_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package proxy
+package proxy_test
 
 import (
 	"context"
@@ -14,6 +14,8 @@
 
 	"github.com/google/go-cmp/cmp"
 	"golang.org/x/pkgsite/internal/derrors"
+	"golang.org/x/pkgsite/internal/proxy"
+	"golang.org/x/pkgsite/internal/proxy/proxytest"
 	"golang.org/x/pkgsite/internal/testing/sample"
 	"golang.org/x/pkgsite/internal/testing/testhelper"
 	"golang.org/x/pkgsite/internal/version"
@@ -21,7 +23,7 @@
 
 const testTimeout = 5 * time.Second
 
-var testModule = &Module{
+var testModule = &proxytest.Module{
 	ModulePath: sample.ModulePath,
 	Version:    sample.VersionString,
 	Files: map[string]string{
@@ -57,7 +59,7 @@
 
 const uncachedModulePath = "example.com/uncached"
 
-var uncachedModule = &Module{
+var uncachedModule = &proxytest.Module{
 	ModulePath: uncachedModulePath,
 	Version:    sample.VersionString,
 	NotCached:  true,
@@ -67,7 +69,7 @@
 	ctx, cancel := context.WithTimeout(context.Background(), testTimeout)
 	defer cancel()
 
-	testModules := []*Module{
+	testModules := []*proxytest.Module{
 		{
 			ModulePath: sample.ModulePath,
 			Version:    "v1.1.0",
@@ -79,7 +81,7 @@
 			Files:      map[string]string{"bar.go": "package bar\nconst Version = 1.2"},
 		},
 	}
-	client, teardownProxy := SetupTestClient(t, testModules)
+	client, teardownProxy := proxytest.SetupTestClient(t, testModules)
 	defer teardownProxy()
 
 	info, err := client.Info(ctx, sample.ModulePath, version.Latest)
@@ -96,7 +98,7 @@
 	ctx, cancel := context.WithTimeout(context.Background(), testTimeout)
 	defer cancel()
 
-	testModules := []*Module{
+	testModules := []*proxytest.Module{
 		{
 			ModulePath: sample.ModulePath,
 			Version:    "v1.1.0",
@@ -113,7 +115,7 @@
 			Files:      map[string]string{"bar.go": "package bar\nconst Version = 1.3"},
 		},
 	}
-	client, teardownProxy := SetupTestClient(t, testModules)
+	client, teardownProxy := proxytest.SetupTestClient(t, testModules)
 	defer teardownProxy()
 
 	want := []string{"v1.1.0", "v1.2.0"}
@@ -130,7 +132,7 @@
 	ctx, cancel := context.WithTimeout(context.Background(), testTimeout)
 	defer cancel()
 
-	client, teardownProxy := SetupTestClient(t, []*Module{testModule, uncachedModule})
+	client, teardownProxy := proxytest.SetupTestClient(t, []*proxytest.Module{testModule, uncachedModule})
 	defer teardownProxy()
 
 	info, err := client.Info(ctx, sample.ModulePath, sample.VersionString)
@@ -164,11 +166,11 @@
 	ctx, cancel := context.WithTimeout(context.Background(), testTimeout)
 	defer cancel()
 
-	proxyServer := NewServer(nil)
+	proxyServer := proxytest.NewServer(nil)
 	proxyServer.AddRoute(
 		fmt.Sprintf("/%s/@v/%s.info", "module.com/timeout", sample.VersionString),
 		func(w http.ResponseWriter, r *http.Request) { http.Error(w, "fetch timed out", http.StatusNotFound) })
-	client, teardownProxy, err := NewClientForServer(proxyServer)
+	client, teardownProxy, err := proxytest.NewClientForServer(proxyServer)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -197,7 +199,7 @@
 	ctx, cancel := context.WithTimeout(context.Background(), testTimeout)
 	defer cancel()
 
-	client, teardownProxy := SetupTestClient(t, []*Module{testModule})
+	client, teardownProxy := proxytest.SetupTestClient(t, []*proxytest.Module{testModule})
 	defer teardownProxy()
 
 	bytes, err := client.Mod(ctx, sample.ModulePath, sample.VersionString)
@@ -215,7 +217,7 @@
 	ctx, cancel := context.WithTimeout(context.Background(), testTimeout)
 	defer cancel()
 
-	client, teardownProxy := SetupTestClient(t, []*Module{testModule})
+	client, teardownProxy := proxytest.SetupTestClient(t, []*proxytest.Module{testModule})
 	defer teardownProxy()
 
 	zipReader, err := client.Zip(ctx, sample.ModulePath, sample.VersionString)
@@ -254,7 +256,7 @@
 	ctx, cancel := context.WithTimeout(context.Background(), testTimeout)
 	defer cancel()
 
-	client, teardownProxy := SetupTestClient(t, nil)
+	client, teardownProxy := proxytest.SetupTestClient(t, nil)
 	defer teardownProxy()
 
 	if _, err := client.Zip(ctx, sample.ModulePath, sample.VersionString); !errors.Is(err, derrors.NotFound) {
@@ -264,7 +266,7 @@
 
 func TestZipSize(t *testing.T) {
 	t.Run("found", func(t *testing.T) {
-		client, teardownProxy := SetupTestClient(t, []*Module{testModule})
+		client, teardownProxy := proxytest.SetupTestClient(t, []*proxytest.Module{testModule})
 		defer teardownProxy()
 		got, err := client.ZipSize(context.Background(), sample.ModulePath, sample.VersionString)
 		if err != nil {
@@ -276,7 +278,7 @@
 		}
 	})
 	t.Run("not found", func(t *testing.T) {
-		client, teardownProxy := SetupTestClient(t, nil)
+		client, teardownProxy := proxytest.SetupTestClient(t, nil)
 		defer teardownProxy()
 		if _, err := client.ZipSize(context.Background(), sample.ModulePath, sample.VersionString); !errors.Is(err, derrors.NotFound) {
 			t.Errorf("got %v, want %v", err, derrors.NotFound)
@@ -285,7 +287,10 @@
 }
 
 func TestEncodedURL(t *testing.T) {
-	c := &Client{url: "u"}
+	c, err := proxy.New("u")
+	if err != nil {
+		t.Fatal(err)
+	}
 	for _, test := range []struct {
 		path, version, suffix string
 		want                  string // empty => error
@@ -343,7 +348,7 @@
 			"", // only "info" or "zip"
 		},
 	} {
-		got, err := c.escapedURL(test.path, test.version, test.suffix)
+		got, err := c.EscapedURL(test.path, test.version, test.suffix)
 		if got != test.want || (err != nil) != (test.want == "") {
 			t.Errorf("%s, %s, %s: got (%q, %v), want %q", test.path, test.version, test.suffix, got, err, test.want)
 		}
diff --git a/internal/proxy/module.go b/internal/proxy/proxytest/module.go
similarity index 96%
rename from internal/proxy/module.go
rename to internal/proxy/proxytest/module.go
index 4351d82..1aef634 100644
--- a/internal/proxy/module.go
+++ b/internal/proxy/proxytest/module.go
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package proxy
+// Package proxytest supports testing with the proxy.
+package proxytest
 
 import "fmt"
 
diff --git a/internal/proxy/test_helper.go b/internal/proxy/proxytest/proxytest.go
similarity index 89%
rename from internal/proxy/test_helper.go
rename to internal/proxy/proxytest/proxytest.go
index ff2a23f..8cf10a9 100644
--- a/internal/proxy/test_helper.go
+++ b/internal/proxy/proxytest/proxytest.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package proxy
+package proxytest
 
 import (
 	"fmt"
@@ -11,6 +11,7 @@
 	"testing"
 
 	"golang.org/x/mod/modfile"
+	"golang.org/x/pkgsite/internal/proxy"
 	"golang.org/x/pkgsite/internal/testing/testhelper"
 	"golang.org/x/tools/txtar"
 )
@@ -20,7 +21,7 @@
 //
 // It returns a function for tearing down the proxy after the test is completed
 // and a Client for interacting with the test proxy.
-func SetupTestClient(t *testing.T, modules []*Module) (*Client, func()) {
+func SetupTestClient(t *testing.T, modules []*Module) (*proxy.Client, func()) {
 	t.Helper()
 	s := NewServer(modules)
 	client, serverClose, err := NewClientForServer(s)
@@ -32,14 +33,14 @@
 
 // NewClientForServer starts serving proxyMux locally. It returns a client to the
 // server and a function to shut down the server.
-func NewClientForServer(s *Server) (*Client, func(), error) {
+func NewClientForServer(s *Server) (*proxy.Client, func(), error) {
 	// override client.httpClient to skip TLS verification
-	httpClient, proxy, serverClose := testhelper.SetupTestClientAndServer(s.mux)
-	client, err := New(proxy.URL)
+	httpClient, prox, serverClose := testhelper.SetupTestClientAndServer(s.mux)
+	client, err := proxy.New(prox.URL)
 	if err != nil {
 		return nil, nil, err
 	}
-	client.httpClient = httpClient
+	client.HTTPClient = httpClient
 	return client, serverClose, nil
 }
 
diff --git a/internal/proxy/server.go b/internal/proxy/proxytest/server.go
similarity index 97%
rename from internal/proxy/server.go
rename to internal/proxy/proxytest/server.go
index 1e56af2..7b020fc 100644
--- a/internal/proxy/server.go
+++ b/internal/proxy/proxytest/server.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package proxy
+package proxytest
 
 import (
 	"bytes"
@@ -14,6 +14,7 @@
 	"time"
 
 	"golang.org/x/mod/semver"
+	"golang.org/x/pkgsite/internal/proxy"
 	"golang.org/x/pkgsite/internal/testing/testhelper"
 	"golang.org/x/pkgsite/internal/version"
 )
@@ -42,7 +43,7 @@
 func (s *Server) handleInfo(modulePath, resolvedVersion string, uncached bool) {
 	urlPath := fmt.Sprintf("/%s/@v/%s.info", modulePath, resolvedVersion)
 	s.mux.HandleFunc(urlPath, func(w http.ResponseWriter, r *http.Request) {
-		if uncached && r.Header.Get(disableFetchHeader) == "true" {
+		if uncached && r.Header.Get(proxy.DisableFetchHeader) == "true" {
 			http.Error(w, "not found: temporarily unavailable", http.StatusGone)
 			return
 		}
diff --git a/internal/proxydatasource/datasource_test.go b/internal/proxydatasource/datasource_test.go
index 4b025bd..9c30b30 100644
--- a/internal/proxydatasource/datasource_test.go
+++ b/internal/proxydatasource/datasource_test.go
@@ -19,23 +19,23 @@
 	"golang.org/x/pkgsite/internal/derrors"
 	"golang.org/x/pkgsite/internal/godoc/dochtml"
 	"golang.org/x/pkgsite/internal/licenses"
-	"golang.org/x/pkgsite/internal/proxy"
+	"golang.org/x/pkgsite/internal/proxy/proxytest"
 	"golang.org/x/pkgsite/internal/testing/sample"
 	"golang.org/x/pkgsite/internal/version"
 )
 
-var testModules []*proxy.Module
+var testModules []*proxytest.Module
 
 func TestMain(m *testing.M) {
 	dochtml.LoadTemplates(template.TrustedSourceFromConstant("../../static/doc"))
-	testModules = proxy.LoadTestModules("../proxy/testdata")
+	testModules = proxytest.LoadTestModules("../proxy/testdata")
 	licenses.OmitExceptions = true
 	os.Exit(m.Run())
 }
 
 func setup(t *testing.T) (context.Context, *DataSource, func()) {
 	t.Helper()
-	client, teardownProxy := proxy.SetupTestClient(t, testModules)
+	client, teardownProxy := proxytest.SetupTestClient(t, testModules)
 	ctx, cancel := context.WithTimeout(context.Background(), 40*time.Second)
 	return ctx, NewForTesting(client), func() {
 		teardownProxy()
@@ -237,7 +237,7 @@
 
 func TestGetLatestInfo(t *testing.T) {
 	t.Helper()
-	testModules := []*proxy.Module{
+	testModules := []*proxytest.Module{
 		{
 			ModulePath: "foo.com/bar",
 			Version:    "v1.1.0",
@@ -270,7 +270,7 @@
 			ModulePath: "incompatible.com/bar/v3",
 		},
 	}
-	client, teardownProxy := proxy.SetupTestClient(t, testModules)
+	client, teardownProxy := proxytest.SetupTestClient(t, testModules)
 	defer teardownProxy()
 	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
 	defer cancel()
diff --git a/internal/testing/integration/frontend_test.go b/internal/testing/integration/frontend_test.go
index 09e0491..1183d4e 100644
--- a/internal/testing/integration/frontend_test.go
+++ b/internal/testing/integration/frontend_test.go
@@ -20,6 +20,7 @@
 	"golang.org/x/pkgsite/internal/middleware"
 	"golang.org/x/pkgsite/internal/postgres"
 	"golang.org/x/pkgsite/internal/proxy"
+	"golang.org/x/pkgsite/internal/proxy/proxytest"
 	"golang.org/x/pkgsite/internal/queue"
 	"golang.org/x/pkgsite/internal/source"
 	"golang.org/x/pkgsite/internal/testing/htmlcheck"
@@ -72,9 +73,9 @@
 
 // TODO(https://github.com/golang/go/issues/40098): factor out this code reduce
 // duplication
-func setupQueue(ctx context.Context, t *testing.T, proxyModules []*proxy.Module, experimentNames ...string) (queue.Queue, func()) {
+func setupQueue(ctx context.Context, t *testing.T, proxyModules []*proxytest.Module, experimentNames ...string) (queue.Queue, func()) {
 	cctx, cancel := context.WithCancel(ctx)
-	proxyClient, teardown := proxy.SetupTestClient(t, proxyModules)
+	proxyClient, teardown := proxytest.SetupTestClient(t, proxyModules)
 	sourceClient := source.NewClient(1 * time.Second)
 	q := queue.NewInMemory(cctx, 1, experimentNames,
 		func(ctx context.Context, mpath, version string) (_ int, err error) {
@@ -86,9 +87,9 @@
 	}
 }
 
-func processVersions(ctx context.Context, t *testing.T, testModules []*proxy.Module) {
+func processVersions(ctx context.Context, t *testing.T, testModules []*proxytest.Module) {
 	t.Helper()
-	proxyClient, teardown := proxy.SetupTestClient(t, testModules)
+	proxyClient, teardown := proxytest.SetupTestClient(t, testModules)
 	defer teardown()
 
 	for _, tm := range testModules {
@@ -96,7 +97,7 @@
 	}
 }
 
-func fetchAndInsertModule(ctx context.Context, t *testing.T, tm *proxy.Module, proxyClient *proxy.Client) {
+func fetchAndInsertModule(ctx context.Context, t *testing.T, tm *proxytest.Module, proxyClient *proxy.Client) {
 	sourceClient := source.NewClient(1 * time.Second)
 	res := fetch.FetchModule(ctx, tm.ModulePath, tm.Version, proxyClient, sourceClient)
 	defer res.Defer()
diff --git a/internal/testing/integration/integration_test.go b/internal/testing/integration/integration_test.go
index 3ee6dcb..dca279e 100644
--- a/internal/testing/integration/integration_test.go
+++ b/internal/testing/integration/integration_test.go
@@ -23,16 +23,17 @@
 	"golang.org/x/pkgsite/internal/middleware"
 	"golang.org/x/pkgsite/internal/postgres"
 	"golang.org/x/pkgsite/internal/proxy"
+	"golang.org/x/pkgsite/internal/proxy/proxytest"
 )
 
 var (
 	testDB      *postgres.DB
-	testModules []*proxy.Module
+	testModules []*proxytest.Module
 )
 
 func TestMain(m *testing.M) {
 	dochtml.LoadTemplates(template.TrustedSourceFromConstant("../../../static/doc"))
-	testModules = proxy.LoadTestModules("../../proxy/testdata")
+	testModules = proxytest.LoadTestModules("../../proxy/testdata")
 	postgres.RunDBTests("discovery_integration_test", m, &testDB)
 }
 
@@ -101,7 +102,7 @@
 	// Process a newer version of a module, and verify that the cache has been invalidated.
 	modulePath := "example.com/single"
 	version := "v1.2.3"
-	proxyServer.AddModule(proxy.FindModule(testModules, modulePath, "v1.0.0").ChangeVersion(version))
+	proxyServer.AddModule(proxytest.FindModule(testModules, modulePath, "v1.0.0").ChangeVersion(version))
 	_, _, err := fetcher.FetchAndUpdateState(ctx, modulePath, version, "test")
 	if err != nil {
 		t.Fatal(err)
@@ -151,10 +152,10 @@
 	return body, nil
 }
 
-func setupProxyAndIndex(t *testing.T) (*proxy.Client, *proxy.Server, *index.Client, func()) {
+func setupProxyAndIndex(t *testing.T) (*proxy.Client, *proxytest.Server, *index.Client, func()) {
 	t.Helper()
-	proxyServer := proxy.NewServer(testModules)
-	proxyClient, teardownProxy, err := proxy.NewClientForServer(proxyServer)
+	proxyServer := proxytest.NewServer(testModules)
+	proxyClient, teardownProxy, err := proxytest.NewClientForServer(proxyServer)
 	if err != nil {
 		t.Fatal(err)
 	}
diff --git a/internal/worker/fetch_test.go b/internal/worker/fetch_test.go
index e771e57..de6f51e 100644
--- a/internal/worker/fetch_test.go
+++ b/internal/worker/fetch_test.go
@@ -17,7 +17,7 @@
 	"golang.org/x/pkgsite/internal/godoc"
 	"golang.org/x/pkgsite/internal/licenses"
 	"golang.org/x/pkgsite/internal/postgres"
-	"golang.org/x/pkgsite/internal/proxy"
+	"golang.org/x/pkgsite/internal/proxy/proxytest"
 	"golang.org/x/pkgsite/internal/source"
 	"golang.org/x/pkgsite/internal/stdlib"
 	"golang.org/x/pkgsite/internal/testing/sample"
@@ -46,7 +46,7 @@
 	stdlib.UseTestData = true
 	defer func() { stdlib.UseTestData = false }()
 
-	proxyClient, teardownProxy := proxy.SetupTestClient(t, testModules)
+	proxyClient, teardownProxy := proxytest.SetupTestClient(t, testModules)
 	defer teardownProxy()
 
 	myModuleV100 := &internal.Unit{
@@ -377,7 +377,7 @@
 	// test confirms that that feature works.
 	ctx := context.Background()
 	defer postgres.ResetTestDB(testDB, t)
-	proxyServer := proxy.NewServer([]*proxy.Module{
+	proxyServer := proxytest.NewServer([]*proxytest.Module{
 		{
 			ModulePath: "m.com",
 			Version:    "v2.0.0+incompatible",
@@ -389,7 +389,7 @@
 			Files:      map[string]string{"a.go": "package a"},
 		},
 	})
-	proxyClient, teardownProxy, err := proxy.NewClientForServer(proxyServer)
+	proxyClient, teardownProxy, err := proxytest.NewClientForServer(proxyServer)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -419,7 +419,7 @@
 
 func TestFetchAndUpdateLatest(t *testing.T) {
 	ctx := context.Background()
-	prox, teardown := proxy.SetupTestClient(t, testModules)
+	prox, teardown := proxytest.SetupTestClient(t, testModules)
 	defer teardown()
 
 	const modulePath = "example.com/retractions"
diff --git a/internal/worker/fetcherror_test.go b/internal/worker/fetcherror_test.go
index 9381a6e..2a4af43 100644
--- a/internal/worker/fetcherror_test.go
+++ b/internal/worker/fetcherror_test.go
@@ -23,6 +23,7 @@
 	"golang.org/x/pkgsite/internal/godoc"
 	"golang.org/x/pkgsite/internal/postgres"
 	"golang.org/x/pkgsite/internal/proxy"
+	"golang.org/x/pkgsite/internal/proxy/proxytest"
 	"golang.org/x/pkgsite/internal/source"
 	"golang.org/x/pkgsite/internal/testing/sample"
 	"golang.org/x/pkgsite/internal/testing/testhelper"
@@ -35,7 +36,7 @@
 	defer cancel()
 	defer postgres.ResetTestDB(testDB, t)
 
-	proxyClient, teardown := proxy.SetupTestClient(t, []*proxy.Module{
+	proxyClient, teardown := proxytest.SetupTestClient(t, []*proxytest.Module{
 		{
 			ModulePath: sample.ModulePath,
 			Version:    sample.VersionString,
@@ -50,11 +51,11 @@
 	fetchAndCheckStatus(ctx, t, proxyClient, sample.ModulePath, sample.VersionString, http.StatusOK)
 
 	// Take down the module, by having the proxy serve a 404/410 for it.
-	proxyServer := proxy.NewServer([]*proxy.Module{})
+	proxyServer := proxytest.NewServer([]*proxytest.Module{})
 	proxyServer.AddRoute(
 		fmt.Sprintf("/%s/@v/%s.info", sample.ModulePath, sample.VersionString),
 		func(w http.ResponseWriter, r *http.Request) { http.Error(w, "taken down", http.StatusGone) })
-	proxyClient, teardownProxy2, err := proxy.NewClientForServer(proxyServer)
+	proxyClient, teardownProxy2, err := proxytest.NewClientForServer(proxyServer)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -97,7 +98,7 @@
 
 	defer postgres.ResetTestDB(testDB, t)
 
-	proxyClient, teardownProxy := proxy.SetupTestClient(t, nil)
+	proxyClient, teardownProxy := proxytest.SetupTestClient(t, nil)
 	defer teardownProxy()
 
 	if err := testDB.InsertExcludedPrefix(ctx, sample.ModulePath, "user", "for testing"); err != nil {
@@ -116,7 +117,7 @@
 		modulePath = buildConstraintsModulePath
 		version    = "badversion"
 	)
-	proxyClient, teardownProxy := proxy.SetupTestClient(t, testModules)
+	proxyClient, teardownProxy := proxytest.SetupTestClient(t, testModules)
 	defer teardownProxy()
 	fetchAndCheckStatus(ctx, t, proxyClient, modulePath, version, http.StatusNotFound)
 }
@@ -128,7 +129,7 @@
 
 	defer postgres.ResetTestDB(testDB, t)
 
-	proxyClient, teardownProxy := proxy.SetupTestClient(t, testModules)
+	proxyClient, teardownProxy := proxytest.SetupTestClient(t, testModules)
 	defer teardownProxy()
 
 	fetchAndCheckStatus(ctx, t, proxyClient, buildConstraintsModulePath, buildConstraintsVersion, hasIncompletePackagesCode)
@@ -156,7 +157,7 @@
 	defer postgres.ResetTestDB(testDB, t)
 
 	const goModPath = "other"
-	proxyClient, teardownProxy := proxy.SetupTestClient(t, []*proxy.Module{
+	proxyClient, teardownProxy := proxytest.SetupTestClient(t, []*proxytest.Module{
 		{
 			ModulePath: sample.ModulePath,
 			Version:    sample.VersionString,
@@ -185,7 +186,7 @@
 		olderVersion    = "v0.9.0"
 	)
 
-	proxyClient, teardownProxy := proxy.SetupTestClient(t, []*proxy.Module{
+	proxyClient, teardownProxy := proxytest.SetupTestClient(t, []*proxytest.Module{
 		{
 			// mismatched version; will cause deletion
 			ModulePath: sample.ModulePath,
@@ -234,7 +235,7 @@
 		bigFile.WriteString("// All work and no play makes Jack a dull boy.\n")
 	}
 	badModule["bar/bar.go"] = bigFile.String()
-	proxyClient, teardownProxy := proxy.SetupTestClient(t, []*proxy.Module{
+	proxyClient, teardownProxy := proxytest.SetupTestClient(t, []*proxytest.Module{
 		{
 			ModulePath: sample.ModulePath,
 			Version:    sample.VersionString,
@@ -252,7 +253,7 @@
 func TestFetchAndUpdateState_Timeout(t *testing.T) {
 	defer postgres.ResetTestDB(testDB, t)
 
-	proxyClient, teardownProxy := proxy.SetupTestClient(t, nil)
+	proxyClient, teardownProxy := proxytest.SetupTestClient(t, nil)
 	defer teardownProxy()
 
 	ctx, cancel := context.WithTimeout(context.Background(), 0)
@@ -267,13 +268,13 @@
 	defer cancel()
 	defer postgres.ResetTestDB(testDB, t)
 
-	proxyServer := proxy.NewServer(nil)
+	proxyServer := proxytest.NewServer(nil)
 	proxyServer.AddRoute(
 		fmt.Sprintf("/%s/@v/%s.info", sample.ModulePath, sample.VersionString),
 		func(w http.ResponseWriter, r *http.Request) {
 			http.Error(w, "not found: fetch timed out", http.StatusNotFound)
 		})
-	proxyClient, teardownProxy, err := proxy.NewClientForServer(proxyServer)
+	proxyClient, teardownProxy, err := proxytest.NewClientForServer(proxyServer)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -317,7 +318,7 @@
 		b.WriteString("}\n")
 		trimmedModule["baz/baz.go"] = b.String()
 	}
-	proxyClient, teardownProxy := proxy.SetupTestClient(t, []*proxy.Module{
+	proxyClient, teardownProxy := proxytest.SetupTestClient(t, []*proxytest.Module{
 		{
 			ModulePath: sample.ModulePath,
 			Version:    sample.VersionString,
diff --git a/internal/worker/refetch_test.go b/internal/worker/refetch_test.go
index 5f9e294..ff7dc6b 100644
--- a/internal/worker/refetch_test.go
+++ b/internal/worker/refetch_test.go
@@ -16,7 +16,7 @@
 	"golang.org/x/pkgsite/internal/derrors"
 	"golang.org/x/pkgsite/internal/licenses"
 	"golang.org/x/pkgsite/internal/postgres"
-	"golang.org/x/pkgsite/internal/proxy"
+	"golang.org/x/pkgsite/internal/proxy/proxytest"
 	"golang.org/x/pkgsite/internal/source"
 	"golang.org/x/pkgsite/internal/testing/sample"
 	"golang.org/x/pkgsite/internal/testing/testhelper"
@@ -51,7 +51,7 @@
 
 	// First fetch and insert a version containing package foo, and verify that
 	// foo can be retrieved.
-	proxyClient, teardownProxy := proxy.SetupTestClient(t, []*proxy.Module{
+	proxyClient, teardownProxy := proxytest.SetupTestClient(t, []*proxytest.Module{
 		{
 			ModulePath: modulePath,
 			Version:    version,
@@ -70,7 +70,7 @@
 	}
 
 	// Now re-fetch and verify that contents were overwritten.
-	proxyClient, teardownProxy = proxy.SetupTestClient(t, []*proxy.Module{
+	proxyClient, teardownProxy = proxytest.SetupTestClient(t, []*proxytest.Module{
 		{
 			ModulePath: sample.ModulePath,
 			Version:    version,
@@ -148,7 +148,7 @@
 	}
 
 	// Now re-fetch and verify that contents were overwritten.
-	proxyClient, teardownProxy = proxy.SetupTestClient(t, []*proxy.Module{
+	proxyClient, teardownProxy = proxytest.SetupTestClient(t, []*proxytest.Module{
 		{
 			ModulePath: modulePath,
 			Version:    version,
diff --git a/internal/worker/server_test.go b/internal/worker/server_test.go
index 8b9f8b2..c439a35 100644
--- a/internal/worker/server_test.go
+++ b/internal/worker/server_test.go
@@ -24,7 +24,7 @@
 	"golang.org/x/pkgsite/internal/godoc/dochtml"
 	"golang.org/x/pkgsite/internal/index"
 	"golang.org/x/pkgsite/internal/postgres"
-	"golang.org/x/pkgsite/internal/proxy"
+	"golang.org/x/pkgsite/internal/proxy/proxytest"
 	"golang.org/x/pkgsite/internal/queue"
 	"golang.org/x/pkgsite/internal/source"
 	"golang.org/x/pkgsite/internal/testing/sample"
@@ -35,13 +35,13 @@
 var (
 	testDB      *postgres.DB
 	httpClient  *http.Client
-	testModules []*proxy.Module
+	testModules []*proxytest.Module
 )
 
 func TestMain(m *testing.M) {
 	httpClient = &http.Client{Transport: fakeTransport{}}
 	dochtml.LoadTemplates(template.TrustedSourceFromConstant("../../static/doc"))
-	testModules = proxy.LoadTestModules("../proxy/testdata")
+	testModules = proxytest.LoadTestModules("../proxy/testdata")
 	postgres.RunDBTests("discovery_worker_test", m, &testDB)
 }
 
@@ -76,7 +76,7 @@
 			Timestamp: start.Add(time.Second),
 			Version:   "v0.0.1",
 		}
-		fooProxy = &proxy.Module{
+		fooProxy = &proxytest.Module{
 			ModulePath: fooIndex.Path,
 			Version:    fooIndex.Version,
 			Files: map[string]string{
@@ -84,7 +84,7 @@
 				"foo.go": "package foo\nconst Foo = \"Foo\"",
 			},
 		}
-		barProxy = &proxy.Module{
+		barProxy = &proxytest.Module{
 			ModulePath: barIndex.Path,
 			Version:    barIndex.Version,
 			Files: map[string]string{
@@ -125,7 +125,7 @@
 	tests := []struct {
 		label    string
 		index    []*internal.IndexVersion
-		proxy    []*proxy.Module
+		proxy    []*proxytest.Module
 		requests []*http.Request
 		wantFoo  *internal.ModuleVersionState
 		wantBar  *internal.ModuleVersionState
@@ -133,7 +133,7 @@
 		{
 			label: "poll only",
 			index: []*internal.IndexVersion{fooIndex, barIndex},
-			proxy: []*proxy.Module{fooProxy, barProxy},
+			proxy: []*proxytest.Module{fooProxy, barProxy},
 			requests: []*http.Request{
 				httptest.NewRequest("POST", "/poll", nil),
 			},
@@ -143,7 +143,7 @@
 		{
 			label: "full fetch",
 			index: []*internal.IndexVersion{fooIndex, barIndex},
-			proxy: []*proxy.Module{fooProxy, barProxy},
+			proxy: []*proxytest.Module{fooProxy, barProxy},
 			requests: []*http.Request{
 				httptest.NewRequest("POST", "/poll", nil),
 				httptest.NewRequest("POST", "/enqueue", nil),
@@ -153,7 +153,7 @@
 		}, {
 			label: "partial fetch",
 			index: []*internal.IndexVersion{fooIndex, barIndex},
-			proxy: []*proxy.Module{fooProxy, barProxy},
+			proxy: []*proxytest.Module{fooProxy, barProxy},
 			requests: []*http.Request{
 				httptest.NewRequest("POST", "/poll?limit=1", nil),
 				httptest.NewRequest("POST", "/enqueue", nil),
@@ -162,7 +162,7 @@
 		}, {
 			label: "fetch with errors",
 			index: []*internal.IndexVersion{fooIndex, barIndex},
-			proxy: []*proxy.Module{fooProxy},
+			proxy: []*proxytest.Module{fooProxy},
 			requests: []*http.Request{
 				httptest.NewRequest("POST", "/poll", nil),
 				httptest.NewRequest("POST", "/enqueue", nil),
@@ -176,7 +176,7 @@
 			indexClient, teardownIndex := index.SetupTestIndex(t, test.index)
 			defer teardownIndex()
 
-			proxyClient, teardownProxy := proxy.SetupTestClient(t, test.proxy)
+			proxyClient, teardownProxy := proxytest.SetupTestClient(t, test.proxy)
 			defer teardownProxy()
 			defer postgres.ResetTestDB(testDB, t)
 			f := &Fetcher{proxyClient, source.NewClient(sourceTimeout), testDB, nil}