Skip to content

Commit

Permalink
Remove rate limiting
Browse files Browse the repository at this point in the history
  • Loading branch information
lewislbr committed May 24, 2024
1 parent a004ec1 commit ebe254f
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 91 deletions.
15 changes: 0 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ GSS (Go serve SPA) is a containerized web server for single-page applications wr
- Optimized for single-page apps.
- Automatically serves pre-compressed brotli and gzip files if available.
- Sensible default cache configuration.
- Configurable rate limiter.
- Configurable response headers.
- Optional out-of-the-box metrics.
- Deployable as a container.
Expand Down Expand Up @@ -135,20 +134,6 @@ Enables metrics collection and exposes an endpoint at `:<metricsPort>/metrics`.
> metrics: true
> ```
### Rate limit per minute: `rateLimit`
##### string: integer
Configures the rate limit per minute per IP using a memory store. 15 by default.
> Example:
>
> ```yaml
> # gss.yaml
>
> rateLimit: 10
> ```
## Contributing
This project started as a way to learn and to solve a need I had. If you think it can be improved in any way, you are very welcome to contribute!
31 changes: 7 additions & 24 deletions gss.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ import (
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"github.com/sethvargo/go-limiter/httplimit"
"github.com/sethvargo/go-limiter/memorystore"
"gopkg.in/yaml.v2"
)

Expand Down Expand Up @@ -50,11 +48,10 @@ func setUpLogger() {
}

type config struct {
FilesPort int `yaml:"filesPort,omitempty"`
MetricsPort int `yaml:"metricsPort,omitempty"`
ResponseHeaders map[string]string `yaml:"headers,omitempty"`
MetricsEnabled bool `yaml:"metrics,omitempty"`
RateLimitPerMinute int `yaml:"rateLimit,omitempty"`
FilesPort int `yaml:"filesPort,omitempty"`
MetricsPort int `yaml:"metricsPort,omitempty"`
ResponseHeaders map[string]string `yaml:"headers,omitempty"`
MetricsEnabled bool `yaml:"metrics,omitempty"`
}

func newConfig() *config {
Expand All @@ -65,8 +62,7 @@ func newConfig() *config {
ResponseHeaders: map[string]string{
"Server": "GSS",
},
MetricsEnabled: false,
RateLimitPerMinute: 15,
MetricsEnabled: false,
}
}

Expand Down Expand Up @@ -109,23 +105,10 @@ func newFileServer(cfg *config, metrics *metrics) *fileServer {
}

func (f *fileServer) init() *fileServer {
store, err := memorystore.New(&memorystore.Config{
Tokens: uint64(f.Config.RateLimitPerMinute),
Interval: time.Minute,
})
if err != nil {
log.Fatal().Msgf("Error creating rate limit store: %v", err)
}

rateLimit, err := httplimit.NewMiddleware(store, httplimit.IPKeyFunc())
if err != nil {
log.Fatal().Msgf("Error creating rate limit middleware: %v", err)
}

if f.Config.MetricsEnabled {
f.Server.Handler = metricsMiddleware(f.Metrics)(rateLimit.Handle(f.setHeaders((f.serveSPA()))))
f.Server.Handler = metricsMiddleware(f.Metrics)(f.setHeaders((f.serveSPA())))
} else {
f.Server.Handler = rateLimit.Handle(f.setHeaders((f.serveSPA())))
f.Server.Handler = f.setHeaders((f.serveSPA()))
}

return f
Expand Down
64 changes: 12 additions & 52 deletions gss_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ func TestGSS(t *testing.T) {
ResponseHeaders: map[string]string{
"X-Test": "test",
},
RateLimitPerMinute: 100,
}
fileServer := newFileServer(cfg, metrics).init()
w := httptest.NewRecorder()
Expand All @@ -29,27 +28,10 @@ func TestGSS(t *testing.T) {
assert.Equal(t, "test", w.Header().Get("X-Test"))
})

t.Run("rate limits requests", func(t *testing.T) {
t.Parallel()

cfg := &config{
RateLimitPerMinute: 100,
}
fileServer := newFileServer(cfg, metrics).init()
w := httptest.NewRecorder()
r := httptest.NewRequest(http.MethodGet, "/", nil)

fileServer.Server.Handler.ServeHTTP(w, r)

assert.NotEmpty(t, w.Header().Get("X-Ratelimit-Limit"))
})

t.Run("redirects index correctly", func(t *testing.T) {
t.Parallel()

cfg := &config{
RateLimitPerMinute: 100,
}
cfg := &config{}
fileServer := newFileServer(cfg, metrics).init()
w := httptest.NewRecorder()
r := httptest.NewRequest(http.MethodGet, "/index.html", nil)
Expand All @@ -62,9 +44,7 @@ func TestGSS(t *testing.T) {
t.Run("serves HTML files succesfully", func(t *testing.T) {
t.Parallel()

cfg := &config{
RateLimitPerMinute: 100,
}
cfg := &config{}
fileServer := newFileServer(cfg, metrics).init()
w := httptest.NewRecorder()
r := httptest.NewRequest(http.MethodGet, "/", nil)
Expand All @@ -79,9 +59,7 @@ func TestGSS(t *testing.T) {
t.Run("serves CSS files succesfully", func(t *testing.T) {
t.Parallel()

cfg := &config{
RateLimitPerMinute: 100,
}
cfg := &config{}
fileServer := newFileServer(cfg, metrics).init()
w := httptest.NewRecorder()
r := httptest.NewRequest(http.MethodGet, "/static/main.68aa49f7.css", nil)
Expand All @@ -96,9 +74,7 @@ func TestGSS(t *testing.T) {
t.Run("serves JavaScript files succesfully", func(t *testing.T) {
t.Parallel()

cfg := &config{
RateLimitPerMinute: 100,
}
cfg := &config{}
fileServer := newFileServer(cfg, metrics).init()
w := httptest.NewRecorder()
r := httptest.NewRequest(http.MethodGet, "/static/main.8d3db4ef.js", nil)
Expand All @@ -113,9 +89,7 @@ func TestGSS(t *testing.T) {
t.Run("serves other files succesfully", func(t *testing.T) {
t.Parallel()

cfg := &config{
RateLimitPerMinute: 100,
}
cfg := &config{}
fileServer := newFileServer(cfg, metrics).init()
w := httptest.NewRecorder()
r := httptest.NewRequest(http.MethodGet, "/static/main.8d3db4ef.js.LICENSE.txt", nil)
Expand All @@ -129,9 +103,7 @@ func TestGSS(t *testing.T) {
t.Run("serves brotli files succesfully", func(t *testing.T) {
t.Parallel()

cfg := &config{
RateLimitPerMinute: 100,
}
cfg := &config{}
fileServer := newFileServer(cfg, metrics).init()
w := httptest.NewRecorder()
r := httptest.NewRequest(http.MethodGet, "/", nil)
Expand All @@ -146,9 +118,7 @@ func TestGSS(t *testing.T) {
t.Run("serves brotli files under nested folders succesfully", func(t *testing.T) {
t.Parallel()

cfg := &config{
RateLimitPerMinute: 100,
}
cfg := &config{}
fileServer := newFileServer(cfg, metrics).init()
w := httptest.NewRecorder()
r := httptest.NewRequest(http.MethodGet, "/static/main.8d3db4ef.js", nil)
Expand All @@ -165,9 +135,7 @@ func TestGSS(t *testing.T) {
t.Run("serves gzip files succesfully", func(t *testing.T) {
t.Parallel()

cfg := &config{
RateLimitPerMinute: 100,
}
cfg := &config{}
fileServer := newFileServer(cfg, metrics).init()
w := httptest.NewRecorder()
r := httptest.NewRequest(http.MethodGet, "/", nil)
Expand All @@ -182,9 +150,7 @@ func TestGSS(t *testing.T) {
t.Run("serves gzip files under nested folders succesfully", func(t *testing.T) {
t.Parallel()

cfg := &config{
RateLimitPerMinute: 100,
}
cfg := &config{}
fileServer := newFileServer(cfg, metrics).init()
w := httptest.NewRecorder()
r := httptest.NewRequest(http.MethodGet, "/static/main.8d3db4ef.js", nil)
Expand All @@ -201,9 +167,7 @@ func TestGSS(t *testing.T) {
t.Run("serves unexisting files without extension", func(t *testing.T) {
t.Parallel()

cfg := &config{
RateLimitPerMinute: 100,
}
cfg := &config{}
fileServer := newFileServer(cfg, metrics).init()
w := httptest.NewRecorder()
r := httptest.NewRequest(http.MethodGet, "/random-page", nil)
Expand All @@ -218,9 +182,7 @@ func TestGSS(t *testing.T) {
t.Run("doesn't serve unexisting files with extension", func(t *testing.T) {
t.Parallel()

cfg := &config{
RateLimitPerMinute: 100,
}
cfg := &config{}
fileServer := newFileServer(cfg, metrics).init()
w := httptest.NewRecorder()
r := httptest.NewRequest(http.MethodGet, "/favicon.ico", nil)
Expand All @@ -233,9 +195,7 @@ func TestGSS(t *testing.T) {
t.Run("serves a cached response for a fresh resource", func(t *testing.T) {
t.Parallel()

cfg := &config{
RateLimitPerMinute: 100,
}
cfg := &config{}
fileServer := newFileServer(cfg, metrics).init()

t.Run("HTML files should have Cache-Control: no-cache", func(t *testing.T) {
Expand Down

0 comments on commit ebe254f

Please sign in to comment.