internal/middleware: remove LegacyQuota

Change-Id: I4cdb402980ae6b70ddead303ff647959ea63f0a9
Reviewed-on: https://go-review.googlesource.com/c/pkgsite/+/277814
Trust: Jonathan Amsterdam <jba@google.com>
Run-TryBot: Jonathan Amsterdam <jba@google.com>
TryBot-Result: kokoro <noreply+kokoro@google.com>
Reviewed-by: Jamal Carvalho <jamal@golang.org>
diff --git a/go.mod b/go.mod
index f9829e5..8c954f1 100644
--- a/go.mod
+++ b/go.mod
@@ -21,7 +21,6 @@
 	github.com/go-redis/redis_rate/v9 v9.0.2
 	github.com/gogo/protobuf v1.3.0 // indirect
 	github.com/golang-migrate/migrate/v4 v4.6.2
-	github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e
 	github.com/golang/protobuf v1.4.2
 	github.com/gomodule/redigo v2.0.0+incompatible // indirect
 	github.com/google/go-cmp v0.5.2
diff --git a/internal/middleware/quota.go b/internal/middleware/quota.go
index 3afa3e2..a260182 100644
--- a/internal/middleware/quota.go
+++ b/internal/middleware/quota.go
@@ -13,18 +13,15 @@
 	"net"
 	"net/http"
 	"strings"
-	"sync"
 	"time"
 
 	"github.com/go-redis/redis/v8"
 	rrate "github.com/go-redis/redis_rate/v9"
-	"github.com/golang/groupcache/lru"
 	"go.opencensus.io/stats"
 	"go.opencensus.io/stats/view"
 	"go.opencensus.io/tag"
 	"golang.org/x/pkgsite/internal/config"
 	"golang.org/x/pkgsite/internal/log"
-	"golang.org/x/time/rate"
 )
 
 var (
@@ -44,68 +41,6 @@
 	}
 )
 
-// LegacyQuota implements a simple IP-based rate limiter. Each set of incoming IP
-// addresses with the same low-order byte gets qps requests per second, with the
-// given burst.
-// Information is kept in an LRU cache of size maxEntries.
-//
-// If a request is disallowed, a 429 (TooManyRequests) will be served.
-func LegacyQuota(settings config.QuotaSettings) Middleware {
-	var mu sync.Mutex
-	cache := lru.New(settings.MaxEntries)
-
-	return func(h http.Handler) http.Handler {
-		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-			authVal := r.Header.Get(config.BypassQuotaAuthHeader)
-			for _, wantVal := range settings.AuthValues {
-				if authVal == wantVal {
-					recordQuotaMetric(r.Context(), "bypassed")
-					log.Infof(r.Context(), "Quota: accepting %q", authVal)
-					h.ServeHTTP(w, r)
-					return
-				}
-			}
-			header := r.Header.Get("X-Godoc-Forwarded-For")
-			if header == "" {
-				header = r.Header.Get("X-Forwarded-For")
-			}
-			key := ipKey(header)
-			// key is empty if we couldn't parse an IP, or there is no IP.
-			// Fail open in this case: allow serving.
-			var limiter *rate.Limiter
-			if key != "" {
-				mu.Lock()
-				if v, ok := cache.Get(key); ok {
-					limiter = v.(*rate.Limiter)
-				} else {
-					limiter = rate.NewLimiter(rate.Limit(settings.QPS), settings.Burst)
-					cache.Add(key, limiter)
-				}
-				mu.Unlock()
-			}
-			blocked := limiter != nil && !limiter.Allow()
-			var mv string
-			switch {
-			case header == "":
-				mv = "no header"
-			case key == "":
-				mv = "bad header"
-			case blocked:
-				mv = "blocked"
-			default:
-				mv = "allowed"
-			}
-			recordQuotaMetric(r.Context(), mv)
-			if blocked && settings.RecordOnly != nil && !*settings.RecordOnly {
-				const tmr = http.StatusTooManyRequests
-				http.Error(w, http.StatusText(tmr), tmr)
-				return
-			}
-			h.ServeHTTP(w, r)
-		})
-	}
-}
-
 func recordQuotaMetric(ctx context.Context, blocked string) {
 	stats.RecordWithTags(ctx, []tag.Mutator{
 		tag.Upsert(keyQuotaBlocked, blocked),
diff --git a/internal/middleware/quota_test.go b/internal/middleware/quota_test.go
index a305df1..e910544 100644
--- a/internal/middleware/quota_test.go
+++ b/internal/middleware/quota_test.go
@@ -7,144 +7,14 @@
 import (
 	"context"
 	"fmt"
-	"net/http"
-	"net/http/httptest"
 	"testing"
 	"time"
 
 	"github.com/alicebob/miniredis/v2"
 	"github.com/go-redis/redis/v8"
-	"github.com/google/go-cmp/cmp"
 	"go.opencensus.io/stats/view"
-	"golang.org/x/pkgsite/internal/config"
 )
 
-func TestLegacyQuota(t *testing.T) {
-	mw := LegacyQuota(config.QuotaSettings{QPS: 1, Burst: 2, MaxEntries: 1, RecordOnly: boolptr(false)})
-	var npass int
-	h := func(w http.ResponseWriter, r *http.Request) {
-		npass++
-	}
-	ts := httptest.NewServer(mw(http.HandlerFunc(h)))
-	defer ts.Close()
-	c := ts.Client()
-	view.Register(QuotaResultCount)
-	defer view.Unregister(QuotaResultCount)
-
-	check := func(msg string, nwant int) {
-		npass = 0
-		for i := 0; i < 5; i++ {
-			req, err := http.NewRequest("GET", ts.URL, nil)
-			if err != nil {
-				t.Fatal(err)
-			}
-			req.Header.Add("X-Forwarded-For", "1.2.3.4, and more")
-			res, err := c.Do(req)
-			if err != nil {
-				t.Fatalf("%s: %v", msg, err)
-			}
-			res.Body.Close()
-			want := http.StatusOK
-			if i >= nwant {
-				want = http.StatusTooManyRequests
-			}
-			if got := res.StatusCode; got != want {
-				t.Errorf("%s, #%d: got %d, want %d", msg, i, got, want)
-			}
-		}
-		if npass != nwant {
-			t.Errorf("%s: got %d requests to pass, want %d", msg, npass, nwant)
-		}
-	}
-
-	// When making multiple requests in quick succession from the same IP,
-	// only the first two get through; the rest are blocked.
-	check("before", 2)
-	// After a second (and a bit more), we should have one token back, meaning
-	// we can serve one request.
-	time.Sleep(1100 * time.Millisecond)
-	check("after", 1)
-
-	// Check the metric.
-	got := collectViewData(t)
-	want := map[bool]int{true: 7, false: 3} // only 3 requests of the ten we sent get through.
-	if diff := cmp.Diff(want, got); diff != "" {
-		t.Errorf("mismatch (-want +got):\n%s", diff)
-	}
-}
-
-func TestLegacyQuotaRecordOnly(t *testing.T) {
-	// Like TestQuota, but with in RecordOnly mode nothing is actually blocked.
-	mw := LegacyQuota(config.QuotaSettings{QPS: 1, Burst: 2, MaxEntries: 1, RecordOnly: boolptr(true)})
-	npass := 0
-	h := func(w http.ResponseWriter, r *http.Request) {
-		npass++
-	}
-	ts := httptest.NewServer(mw(http.HandlerFunc(h)))
-	defer ts.Close()
-	c := ts.Client()
-	view.Register(QuotaResultCount)
-	defer view.Unregister(QuotaResultCount)
-
-	const nreq = 100
-	for i := 0; i < nreq; i++ {
-		req, err := http.NewRequest("GET", ts.URL, nil)
-		if err != nil {
-			t.Fatal(err)
-		}
-		req.Header.Add("X-Forwarded-For", "1.2.3.4, and more")
-		res, err := c.Do(req)
-		if err != nil {
-			t.Fatal(err)
-		}
-		res.Body.Close()
-	}
-	if npass != nreq {
-		t.Errorf("%d passed, want %d", npass, nreq)
-	}
-	got := collectViewData(t)
-	want := map[bool]int{true: nreq - 2, false: 2} // record as if blocking occurred
-	if diff := cmp.Diff(want, got); diff != "" {
-		t.Errorf("mismatch (-want +got):\n%s", diff)
-	}
-}
-
-func TestLegacyQuotaBadKey(t *testing.T) {
-	// Verify that invalid IP addresses are not blocked.
-	mw := LegacyQuota(config.QuotaSettings{QPS: 1, Burst: 2, MaxEntries: 1, RecordOnly: boolptr(true)})
-	npass := 0
-	h := func(w http.ResponseWriter, r *http.Request) {
-		npass++
-	}
-	ts := httptest.NewServer(mw(http.HandlerFunc(h)))
-	defer ts.Close()
-	c := ts.Client()
-	view.Register(QuotaResultCount)
-	defer view.Unregister(QuotaResultCount)
-
-	const nreq = 100
-	for i := 0; i < nreq; i++ {
-		req, err := http.NewRequest("GET", ts.URL, nil)
-		if err != nil {
-			t.Fatal(err)
-		}
-		req.Header.Add("X-Forwarded-For", "not.a.valid.ip, and more")
-		res, err := c.Do(req)
-		if err != nil {
-			t.Fatal(err)
-		}
-		res.Body.Close()
-	}
-	if npass != nreq {
-		t.Errorf("%d passed, want %d", npass, nreq)
-	}
-	got := collectViewData(t)
-	want := map[bool]int{false: nreq} // no blocking occurred
-	if diff := cmp.Diff(want, got); diff != "" {
-		t.Errorf("mismatch (-want +got):\n%s", diff)
-	}
-}
-
 func collectViewData(t *testing.T) map[bool]int {
 	m := map[bool]int{}
 	rows, err := view.RetrieveData(QuotaResultCount.Name)