Skip to content

feat(gateway): make request body size configurable via env#186

Open
PranavAgarkar07 wants to merge 4 commits into
AnkanMisra:mainfrom
PranavAgarkar07:feat/configurable-body-size
Open

feat(gateway): make request body size configurable via env#186
PranavAgarkar07 wants to merge 4 commits into
AnkanMisra:mainfrom
PranavAgarkar07:feat/configurable-body-size

Conversation

@PranavAgarkar07
Copy link
Copy Markdown
Contributor

@PranavAgarkar07 PranavAgarkar07 commented May 29, 2026

Summary

Replaces the hardcoded const maxBodySize = 10 * 1024 * 1024 in gateway/main.go with a configurable value driven by the MAX_REQUEST_BODY_MB environment variable. A new helper getMaxBodySize() in gateway/config.go handles parsing and falls back to 10 MB when the variable is unset or invalid.

Also fixes a P1 issue introduced when the original hardcoded constant was replaced: the 413 error response JSON key drifted from "max_size" to "max_size_mb" with a type change (string → int). Restored the original response format so clients parsing the error do not break.

Type Of Change

  • Bug fix
  • Feature
  • Documentation
  • Tests
  • Refactor
  • Deployment/config

Affected Areas

  • Gateway (gateway/)
  • Verifier (verifier/)
  • Web (web/)
  • E2E/tests
  • Benchmarks
  • Deployment/config
  • Documentation/community files

Contributor Checklist

  • I kept the change focused and avoided unrelated refactors.
  • I updated README/service docs/OpenAPI/env examples when behavior, config, headers, status codes, or public APIs changed.
  • I did not commit secrets, private keys, funded wallets, API keys, or real production URLs.
  • I checked x402/EIP-712 field parity when touching payment context, signatures, timestamps, nonces, chain IDs, receipts, or wallet flow.
  • I checked Docker/Compose/Fly/Vercel docs when touching ports, service names, health checks, or environment variables.

Verification

$ cd gateway && go vet ./... && go test -v ./...
ok  	gateway	10.009s
ok  	gateway/internal/ai	0.006s

Notes For Reviewers

The getMaxBodySize() helper lives in config.go alongside the other typed-helper functions (getEnvAsDuration, getEnvAsBool, etc.) and follows the same pattern: log a warning and return the default when parsing fails.

Summary by CodeRabbit

  • New Features

    • Request body size limit is now configurable (default 10MB) with dynamic error responses
    • Added duplicate nonce error type with improved user messaging
    • Implemented error detail sanitization for cleaner API responses
  • Tests

    • Added comprehensive test coverage for error classification and handling behavior
  • Chores

    • Added testing framework and related dependencies

Review Change Stack

Add dedicated duplicate-nonce error kind for nonce_already_used
(was incorrectly mapped to 'expired'). Sanitize raw gateway JSON
blobs in debug detail to show clean error codes instead.

Closes AnkanMisra#165
Covers all HTTP status -> error kind mappings (400/402/403/408/409/429/
502/504/5xx), gateway error codes (nonce_already_used, invalid_signature,
upstream_unavailable, verification_unavailable, verifier_timeout, etc.),
wallet error patterns (rejection codes 4001/ACTION_REJECTED, wrong chain
messages, missing wallet, network errors), and detail sanitization.
Replace hardcoded 10MB limit with MAX_REQUEST_BODY_MB env
var parsed by getMaxBodySize() helper in config.go. Falls
back to 10MB when unset or invalid.

Also fixes a P1 regression from the original implementation:
the 413 error response key was mistakenly changed from
'max_size' to 'max_size_mb' with a different format. The
original 'max_size' key with '%dMB' string format is
restored, now driven by the configurable value.

Closes AnkanMisra#116
@vercel
Copy link
Copy Markdown

vercel Bot commented May 29, 2026

@PranavAgarkar07 is attempting to deploy a commit to the ankanmisra's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 29, 2026

📝 Walkthrough

Walkthrough

Request body size limits transition from hardcoded 10MB to environment configuration; error classification adds duplicate-nonce handling with detail sanitization; web error tests validate classification paths and detail formatting rules.

Changes

Request Body Configurability and Error Handling

Layer / File(s) Summary
Environment configuration for request body limits
\.env\.example
MAX_REQUEST_BODY_MB environment variable (default 10) added to control request body size in MB.
Gateway request body enforcement
gateway/config.go, gateway/main.go
getMaxBodySize() reads environment and converts MB to bytes; handleSummarize applies configurable limit to http.MaxBytesReader and reports dynamic max_size in 413 error responses.
Error type and messaging for duplicate nonce
web/src/lib/errors.ts
ErrorKind union adds "duplicate-nonce" variant; COPY map includes user-facing title and message for the new error kind.
Error detail sanitization and HTTP status mapping
web/src/lib/errors.ts
sanitizeDetail() parses JSON error payloads, extracts error codes and correlation IDs, truncates long strings; HTTP 409 nonce_already_used maps to "duplicate-nonce" instead of previous mapping.
Test infrastructure for web error handling
web/package.json
vitest dev dependency and test:unit npm script added to enable unit testing.
Comprehensive error classification and sanitization tests
web/src/lib/errors.test.ts
Test suites validate classifyError classification from HTTP context, thrown errors (rejection/chain/wallet/network), detail sanitization (JSON extraction, truncation, correlation IDs), and edge cases (non-objects, null).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related issues

  • #116: Request body size configurability implementation via MAX_REQUEST_BODY_MB, getMaxBodySize(), and dynamic limit enforcement in request handlers.

Suggested labels

SWoC26, level:intermediate

Suggested reviewers

  • AnkanMisra

Poem

🐰 A config hop, body sizes now flow,
Duplicate nonces get a kind way to show,
Detail sanitized, errors shine bright,
Tests validate all paths—thorough and right!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The PR title clearly and concisely describes the main change: making request body size configurable via environment variable in the gateway.
Description check ✅ Passed The PR description includes all required sections from the template and contains substantive details about the changes, rationale, and verification steps.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
⚔️ Resolve merge conflicts
  • Resolve merge conflict in branch feat/configurable-body-size

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.

🔧 golangci-lint (2.12.2)

level=error msg="[linters_context] typechecking error: pattern ./...: directory prefix . does not contain main module or its selected dependencies"


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@gateway/config.go`:
- Around line 99-102: The getMaxBodySize function must guard against
non-positive values returned by getEnvAsInt (e.g., MAX_REQUEST_BODY_MB=0 or
negative) by clamping them to the default used elsewhere (like
getPositiveTimeout); update getMaxBodySize to treat mb <= 0 as the default 10
(or use the same default constant if present) before converting to bytes so
http.MaxBytesReader never receives a zero/negative limit and accidentally
rejects valid requests.

In `@gateway/main.go`:
- Around line 419-425: Replace the hardcoded const maxBodySize = 10*1024*1024 in
gateway/cache.go and any Content-Length checks or http.MaxBytesReader uses with
the dynamic value from getMaxBodySize(); update the cache middleware (e.g., the
Cache middleware/handler function) to call maxSize := getMaxBodySize(), use
http.MaxBytesReader(c.Writer, c.Request.Body, maxSize), compare Content-Length
against maxSize, and when returning 413 include the same formatted max_size
string as in gateway/main.go (fmt.Sprintf("%dMB", maxSize/1024/1024)) so
CACHE_ENABLED respects MAX_REQUEST_BODY_MB.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 169325ae-7afd-47d8-8070-93b825677bde

📥 Commits

Reviewing files that changed from the base of the PR and between 8985ec7 and f290dbe.

📒 Files selected for processing (6)
  • .env.example
  • gateway/config.go
  • gateway/main.go
  • web/package.json
  • web/src/lib/errors.test.ts
  • web/src/lib/errors.ts

Comment thread gateway/config.go
Comment on lines +99 to +102
func getMaxBodySize() int64 {
mb := getEnvAsInt("MAX_REQUEST_BODY_MB", 10)
return int64(mb) * 1024 * 1024
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Guard against non-positive MAX_REQUEST_BODY_MB.

getEnvAsInt returns 0/negative values verbatim, so MAX_REQUEST_BODY_MB=0 (or a negative) produces a 0/negative byte limit. http.MaxBytesReader with a 0 limit rejects every non-empty body, silently turning all /api/ai/summarize requests into 413s. The sibling getPositiveTimeout already clamps non-positive values to the default; mirror that here.

🛡️ Proposed fix to clamp non-positive values
 func getMaxBodySize() int64 {
 	mb := getEnvAsInt("MAX_REQUEST_BODY_MB", 10)
+	if mb <= 0 {
+		log.Printf("Warning: MAX_REQUEST_BODY_MB must be positive, using default 10")
+		mb = 10
+	}
 	return int64(mb) * 1024 * 1024
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
func getMaxBodySize() int64 {
mb := getEnvAsInt("MAX_REQUEST_BODY_MB", 10)
return int64(mb) * 1024 * 1024
}
func getMaxBodySize() int64 {
mb := getEnvAsInt("MAX_REQUEST_BODY_MB", 10)
if mb <= 0 {
log.Printf("Warning: MAX_REQUEST_BODY_MB must be positive, using default 10")
mb = 10
}
return int64(mb) * 1024 * 1024
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@gateway/config.go` around lines 99 - 102, The getMaxBodySize function must
guard against non-positive values returned by getEnvAsInt (e.g.,
MAX_REQUEST_BODY_MB=0 or negative) by clamping them to the default used
elsewhere (like getPositiveTimeout); update getMaxBodySize to treat mb <= 0 as
the default 10 (or use the same default constant if present) before converting
to bytes so http.MaxBytesReader never receives a zero/negative limit and
accidentally rejects valid requests.

Comment thread gateway/main.go
Comment on lines +419 to +425
maxSize := getMaxBodySize()
c.Request.Body = http.MaxBytesReader(c.Writer, c.Request.Body, maxSize)
requestBody, err = io.ReadAll(c.Request.Body)
if err != nil {
var maxBytesErr *http.MaxBytesError
if errors.As(err, &maxBytesErr) {
c.JSON(413, gin.H{"error": "Payload too large", "max_size": "10MB"})
c.JSON(413, gin.H{"error": "Payload too large", "max_size": fmt.Sprintf("%dMB", maxSize/1024/1024)})
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Confirm cache.go still hardcodes the body limit / 413 max_size instead of using getMaxBodySize()
rg -nC3 'maxBodySize|max_size|MaxBytesReader' gateway/cache.go

Repository: AnkanMisra/MicroAI-Paygate

Length of output: 1084


Fix gateway/cache.go to use the configurable request body limit instead of a hardcoded 10MB

gateway/cache.go hardcodes const maxBodySize = 10 * 1024 * 1024 for both the Content-Length check and http.MaxBytesReader, and returns a fixed max_size: "10MB" on 413. This makes the cached request path inconsistent with gateway/main.go’s dynamic getMaxBodySize() + formatted max_size, so MAX_REQUEST_BODY_MB won’t be honored when CACHE_ENABLED=true. Route cache middleware through getMaxBodySize() and use the same max_size formatting as the main handler.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@gateway/main.go` around lines 419 - 425, Replace the hardcoded const
maxBodySize = 10*1024*1024 in gateway/cache.go and any Content-Length checks or
http.MaxBytesReader uses with the dynamic value from getMaxBodySize(); update
the cache middleware (e.g., the Cache middleware/handler function) to call
maxSize := getMaxBodySize(), use http.MaxBytesReader(c.Writer, c.Request.Body,
maxSize), compare Content-Length against maxSize, and when returning 413 include
the same formatted max_size string as in gateway/main.go (fmt.Sprintf("%dMB",
maxSize/1024/1024)) so CACHE_ENABLED respects MAX_REQUEST_BODY_MB.

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.

1 participant