Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parsoid: Rate limit stashing requests #1140

Merged
merged 1 commit into from
May 23, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions config.example.wikimedia.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ default_project: &default_project
parsoid:
host: https://parsoid-beta.wmflabs.org
grace_ttl: 1000000
stash_ratelimit: 5
action:
apiUriTemplate: "{{'https://{domain}/w/api.php'}}"
baseUriTemplate: "{{'https://{domain}/api/rest_v1'}}"
Expand Down
50 changes: 46 additions & 4 deletions sys/parsoid.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,7 @@ function compileReRenderBlacklist(blacklist) {

class ParsoidService {
constructor(options) {
this.options = options = options || {};
this.parsoidHost = options.parsoidHost;

this._blacklist = compileReRenderBlacklist(options.rerenderBlacklist);
this._initOpts(options);

// Set up operations
this.operations = {
Expand All @@ -125,6 +122,46 @@ class ParsoidService {
};
}

_initOpts(opts = {}) {
this.options = opts;
this.parsoidHost = opts.parsoidHost;
this.options.stash_ratelimit = opts.stash_ratelimit || 5;
this.options.grace_ttl = opts.grace_ttl || 86400;
this._blacklist = compileReRenderBlacklist(opts.rerenderBlacklist);
if (!opts.parsoidHost) {
throw new Error('Parsoid module: the option parsoidHost must be provided!');
}
}

_checkStashRate(hyper, req) {
if (!hyper.ratelimiter) {
return;
}
if (hyper._rootReq.headers['x-request-class'] !== 'external') {
return;
}
if (!((req.query && req.query.stash) || (req.body && req.body.stash))) {
return;
}
const key = `${hyper.config.service_name}.parsoid_stash|` +
`${hyper._rootReq.headers['x-client-ip']}`;
if (hyper.ratelimiter.isAboveLimit(key, this.options.stash_ratelimit)) {
hyper.logger.log('warn/parsoid/stashlimit', {
key,
rate_limit_per_second: this.options.stash_ratelimit,
message: 'Stashing rate limit exceeded'
});
throw new HTTPError({
status: 429,
body: {
type: 'request_rate_exceeded',
title: 'Stashing rate limit exceeded',
rate_limit_per_second: this.options.stash_ratelimit
}
});
}
}

/**
* Get the URI of a bucket for the latest Parsoid content.
* @param {string} domain the domain name.
Expand Down Expand Up @@ -453,6 +490,9 @@ class ParsoidService {
});
}

// check the rate limit for stashing requests
this._checkStashRate(hyper, req);

let contentReq =
this._getContentWithFallback(hyper, rp.domain, rp.title, rp.revision, rp.tid);

Expand Down Expand Up @@ -690,6 +730,8 @@ class ParsoidService {
if (!rp.revision) {
rp.revision = '0';
}
// check the rate limit for stashing requests
this._checkStashRate(hyper, req);
}

let transform;
Expand Down
9 changes: 6 additions & 3 deletions v1/content.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,8 @@ paths:
in: query
description: >
Whether to temporary stash data-parsoid in order to support transforming the
modified content later.
modified content later. If this parameter is set, requests are rate-limited on
a per-client basis (max 5 requests per second per client)
type: boolean
required: false
- name: Accept-Language
Expand Down Expand Up @@ -426,7 +427,8 @@ paths:
in: query
description: >
Whether to temporary stash data-parsoid in order to support transforming the
modified content later.
modified content later. If this parameter is set, requests are rate-limited on
a per-client basis (max 5 requests per second per client)
type: boolean
required: false
- name: Accept-Language
Expand Down Expand Up @@ -541,7 +543,8 @@ paths:
in: query
description: >
Whether to temporary stash data-parsoid in order to support transforming the
modified content later.
modified content later. If this parameter is set, requests are rate-limited on
a per-client basis (max 5 requests per second per client)
type: boolean
required: false
- name: Accept-Language
Expand Down
2 changes: 1 addition & 1 deletion v1/transform.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ paths:
also need to supply the title.

- Stability: [stable](https://www.mediawiki.org/wiki/API_versioning#Stable)
- Rate limit: 25 req/s
- Rate limit: 25 req/s (5 req/s when `stash: true`)
consumes:
- multipart/form-data
produces:
Expand Down