2016-01-06 9 views
10

Ich schreibe einen Wrapper um fetch, dass ich etwas an die URL hinzufügen möchte, bevor Sie die Anfrage z. Identifizieren von Abfrageparametern. Ich kann nicht herausfinden, wie man eine Kopie eines gegebenen Request Objekts mit einer anderen URL als dem Original erstellt. Mein Code sieht so aus:Wie kopiere ich ein Request-Objekt mit einer anderen URL?

// My function which tries to modify the URL of the request 
function addLangParameter(request) { 
    const newUrl = request.url + "?lang=" + lang; 
    return new Request(newUrl, /* not sure what to put here */); 
} 

// My fetch wrapper 
function myFetch(input, init) { 
    // Normalize the input into a Request object 
    return Promise.resolve(new Request(input, init)) 
     // Call my modifier function 
     .then(addLangParameter) 
     // Make the actual request 
     .then(request => fetch(request)); 
} 

Ich habe versucht, die ursprüngliche Anforderung als zweiten arguent an den Konstruktor Request setzen, etwa so:

function addLangParameter(request) { 
    const newUrl = request.url + "?lang=" + lang; 
    return new Request(newUrl, request); 
} 

die meist Attribute des alten Wunsches zu kopieren scheint aber scheint nicht die body der alten Anfrage zu bewahren. Zum Beispiel würde

const request1 = new Request("/", { method: "POST", body: "test" }); 
const request2 = new Request("/new", request1); 
request2.text().then(body => console.log(body)); 

Ich erwartet, dass „test“ protokollieren, sondern protokolliert er die leere Zeichenkette, weil der Körper über nicht kopiert wird.

Muss ich etwas expliziteres tun, um alle Attribute korrekt zu kopieren, oder gibt es eine nette Abkürzung, die etwas Sinnvolles für mich tut?

Ich benutze die github/fetch Polyfill, aber habe mit dem Polyfill und der nativen fetch Implementierung im neuesten Chrome getestet.

+0

Pseudocode nicht anzeigen: echten Code anzeigen. –

+0

@ Mike'Pomax'Kamermans Ich habe den eigentlichen Code hinzugefügt. Ich denke, es macht es schwerer, das eigentliche Problem zu verstehen, vielleicht wird es hilfreich sein. – Xymostech

+0

statt härter, Ihr neuer Code macht es tatsächlich offensichtlich, was Sie fragen, indem Sie Ihre Verwendung des Request-Objekts im Code selbst zeigen. –

Antwort

7

Es ist wie Sie am besten aussieht, ist der Körper mit der Body Schnittstelle zu lesen, die implementieren Anfragen:

https://fetch.spec.whatwg.org/#body

Dies kann nur asynchron ausgeführt werden, da die zugrunde liegenden „verbrauchen Körper“ -Betrieb immer asynchron liest und gibt ein Versprechen ab. So etwas sollte funktionieren:

const request = new Request('/old', { method: 'GET' }); 
const bodyP = request.headers.get('Content-Type') ? request.blob() : Promise.resolve(undefined); 
const newRequestP = 
    bodyP.then((body) => 
    new Request('/new', { 
     method: request.method, 
     headers: request.headers, 
     body: body, 
     referrer: request.referrer, 
     referrerPolicy: request.referrerPolicy, 
     mode: request.mode, 
     credentials: request.credentials, 
     cache: request.cache, 
     redirect: request.redirect, 
     integrity: request.integrity, 
    }) 
); 

Danach tun, newRequestP wird ein Versprechen, das auf die Anforderung löst Sie wollen. Glücklicherweise ist fetch asynchron, also sollte Ihr Wrapper dadurch nicht wesentlich behindert werden.

(Hinweis: Das Lesen des Rumpfs mit .blob() off einer Anforderung, die keinen Rumpf hat, scheint ein Blob-Objekt der Länge Null zurückzugeben, aber es ist falsch, einen Körper, sogar einen Null-Länge, auf einem GET anzugeben Ich glaube, dass die Überprüfung, ob die ursprüngliche Anfrage Content-Type gesetzt hat, ein genauer Proxy ist, ob es einen Körper hat, was wir wirklich bestimmen müssen.)

+2

Sieht so aus, als ob dies momentan nicht im Polyfill github/fetch funktioniert (was den 'Content-Type'-Header nicht richtig setzt), aber das funktioniert in Chrome großartig. Vielen Dank! – Xymostech

+0

Einige gute Informationen: https://github.com/whatwg/fetch/issues/191 – Endless