Arlolra has uploaded a new change for review. https://gerrit.wikimedia.org/r/187848
Change subject: Set X-Forwarded-Proto when proxying https ...................................................................... Set X-Forwarded-Proto when proxying https * Refactors a bit about how proxies are stored in order to accommodate associating setting a header for that proxy. Bug: T88100 Change-Id: Iad6d64971085c54e77adfbe76a3a8499c4d5c9ef --- M lib/mediawiki.ApiRequest.js M lib/mediawiki.ParsoidConfig.js M lib/mediawiki.WikiConfig.js M lib/mediawiki.parser.environment.js 4 files changed, 87 insertions(+), 65 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/services/parsoid refs/changes/48/187848/1 diff --git a/lib/mediawiki.ApiRequest.js b/lib/mediawiki.ApiRequest.js index d977513..6b31a3f 100644 --- a/lib/mediawiki.ApiRequest.js +++ b/lib/mediawiki.ApiRequest.js @@ -235,14 +235,15 @@ apiargs.titles = title; } - var uri = env.conf.wiki.apiURI + '?' + qs.stringify( apiargs ); + var uri = env.conf.wiki.apiURI + '?' + qs.stringify( apiargs ), + proxy = env.conf.wiki.apiProxy; this.requestOptions = { method: 'GET', followRedirect: true, uri: uri, timeout: 40 * 1000, // 40 seconds - proxy: env.conf.wiki.apiProxyURI, + proxy: proxy && proxy.uri, strictSSL: env.conf.parsoid.strictSSL, headers: { 'User-Agent': userAgent, @@ -250,7 +251,11 @@ } }; - if (env.cookie) { + if ( proxy && proxy.headers ) { + Object.assign( this.requestOptions.headers, proxy.headers ); + } + + if ( env.cookie ) { // Forward the cookie if set this.requestOptions.headers.Cookie = env.cookie; } @@ -375,7 +380,8 @@ apiargs.revid = env.page.meta.revision.revid; } - var uri = env.conf.wiki.apiURI; + var uri = env.conf.wiki.apiURI, + proxy = env.conf.wiki.apiProxy; this.requestOptions = { // Use POST since we are passing a bit of source, and GET has a very @@ -386,7 +392,7 @@ followRedirect: true, uri: uri, timeout: 30 * 1000, // 30 seconds - proxy: env.conf.wiki.apiProxyURI, + proxy: proxy && proxy.uri, strictSSL: env.conf.parsoid.strictSSL, headers: { 'User-Agent': userAgent, @@ -394,7 +400,11 @@ } }; - if (env.cookie) { + if ( proxy && proxy.headers ) { + Object.assign( this.requestOptions.headers, proxy.headers ); + } + + if ( env.cookie ) { // Forward the cookie if set this.requestOptions.headers.Cookie = env.cookie; } @@ -476,7 +486,9 @@ contentmodel: 'wikitext', prop: 'text|modules|categories' }; - var uri = env.conf.wiki.apiURI; + + var uri = env.conf.wiki.apiURI, + proxy = env.conf.wiki.apiProxy; // Pass the page title to the API var title = env.page && env.page.title && env.page.title.key; @@ -493,7 +505,7 @@ followRedirect: true, uri: uri, timeout: 16 * 1000, // 16 seconds - proxy: env.conf.wiki.apiProxyURI, + proxy: proxy && proxy.uri, strictSSL: env.conf.parsoid.strictSSL, headers: { 'User-Agent': userAgent, @@ -501,7 +513,11 @@ } }; - if (env.cookie) { + if ( proxy && proxy.headers ) { + Object.assign( this.requestOptions.headers, proxy.headers ); + } + + if ( env.cookie ) { // Forward the cookie if set this.requestOptions.headers.Cookie = env.cookie; } @@ -610,14 +626,12 @@ var apiargs = { oldid: oldid }; + var uri = env.conf.parsoid.parsoidCacheURI + env.conf.wiki.iwp + '/' + encodeURIComponent(title.replace(/ /g, '_')) + '?' + qs.stringify( apiargs ); + this.uri = uri; - - //console.warn('Cache request:', uri); - - this.retries = 0; this.requestOptions = { // Use GET so that our request is cacheable @@ -675,14 +689,18 @@ * A request for the wiki's configuration variables. * * @constructor - * @param {string} apiURI The API URI to use for fetching + * @param {string} uri The API URI to use for fetching * @param {MWParserEnvironment} env - * @param {string} apiProxyURI (optional) The proxy URI to use for the - * ConfigRequest + * @param {string} proxy (optional) The proxy to use for the ConfigRequest. */ -var ConfigRequest = function ( apiURI, env, apiProxyURI ) { +var ConfigRequest = function( uri, env, proxy ) { ApiRequest.call( this, env, null ); - this.queueKey = apiURI; + this.queueKey = uri; + + if ( !uri ) { + this._requestCB( new Error( 'There was no base URI for the API we tried to use.' ) ); + return; + } var metas = [ 'siteinfo' @@ -705,17 +723,12 @@ siprop: siprops.join( '|' ) }; - if ( !apiURI ) { - this._requestCB( new Error( 'There was no base URI for the API we tried to use.' ) ); - return; - } - this.requestOptions = { method: 'GET', followRedirect: true, - uri: apiURI + '?' + qs.stringify( apiargs ), + uri: uri + '?' + qs.stringify( apiargs ), timeout: 40 * 1000, - proxy: apiProxyURI, + proxy: proxy && proxy.uri, strictSSL: env.conf.parsoid.strictSSL, headers: { 'User-Agent': userAgent, @@ -723,11 +736,14 @@ } }; - if (env.cookie) { + if ( proxy && proxy.headers ) { + Object.assign( this.requestOptions.headers, proxy.headers ); + } + + if ( env.cookie ) { // Forward the cookie if set this.requestOptions.headers.Cookie = env.cookie; } - this.request( this.requestOptions, this._requestCB.bind( this ) ); }; @@ -804,18 +820,25 @@ uri += qs.stringify( apiArgs ); + var proxy = env.conf.wiki.apiProxy; + this.requestOptions = { method: 'GET', followRedirect: true, uri: uri, timeout: 40 * 1000, - proxy: env.conf.wiki.apiProxyURI, + proxy: proxy && proxy.uri, headers: { 'User-Agent': userAgent, 'Connection': 'close' } }; - if (env.cookie) { + + if ( proxy && proxy.headers ) { + Object.assign( this.requestOptions.headers, proxy.headers ); + } + + if ( env.cookie ) { // Forward the cookie if set this.requestOptions.headers.Cookie = env.cookie; } diff --git a/lib/mediawiki.ParsoidConfig.js b/lib/mediawiki.ParsoidConfig.js index 11cbc9b..a4230cd 100644 --- a/lib/mediawiki.ParsoidConfig.js +++ b/lib/mediawiki.ParsoidConfig.js @@ -26,7 +26,7 @@ function ParsoidConfig( localSettings, options ) { this.interwikiMap = new Map(); this.reverseIWMap = new Map(); - this.apiProxyURIs = new Map(); + this.apiProxys = new Map(); this.interwikiRegexp = ""; if ( localSettings && localSettings.setup ) { @@ -60,18 +60,22 @@ * * @param {string} prefix * @param {string} apiURI The URL to the wiki's api.php. - * @param {string} apiProxyURI The URL of a proxy to use for API requests, or + * @param {string} proxyURI The URL of a proxy to use for API requests, or * null to explicitly disable API request proxying for this wiki. Will fall * back to ParsoidConfig.defaultAPIProxyURI if undefined (default value). + * @param {object} proxyHeaders Headers to add when proxying. */ -ParsoidConfig.prototype.setInterwiki = function( prefix, apiURI, apiProxyURI ) { +ParsoidConfig.prototype.setInterwiki = function( prefix, apiURI, proxyURI, proxyHeaders ) { this.interwikiMap.set( prefix, apiURI ); this.reverseIWMap.set( url.parse( apiURI ).host, prefix ); - if ( apiProxyURI !== undefined ) { - this.apiProxyURIs.set(prefix, apiProxyURI); + if ( proxyURI !== undefined || proxyHeaders !== undefined ) { + this.apiProxys.set(prefix, { + uri: proxyURI, + headers: proxyHeaders + }); } else { - this.apiProxyURIs.delete(prefix); + this.apiProxys.delete(prefix); } if ( this.interwikiRegexp.match( '(^|\\|)' + prefix + '(\\||$)' ) === null ) { @@ -93,7 +97,7 @@ var u = url.parse( this.interwikiMap.get(prefix) ); this.reverseIWMap.delete(u.host); this.interwikiMap.delete(prefix); - this.apiProxyURIs.delete(prefix); + this.apiProxys.delete(prefix); this.interwikiRegexp = this.interwikiRegexp.replace( new RegExp( '(^|\\|)' + prefix + '(\\||$)' ), function() { return arguments[0] === ("|" + prefix + "|") ? "|" : ''; @@ -213,7 +217,7 @@ ParsoidConfig.prototype.strictSSL = true; /** - * The default api proxy, overridden by apiProxyURIs entries. + * The default api proxy, overridden by apiProxys entries. */ ParsoidConfig.prototype.defaultAPIProxyURI = undefined; @@ -226,19 +230,20 @@ * Initialize the interwikiMap and friends. */ ParsoidConfig.prototype.initInterwikiMap = function() { - var insertInMaps = function( proxy, site ) { + var insertInMaps = function( proxyURI, site ) { + var proxyHeaders; // Avoid overwriting those already set in localsettings setup. if ( !this.interwikiMap.has( site.dbname ) ) { - var url = site.url; - // Strip TLS if we're using the default proxy. - if ( proxy === undefined ) { - url = url.replace("https", "http"); + // When proxying https, lie to the appserver to indicate + // unwrapping has just occurred. + if ( proxyURI === undefined && /https/.test( site.url ) ) { + proxyHeaders = { "X-Forwarded-Proto": "https" }; } - this.setInterwiki( site.dbname, url + "/w/api.php", proxy ); + this.setInterwiki( site.dbname, site.url + "/w/api.php", proxyURI, proxyHeaders ); } }; - // See MWParserEnvironment.prototype.getAPIProxyURI for the meaning + // See MWParserEnvironment.prototype.getAPIProxy for the meaning // of null / undefined in setInterwiki. var self = this; diff --git a/lib/mediawiki.WikiConfig.js b/lib/mediawiki.WikiConfig.js index 530894e..95c44f5 100644 --- a/lib/mediawiki.WikiConfig.js +++ b/lib/mediawiki.WikiConfig.js @@ -22,15 +22,12 @@ * @param {Object} resultConf The configuration object from a MediaWiki API request. See the #ConfigRequest class in lib/mediawiki.ApiRequest.js for information about how we get this object. If null, we use the contents of lib/mediawiki.BaseConfig.json instead. * @param {string} prefix The interwiki prefix this config will represent. Will be used for caching elsewhere in the code. * @param {string} apiURI The URI that represents this wiki's API endpoint. Usually ends in api.php. - * @param {string} apiProxyURI (optional) The URI of a proxy that should be - * used to access apiURI, or null to explicitly disable proxying for this - * wiki. + * @param {string} apiProxy (optional) The proxy that should be used to access apiURI. */ -function WikiConfig( resultConf, prefix, apiURI, apiProxyURI ) { +function WikiConfig( resultConf, prefix, apiURI, apiProxy ) { var nsid, name, conf = this; - // Mapping from canonical namespace name to id // The English namespace names are built-in and will work in any language. @@ -67,7 +64,7 @@ this.apiURI = apiURI || null; // The proxy to use for this wiki. - this.apiProxyURI = apiProxyURI; + this.apiProxy = apiProxy; if ( resultConf === null ) { // Use the default JSON that we've already loaded above. diff --git a/lib/mediawiki.parser.environment.js b/lib/mediawiki.parser.environment.js index 90ee85e..87f7171 100644 --- a/lib/mediawiki.parser.environment.js +++ b/lib/mediawiki.parser.environment.js @@ -271,18 +271,19 @@ }; /** - * Figure out the proxy URI to use for API requests for a given wiki + * Figure out the proxy to use for API requests for a given wiki */ -MWParserEnvironment.prototype.getAPIProxyURI = function (prefix) { - var apiProxyURI = this.conf.parsoid.apiProxyURIs.get(prefix); - if (apiProxyURI === undefined) { +MWParserEnvironment.prototype.getAPIProxy = function( prefix ) { + var apiProxy = this.conf.parsoid.apiProxys.get(prefix) || + { uri: undefined, headers: undefined }; + if ( apiProxy.uri === undefined ) { // No specific api proxy set. Fall back to generic API proxy. - apiProxyURI = this.conf.parsoid.defaultAPIProxyURI; - } else if (apiProxyURI === null) { + apiProxy.uri = this.conf.parsoid.defaultAPIProxyURI; + } else if ( apiProxy.uri === null ) { // Explicitly disable the proxy if null was set for this prefix - apiProxyURI = undefined; + apiProxy.uri = undefined; } - return apiProxyURI; + return apiProxy; }; @@ -295,14 +296,12 @@ * @param {Error} cb.err */ MWParserEnvironment.prototype.switchToConfig = function ( prefix, cb ) { - function setupWikiConfig(env, apiURI, error, config) { if ( error === null ) { - env.conf.wiki = new WikiConfig( config, prefix, apiURI, env.getAPIProxyURI(prefix) ); + env.conf.wiki = new WikiConfig( config, prefix, apiURI, env.getAPIProxy(prefix) ); env.confCache[prefix] = env.conf.wiki; } - cb( error ); } @@ -330,10 +329,8 @@ this.conf.wiki = this.confCache[prefix]; cb( null ); } else if ( this.conf.parsoid.fetchConfig ) { - - var apiProxyURI = this.getAPIProxyURI(prefix), - confRequest = new ConfigRequest( uri, this, apiProxyURI ); - confRequest.on( 'src', setupWikiConfig.bind(null, this, uri)); + var confRequest = new ConfigRequest( uri, this, this.getAPIProxy(prefix) ); + confRequest.on('src', setupWikiConfig.bind(null, this, uri)); } else { // Load the config from cached config on disk var localConfigFile = './baseconfig/' + prefix + '.json', -- To view, visit https://gerrit.wikimedia.org/r/187848 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Iad6d64971085c54e77adfbe76a3a8499c4d5c9ef Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/services/parsoid Gerrit-Branch: master Gerrit-Owner: Arlolra <abrea...@wikimedia.org> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits