Skip to content

Instantly share code, notes, and snippets.

@asaaki
Created September 17, 2020 13:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save asaaki/7f9117329332cc910449dd4968f300e5 to your computer and use it in GitHub Desktop.
Save asaaki/7f9117329332cc910449dd4968f300e5 to your computer and use it in GitHub Desktop.
fetch and no-cors, a difficult story
// Fetch - readable on origin only (it does make the call though)
let res = await (async () => {
const url = "https://markentier.tech/feed.json";
// const url = "https://dummy.restapiexample.com/api/v1/employee/9";
const res = await fetch(url, { mode: "no-cors" });
if(res.ok && res.status === 200) {
const body = await res.json();
return {body}
// const headers = Object.fromEntries(res.headers);
// return { body, headers }
}
return { error: "nope", res }
})()
res // Response type=opaque
// no body or anything useful 😭
// XHR - works everywhere - yay!
const xhrFetch = (() => {
const splitOnce = (input, delim = ": ") => {
const parts = input.split(delim);
const left = parts.shift();
const right = parts.join(delim);
return [left, right];
};
const headerMap = (headerArray, init = {}) => {
return headerArray.reduce((acc, line) => {
const [header, value] = splitOnce(line, ": ");
acc[header] = value;
return acc;
}, init);
};
return async (url, overrideMimeType = "application/json") => {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.overrideMimeType(overrideMimeType);
xhr.onload = () => {
if (xhr.status === 200) {
// https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/getAllResponseHeaders
const rawHeaders = xhr.getAllResponseHeaders();
const headerArray = rawHeaders.trim().split(/[\r\n]+/);
const headers = headerMap(headerArray);
// return a Response to be compatible with `fetch`
// https://developer.mozilla.org/en-US/docs/Web/API/Response
const response = new Response(xhr.responseText, {
status: xhr.status,
statusText: xhr.statusText,
headers,
});
resolve(response);
} else {
reject({ failed: xhr.statusText });
}
};
xhr.onerror = () => reject({ error: xhr.statusText });
xhr.onabort = () => reject({ abort: xhr.statusText });
xhr.ontimeout = () => reject({ timeout: xhr.statusText });
xhr.open("GET", url, true);
xhr.send();
});
};
})();
const url = "https://markentier.tech/feed.json";
let res = await xhrFetch(url);
let json = await res.json();
let headers = Object.fromEntries(res.headers);
let r = {json, headers};
r
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment