
CORS and rate limit
Settings in namespace minishop3: System settings → API.
CORS
ms3_cors_allowed_origins value | Behavior |
|---|---|
| empty (this is what the installer writes) | Same-origin only: CORS headers are not set |
* | Access-Control-Allow-Origin: *, credentials are turned off |
| comma-separated list | The server echoes the request Origin and adds Vary: Origin and Allow-Credentials: true |
web.php creates CorsMiddleware with allow_credentials => true.
Allowed methods: GET, POST, PUT, DELETE, OPTIONS. Allowed headers: Content-Type, Authorization, X-Requested-With, MS3TOKEN. max_age is 86400.
In a pattern such as https://*.example.com the asterisk replaces one DNS label, not an arbitrary part of the address.
OPTIONS preflight returns 200 without token mint.
Rate limit
Over the quota:
HTTP/1.1 429 Too Many Requests
Retry-After: 42{
"success": false,
"message": "ms3_err_rate_limit",
"code": 429,
"errors": null,
"error_code": "rate_limited"
}The window is fixed: it starts with the first request, reset_at is set once as «now plus ms3_rate_limit_decay_seconds» and never slides. Once the window is over, the counter resets completely.
| Header | When it is sent | What it holds |
|---|---|---|
Retry-After | with a 429 only | seconds until the window ends |
X-RateLimit-Limit | while the request fits the quota | the value of ms3_rate_limit_max_attempts |
X-RateLimit-Remaining | the same | how many requests are left |
X-RateLimit-Reset | the same | a Unix timestamp of the window end, not a number of seconds |
Behind a reverse proxy the counter is shared
The bucket key is md5() of REMOTE_ADDR. The middleware deliberately ignores headers such as X-Forwarded-For: the client controls them, so the limit could be bypassed by forging one. If the site sits behind a reverse proxy, a CDN or a Nuxt server and the web server does not replace REMOTE_ADDR with the visitor address, every customer shares one bucket and hits a common limit. Configure the real address at the web-server level.
OPTIONS requests do not consume the quota.
| Setting | Default | What it sets |
|---|---|---|
ms3_rate_limit_max_attempts | 60 | Number of requests in the window |
ms3_rate_limit_decay_seconds | 60 | Window length in seconds |
ms3_rate_limit_store picks the counter storage (default file). The installer also creates the redis and memcached keys and the file path next to it. The error body is described in Errors.
An environment variable overrides the setting, and a backend failure is silent
When the MS3_RATE_LIMIT_STORE environment variable is set, its value wins and the system setting is ignored.
When the chosen backend is unavailable — no redis or memcached extension, or the connection fails — the factory writes a WARN to the log and quietly falls back to file storage. Requests keep working, but on a cluster the counter stops being shared: every node starts counting its own attempts. Check the log after changing the storage.
Nuxt on another origin
- List the frontend origin (or BFF) in
ms3_cors_allowed_origins. - Requests with
credentials: 'include'or Bearer without cookie. - Do not set
*together with a cookie session: with that value a cookie from another origin will not work.
