Skip to content

Add rate limiting, production server hardening, and CD workflow#20

Open
pascaljoly wants to merge 1 commit into
Ribbit-Network:mainfrom
pascaljoly:fix/issues-14-15-17
Open

Add rate limiting, production server hardening, and CD workflow#20
pascaljoly wants to merge 1 commit into
Ribbit-Network:mainfrom
pascaljoly:fix/issues-14-15-17

Conversation

@pascaljoly
Copy link
Copy Markdown
Contributor

Closes #14, #15, #17

Changes

Issue #17 — Rate limiting

  • New internal/ratelimit package: per-API-key token-bucket limiter (60 req/s, burst 30)
  • Wired into /data after the auth middleware
  • 5 tests covering burst, block-after-burst, per-key isolation, Bearer token, and no-key passthrough

Issue #15 — Deploy to Hosting

  • http.Server with 30s read/write + 120s idle timeouts
  • Graceful SIGTERM/SIGINT shutdown (15s drain window)
  • /healthz endpoint for fly.io health checks
  • CORS middleware for browser clients
  • .github/workflows/deploy.yml — auto-deploys to fly.io on push to main (requires FLY_API_TOKEN GitHub secret)

Issue #14 — API Keys

  • Already implemented in the codebase; no code changes needed

Closes Ribbit-Network#17: per-API-key token-bucket rate limiter (60 req/s, burst 30)
in new internal/ratelimit package, wired into /data after auth.

Closes Ribbit-Network#15: http.Server with read/write/idle timeouts, graceful SIGTERM
shutdown, /healthz endpoint, CORS middleware, and a fly.io CD workflow
(.github/workflows/deploy.yml) that deploys on push to main.

Issue Ribbit-Network#14 (API keys) was already implemented in the codebase.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@keenanjohnson
Copy link
Copy Markdown
Member

Hey @pascaljoly! Thanks for the new changeset! I see the CI is failing due to a license key issue. I thought I had sorted that out for the secret monitoring, but let me fix it again.

@keenanjohnson keenanjohnson self-requested a review May 18, 2026 22:40
Copy link
Copy Markdown
Member

@keenanjohnson keenanjohnson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok this is a good start, but there are a few changes I think we need to make before we merge this. Let me know if you have bandwidth to do so, but if not I can knock them out @pascaljoly

Comment thread main.go
}

requireKey := auth.Require(store)
// 60 requests/minute per key with a burst of 30.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment here and the burst limit in the code below disagree. The comment says burst 30, but the code below is burst 60.

})
}

func (l *Limiter) get(key string) *rate.Limiter {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The actual rate limited never removes a client when added, which will be an infinite memory leak. We should eventually remove clients after some time threshold or use a library like https://github.com/didip/tollbooth which handles the removal.

return lim
}

func extractKey(r *http.Request) string {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function appears to be a duplicate of the one in middleware.go

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably use the authentication layer. The auth should then stash the verified key in r.Context() and let ratelimit read it from there.

steps:
- uses: actions/checkout@v4
- uses: superfly/flyctl-actions/setup-flyctl@master
- run: flyctl deploy --remote-only
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This deploys no matter what, even if the tests fail etc. Either needs: the CI job or run go test ./... before flyctl deploy

@keenanjohnson
Copy link
Copy Markdown
Member

@pascaljoly I've also investigated the gitleaks license key issue and it seems that a limitation of the gitleaks secret scanning is that it doesn't work on community fork contributions like yours per this github issue: gitleaks/gitleaks#2063

You can see new PR's I opened from inside the repo run fine, like this one, which means the API key is working: #21

I'll try to investigate a workaround but for now, let's just ignore that failing check.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add API Keys to Limit API Access

2 participants