2016-02-15 67 views
6

是否可以更改由fetch事件接收的Request對象的標題?如何更改請求的標題?

兩次嘗試:

  1. 修改現有的標題:

    self.addEventListener('fetch', function (event) { 
        event.request.headers.set("foo", "bar"); 
        event.respondWith(fetch(event.request)); 
    }); 
    

    Failed to execute 'set' on 'Headers': Headers are immutable失敗。

  2. 創建新Request對象:

    self.addEventListener('fetch', function (event) { 
        var req = new Request(event.request, { 
        headers: { "foo": "bar" } 
        }); 
        event.respondWith(fetch(req)); 
    }); 
    

    Failed to construct 'Request': Cannot construct a Request with a Request whose mode is 'navigate' and a non-empty RequestInit.

失敗(也How to alter the headers of a Response?見)

回答

8

創建一個新的請求對象的工作,只要你設置的所有選項:

// request is event.request sent by browser here 
var req = new Request(request.url, { 
    method: request.method, 
    headers: request.headers, 
    mode: 'same-origin', // need to set this properly 
    credentials: request.credentials, 
    redirect: 'manual' // let browser handle redirects 
}); 

不能使用原來的mode如果navigate(這就是爲什麼你得到一個例外),你可能想要將重定向傳遞迴瀏覽器,讓它更改其URL而不是讓fetch處理它。

請確保您沒有在GET請求上設置正文 - 提取不喜歡它,但瀏覽器有時會在響應POST請求重定向時生成GET請求。 fetch不喜歡它。

+0

你碰巧知道爲什麼'navigate'的'mode'會成爲問題嗎? – mjs

+3

https://fetch.spec.whatwg.org/#dom-request的步驟12.1:「如果請求的模式是」導航「,則拋出一個TypeError。」。 – Marco

2

你有沒有試着用一個類似的解決方案你提到的問題(How to alter the headers of a Response?)?

在Service Worker Cookbook中,我們手動複製Request對象以將它們存儲在IndexedDB(https://serviceworke.rs/request-deferrer_service-worker_doc.html)中。這是出於不同原因(我們希望將它們存儲在緩存中,但由於https://github.com/slightlyoff/ServiceWorker/issues/693,我們無法存儲POST請求),但它也應該適用於您想要執行的操作。

// Serialize is a little bit convolved due to headers is not a simple object. 
function serialize(request) { 
    var headers = {}; 
    // `for(... of ...)` is ES6 notation but current browsers supporting SW, support this 
    // notation as well and this is the only way of retrieving all the headers. 
    for (var entry of request.headers.entries()) { 
    headers[entry[0]] = entry[1]; 
    } 
    var serialized = { 
    url: request.url, 
    headers: headers, 
    method: request.method, 
    mode: request.mode, 
    credentials: request.credentials, 
    cache: request.cache, 
    redirect: request.redirect, 
    referrer: request.referrer 
    }; 



    // Only if method is not `GET` or `HEAD` is the request allowed to have body. 
    if (request.method !== 'GET' && request.method !== 'HEAD') { 
    return request.clone().text().then(function(body) { 
     serialized.body = body; 
     return Promise.resolve(serialized); 
    }); 
    } 
    return Promise.resolve(serialized); 
} 

// Compared, deserialize is pretty simple. 
function deserialize(data) { 
    return Promise.resolve(new Request(data.url, data)); 
}