Что ж, клонировать запрос на выборку легко, не так ли? Fetch предоставляет готовое решение для этого, верно? Ну да и нет.

Request.clone() выполняет работу для точного клона. Но чаще всего он нам не нужен. Что нам нужно, так это отправить тот же запрос на другой ресурс (URL). Так почему бы не использовать очевидное решение? Используйте конструктор.

async function implicitClone(){
    const request = new Request(api_url_old, {method:'POST', body:JSON.stringify({'test':'test'}), headers: new Headers({
        'Content-Type': 'application/json'
    })})
    const clonedRequest =  new Request(api_url,request);
    await fetch(clonedRequest);
}

Он отлично работает, когда нет тела запроса. Но когда есть тело, текущие браузеры борются. По крайней мере Хром и Файрфокс. (Ну, это примерно 80% использования!). В то время как Firefox молча удаляет тело запроса в клонированном запросе, Chrome жалуется еще до отправки запроса. (Для получения дополнительной информации https://github.com/whatwg/fetch/issues/1486)

support.js:85 Uncaught (in promise) TypeError: Failed to construct 'Request': The `duplex` member must be specified for a request with a streaming body
    at implicitClone (support.js:85:28)
    at HTMLButtonElement.onclick (index.html:12:36)

Итак, давайте попробуем явно клонировать запрос.

async function explicitClone(){
    const request = new Request(api_url_old, {method:'POST', body:JSON.stringify({'test':'test'}), headers: new Headers({
        'Content-Type': 'application/json'
    })})
    const clonedRequest =  new Request(api_url, {
        method: request.method,
        headers: request.headers,
        body: request.body,
        referrer: request.referrer,
        referrerPolicy: request.referrerPolicy,
        mode: request.mode,
        credentials: request.credentials,
        cache: request.cache,
        redirect: request.redirect,
        integrity: request.integrity,
      });
     await fetch(clonedRequest);
}

Очень жаль! Тем не менее, у нас та же проблема. Несмотря на то, что спецификация выборки четко описывает клонирование запросов, веб-браузеры еще не существуют.

Тело запроса в Fetch состоит из ReadableStream‹Uint8Array›. Мы можем изучить Readable Stream, чтобы создать его клон. Давайте возьмем большие пушки.

async function getContentOfReadableStream(requestBody: ReadableStream<Uint8Array> | null):  Promise<Uint8Array | null>{

        if(requestBody){
            let isPending = true;
            let arrayLegnth = 0;
            const unit8Arrays = []
            const reader = requestBody.getReader();
            do{
                const readableResults =  await reader.read();

                if(readableResults.value){
                    arrayLegnth +=  readableResults.value.length 
                    unit8Arrays.push(readableResults.value)
                }
               
                isPending = !readableResults.done
            }while(isPending)
            const mergedArray = new Uint8Array(arrayLegnth);
            unit8Arrays.forEach(array=> mergedArray.set(array))
            return mergedArray;
    
        }
        return null;
    }

async function explicitCloneEnhanced() {

    const request = new Request(api_url_old, {method:'POST', body:JSON.stringify({'test':'test'}), headers: new Headers({
        'Content-Type': 'application/json'
    })})
    const requestBody = await getContentOfReadableStream(request.clone().body)
    const clonedRequest =  new Request(api_url, {
        method: request.method,
        headers: request.headers,
        body: requestBody,
        referrer: request.referrer,
        referrerPolicy: request.referrerPolicy,
        mode: request.mode,
        credentials: request.credentials,
        cache: request.cache,
        redirect: request.redirect,
        integrity: request.integrity,
      });
     await fetch(clonedRequest);

}

Эй! Firefox и Chrome больше не жалуются. Ну, тут не на что жаловаться. Наконец-то мы всех порадовали. Решение было протестировано в нескольких браузерах в разных версиях с разными типами тел запросов, и оно работает отлично. Теоретически это немного медленнее, чем готовые решения, но выполняет свою работу.

Удачного кодирования, ребята! ✌️