diff --git a/chrome/content/zotero/xpcom/feedReader.js b/chrome/content/zotero/xpcom/feedReader.js index ff877d804b..c0bf0c0a67 100644 --- a/chrome/content/zotero/xpcom/feedReader.js +++ b/chrome/content/zotero/xpcom/feedReader.js @@ -190,6 +190,12 @@ Zotero.FeedReader = function (url) { } }; + // https://github.com/zotero/zotero/issues/2249 + let isNatureFeed = url.match(/^https?:\/\/[^.]+\.nature\.com\/.+\.rss/); + if (isNatureFeed) { + Zotero.HTTP.RequestModifier.enableRule('remove-nature-feed-origin'); + } + Zotero.debug("FeedReader: Fetching feed from " + feedUrl); // Fetch and start processing @@ -200,6 +206,10 @@ Zotero.FeedReader = function (url) { }).catch((e) => { Zotero.debug(e); this.terminate("Processing failed"); + }).finally(() => { + if (isNatureFeed) { + Zotero.HTTP.RequestModifier.disableRule('remove-nature-feed-origin'); + } }); }; diff --git a/chrome/content/zotero/xpcom/http.js b/chrome/content/zotero/xpcom/http.js index 4a248f931f..fefbea1ff9 100644 --- a/chrome/content/zotero/xpcom/http.js +++ b/chrome/content/zotero/xpcom/http.js @@ -818,6 +818,70 @@ Zotero.HTTP = new function() { }; + /** + * General mechanism for modifying requests based on predefined rules + * + * The observer is only active if any rules are enabled. + */ + this.RequestModifier = { + rules: new Set([ + 'remove-nature-feed-origin' + ]), + enabledRules: new Set(), + + observe: function (channel, topic) { + channel.QueryInterface(Components.interfaces.nsIHttpChannel); + if (topic == "http-on-modify-request") { + // https://github.com/zotero/zotero/issues/2249 + if (this.enabledRules.has('remove-nature-feed-origin') + && channel.URI.spec.match(/^https?:\/\/idp\.nature\.com\/.+\.rss/)) { + let dispURL = Zotero.HTTP.getDisplayURI(channel.URI).spec; + Zotero.debug("RequestModifier: Removing Origin header for " + dispURL); + channel.setRequestHeader("Origin", "", false); + } + } + }, + + enableRule: function (rule) { + if (!this.rules.has(rule)) { + throw new Error(`RequestModifier: Can't enable invalid rule '${rule}'`); + } + if (this.enabledRules.has(rule)) { + Zotero.debug(`RequestModifier: Rule '${rule}' is already enabled`); + return; + } + this.enabledRules.add(rule); + // Register the observer if any rules are enabled + if (this.enabledRules.size == 1) { + this.register(); + } + }, + + disableRule: function (rule) { + if (!this.rules.has(rule)) { + throw new Error(`RequestModifier: Can't disable invalid rule '${rule}'`); + } + if (!this.enabledRules.has(rule)) { + Zotero.debug(`RequestModifier: Rule '${rule}' isn't enabled`); + return; + } + this.enabledRules.delete(rule); + // Disable the observer if no rules are enabled + if (!this.enabledRules.size) { + this.unregister(); + } + }, + + register: function () { + Services.obs.addObserver(this, "http-on-modify-request", false); + }, + + unregister: function () { + Services.obs.removeObserver(this, "http-on-modify-request"); + } + }; + + this.CookieBlocker = { registered: false, observeredTopics: [