Вызов синхронного XMLHttpRequest изнутри расширения (extension) Google Chrome

Пишу своё первое расширение под Google Chrome и застопорился на одном, казалось бы простом, моменте. Суть расширения такова:
1. перехватываем попытку обращения к mysite.com;
2. кроссдоменным синхронным запросом к нашему собственному сервису на api.service.com запрашиваем какой адрес хоста вместо mysite.com надо подставить;
3. меняем хост mysite.com в запросе пользователя на полученный адрес хоста и выполняем запрос.

Файл manifest.json:
/** * GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann * (http://qbnz.com/highlighter/ and http://geshi.org/) */ .javascript.geshi_code {font-family:monospace;} .javascript.geshi_code .imp {font-weight: bold; color: red;} .javascript.geshi_code .kw1 {color: #000066; font-weight: bold;} .javascript.geshi_code .kw2 {color: #003366; font-weight: bold;} .javascript.geshi_code .kw3 {color: #000066;} .javascript.geshi_code .co1 {color: #006600; font-style: italic;} .javascript.geshi_code .co2 {color: #009966; font-style: italic;} .javascript.geshi_code .coMULTI {color: #006600; font-style: italic;} .javascript.geshi_code .es0 {color: #000099; font-weight: bold;} .javascript.geshi_code .br0 {color: #009900;} .javascript.geshi_code .sy0 {color: #339933;} .javascript.geshi_code .st0 {color: #3366CC;} .javascript.geshi_code .nu0 {color: #CC0000;} .javascript.geshi_code .me1 {color: #660066;} .javascript.geshi_code span.xtra { display:block; }
{
  "name": "MyFirstChromeExtension",
  "version": "0.1",
  "description": "Description of my extension",
  "permissions": ["webRequest", "webRequestBlocking", "cookies",
          "*://mysite.com/*", "*://api.service.com/*"],
  "background": {
    "scripts": ["background.js"]
  },

  "manifest_version": 2
}


Файл background.js:
/** * GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann * (http://qbnz.com/highlighter/ and http://geshi.org/) */ .javascript.geshi_code {font-family:monospace;} .javascript.geshi_code .imp {font-weight: bold; color: red;} .javascript.geshi_code .kw1 {color: #000066; font-weight: bold;} .javascript.geshi_code .kw2 {color: #003366; font-weight: bold;} .javascript.geshi_code .kw3 {color: #000066;} .javascript.geshi_code .co1 {color: #006600; font-style: italic;} .javascript.geshi_code .co2 {color: #009966; font-style: italic;} .javascript.geshi_code .coMULTI {color: #006600; font-style: italic;} .javascript.geshi_code .es0 {color: #000099; font-weight: bold;} .javascript.geshi_code .br0 {color: #009900;} .javascript.geshi_code .sy0 {color: #339933;} .javascript.geshi_code .st0 {color: #3366CC;} .javascript.geshi_code .nu0 {color: #CC0000;} .javascript.geshi_code .me1 {color: #660066;} .javascript.geshi_code span.xtra { display:block; }
var newlink = false;
function setLink() {
  var req = new XMLHttpRequest();
  // открываем синхронный запрос к API нашего сервиса
  req.open('GET', 'http://api.service.com', false);
  req.onload = function() {
    // API в заголовках ответа, в "кастомном" заголовке
    // Link-Url присылает нам нужную ссылку
    // + одновременно при этом сервер ставит кукисы "newlink"
    // для домена api.service.com, в которых сохраняет
    // полученный адрес ссылки
    newlink = this.getResponseHeader('Link-Url');
  };
  req.send(null);
  return newlink;
}
function getLink() {
  // смотрим, есть ли у нас в кукисах сохранённый адрес нужной ссылки
  // Если есть - берём его. В противном случае выполняем запрос к API сервиса
  chrome.cookies.get({url:'http://api.service.com', name:'newlink'}, function(cook) {
    if ( ! cook)
      return setLink();
    else
      return cook.value;
  });
}
chrome.webRequest.onBeforeRequest.addListener(
  function(info) {
    // отключаем перехватывание запросов к нашему API
    if(info.url.indexOf('api.service.com') != -1)
      return {cancel:false};
   
    var link = getLink();

    return {redirectUrl: info.url.replace(/mysite.com/i, link)};
  },
  // filters
  {
    urls: [
      "*://mysite.com/*",
      "*://api.service.com/*"
    ]
  },
  // extraInfoSpec
  ["blocking"]
);


Всё прекрасно получается, кроме одного момента: callback-функция для onBeforeRequest отрабатывает, возвращает redirectUrl раньше, чем функция getLink() возвращает нужное значение ссылки. В итоге адрес хоста mysite.com подменяется на undefined. И это несмотря на то, что в функции setLink() объект XMLHttpRequest открывает синхронное соединение.

Где моя ошибка, подскажите?

API всё возвращает правильно, заголовок Access-Control-Allow-Origin: * в ответе стоит, кукисы ставятся нормально - с этим проблем нет. Т.е. при второй и последующих попытках обращения к mysite.com значение ссылки берётся уже из кукисов и всё отрабатывает как надо, хост подменяется.

Описание объекта webRequest
Описание объекта cookies

1 ответов