mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 16:40:24 +08:00 
			
		
		
		
	Use fetch helpers instead of fetch (#27026)
WIP because: - [x] Some calls set a `content-type` but send no body, can likely remove the header - [x] Need to check whether `charset=utf-8` has any significance on the webauthn calls, I assume not as it is the default for json content. - [x] Maybe `no-restricted-globals` is better for eslint, but will require a lot of duplication in the yaml or moving eslint config to a `.js` extension. - [x] Maybe export `request` as `fetch`, shadowing the global.
This commit is contained in:
		@@ -2,6 +2,7 @@
 | 
			
		||||
import {createApp, nextTick} from 'vue';
 | 
			
		||||
import $ from 'jquery';
 | 
			
		||||
import {SvgIcon} from '../svg.js';
 | 
			
		||||
import {GET} from '../modules/fetch.js';
 | 
			
		||||
 | 
			
		||||
const {appSubUrl, assetUrlPrefix, pageData} = window.config;
 | 
			
		||||
 | 
			
		||||
@@ -233,11 +234,11 @@ const sfc = {
 | 
			
		||||
      try {
 | 
			
		||||
        if (!this.reposTotalCount) {
 | 
			
		||||
          const totalCountSearchURL = `${this.subUrl}/repo/search?count_only=1&uid=${this.uid}&team_id=${this.teamId}&q=&page=1&mode=`;
 | 
			
		||||
          response = await fetch(totalCountSearchURL);
 | 
			
		||||
          response = await GET(totalCountSearchURL);
 | 
			
		||||
          this.reposTotalCount = response.headers.get('X-Total-Count');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        response = await fetch(searchedURL);
 | 
			
		||||
        response = await GET(searchedURL);
 | 
			
		||||
        json = await response.json();
 | 
			
		||||
      } catch {
 | 
			
		||||
        if (searchedURL === this.searchURL) {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
<script>
 | 
			
		||||
import {SvgIcon} from '../svg.js';
 | 
			
		||||
import {GET} from '../modules/fetch.js';
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  components: {SvgIcon},
 | 
			
		||||
@@ -123,7 +124,7 @@ export default {
 | 
			
		||||
    },
 | 
			
		||||
    /** Load the commits to show in this dropdown */
 | 
			
		||||
    async fetchCommits() {
 | 
			
		||||
      const resp = await fetch(`${this.issueLink}/commits/list`);
 | 
			
		||||
      const resp = await GET(`${this.issueLink}/commits/list`);
 | 
			
		||||
      const results = await resp.json();
 | 
			
		||||
      this.commits.push(...results.commits.map((x) => {
 | 
			
		||||
        x.hovered = false;
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,7 @@ import $ from 'jquery';
 | 
			
		||||
import {SvgIcon} from '../svg.js';
 | 
			
		||||
import {pathEscapeSegments} from '../utils/url.js';
 | 
			
		||||
import {showErrorToast} from '../modules/toast.js';
 | 
			
		||||
import {GET} from '../modules/fetch.js';
 | 
			
		||||
 | 
			
		||||
const sfc = {
 | 
			
		||||
  components: {SvgIcon},
 | 
			
		||||
@@ -190,8 +191,7 @@ const sfc = {
 | 
			
		||||
      }
 | 
			
		||||
      this.isLoading = true;
 | 
			
		||||
      try {
 | 
			
		||||
        const reqUrl = `${this.repoLink}/${this.mode}/list`;
 | 
			
		||||
        const resp = await fetch(reqUrl);
 | 
			
		||||
        const resp = await GET(`${this.repoLink}/${this.mode}/list`);
 | 
			
		||||
        const {results} = await resp.json();
 | 
			
		||||
        for (const result of results) {
 | 
			
		||||
          let selected = false;
 | 
			
		||||
 
 | 
			
		||||
@@ -11,6 +11,7 @@ import {htmlEscape} from 'escape-goat';
 | 
			
		||||
import {showTemporaryTooltip} from '../modules/tippy.js';
 | 
			
		||||
import {confirmModal} from './comp/ConfirmModal.js';
 | 
			
		||||
import {showErrorToast} from '../modules/toast.js';
 | 
			
		||||
import {request} from '../modules/fetch.js';
 | 
			
		||||
 | 
			
		||||
const {appUrl, appSubUrl, csrfToken, i18n} = window.config;
 | 
			
		||||
 | 
			
		||||
@@ -81,7 +82,7 @@ function fetchActionDoRedirect(redirect) {
 | 
			
		||||
 | 
			
		||||
async function fetchActionDoRequest(actionElem, url, opt) {
 | 
			
		||||
  try {
 | 
			
		||||
    const resp = await fetch(url, opt);
 | 
			
		||||
    const resp = await request(url, opt);
 | 
			
		||||
    if (resp.status === 200) {
 | 
			
		||||
      let {redirect} = await resp.json();
 | 
			
		||||
      redirect = redirect || actionElem.getAttribute('data-redirect');
 | 
			
		||||
@@ -127,7 +128,7 @@ async function formFetchAction(e) {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  let reqUrl = formActionUrl;
 | 
			
		||||
  const reqOpt = {method: formMethod.toUpperCase(), headers: {'X-Csrf-Token': csrfToken}};
 | 
			
		||||
  const reqOpt = {method: formMethod.toUpperCase()};
 | 
			
		||||
  if (formMethod.toLowerCase() === 'get') {
 | 
			
		||||
    const params = new URLSearchParams();
 | 
			
		||||
    for (const [key, value] of formData) {
 | 
			
		||||
@@ -264,7 +265,7 @@ async function linkAction(e) {
 | 
			
		||||
  const url = el.getAttribute('data-url');
 | 
			
		||||
  const doRequest = async () => {
 | 
			
		||||
    el.disabled = true;
 | 
			
		||||
    await fetchActionDoRequest(el, url, {method: 'POST', headers: {'X-Csrf-Token': csrfToken}});
 | 
			
		||||
    await fetchActionDoRequest(el, url, {method: 'POST'});
 | 
			
		||||
    el.disabled = false;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,8 @@
 | 
			
		||||
import $ from 'jquery';
 | 
			
		||||
import {isElemHidden, onInputDebounce, toggleElem} from '../utils/dom.js';
 | 
			
		||||
const {appSubUrl} = window.config;
 | 
			
		||||
import {GET} from '../modules/fetch.js';
 | 
			
		||||
 | 
			
		||||
const {appSubUrl} = window.config;
 | 
			
		||||
const reIssueIndex = /^(\d+)$/; // eg: "123"
 | 
			
		||||
const reIssueSharpIndex = /^#(\d+)$/; // eg: "#123"
 | 
			
		||||
const reIssueOwnerRepoIndex = /^([-.\w]+)\/([-.\w]+)#(\d+)$/;  // eg: "{owner}/{repo}#{index}"
 | 
			
		||||
@@ -54,7 +55,7 @@ export function initCommonIssueListQuickGoto() {
 | 
			
		||||
    // try to check whether the parsed goto link is valid
 | 
			
		||||
    let targetUrl = parseIssueListQuickGotoLink(repoLink, searchText);
 | 
			
		||||
    if (targetUrl) {
 | 
			
		||||
      const res = await fetch(`${targetUrl}/info`);
 | 
			
		||||
      const res = await GET(`${targetUrl}/info`);
 | 
			
		||||
      if (res.status !== 200) targetUrl = '';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,16 +1,11 @@
 | 
			
		||||
import $ from 'jquery';
 | 
			
		||||
 | 
			
		||||
const {csrfToken} = window.config;
 | 
			
		||||
import {POST} from '../../modules/fetch.js';
 | 
			
		||||
 | 
			
		||||
async function uploadFile(file, uploadUrl) {
 | 
			
		||||
  const formData = new FormData();
 | 
			
		||||
  formData.append('file', file, file.name);
 | 
			
		||||
 | 
			
		||||
  const res = await fetch(uploadUrl, {
 | 
			
		||||
    method: 'POST',
 | 
			
		||||
    headers: {'X-Csrf-Token': csrfToken},
 | 
			
		||||
    body: formData,
 | 
			
		||||
  });
 | 
			
		||||
  const res = await POST(uploadUrl, {data: formData});
 | 
			
		||||
  return await res.json();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,5 @@
 | 
			
		||||
import $ from 'jquery';
 | 
			
		||||
 | 
			
		||||
const {csrfToken} = window.config;
 | 
			
		||||
import {POST} from '../../modules/fetch.js';
 | 
			
		||||
 | 
			
		||||
export function initCompReactionSelector($parent) {
 | 
			
		||||
  $parent.find(`.select-reaction .item.reaction, .comment-reaction-button`).on('click', async function (e) {
 | 
			
		||||
@@ -12,15 +11,8 @@ export function initCompReactionSelector($parent) {
 | 
			
		||||
    const reactionContent = $(this).attr('data-reaction-content');
 | 
			
		||||
    const hasReacted = $(this).closest('.ui.segment.reactions').find(`a[data-reaction-content="${reactionContent}"]`).attr('data-has-reacted') === 'true';
 | 
			
		||||
 | 
			
		||||
    const res = await fetch(`${actionUrl}/${hasReacted ? 'unreact' : 'react'}`, {
 | 
			
		||||
      method: 'POST',
 | 
			
		||||
      headers: {
 | 
			
		||||
        'content-type': 'application/x-www-form-urlencoded',
 | 
			
		||||
      },
 | 
			
		||||
      body: new URLSearchParams({
 | 
			
		||||
        _csrf: csrfToken,
 | 
			
		||||
        content: reactionContent,
 | 
			
		||||
      }),
 | 
			
		||||
    const res = await POST(`${actionUrl}/${hasReacted ? 'unreact' : 'react'}`, {
 | 
			
		||||
      data: new URLSearchParams({content: reactionContent}),
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    const data = await res.json();
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
import {clippie} from 'clippie';
 | 
			
		||||
import {showTemporaryTooltip} from '../modules/tippy.js';
 | 
			
		||||
import {convertImage} from '../utils.js';
 | 
			
		||||
import {GET} from '../modules/fetch.js';
 | 
			
		||||
 | 
			
		||||
const {i18n} = window.config;
 | 
			
		||||
 | 
			
		||||
@@ -20,7 +21,7 @@ export function initCopyContent() {
 | 
			
		||||
    if (link) {
 | 
			
		||||
      btn.classList.add('is-loading', 'small-loading-icon');
 | 
			
		||||
      try {
 | 
			
		||||
        const res = await fetch(link, {credentials: 'include', redirect: 'follow'});
 | 
			
		||||
        const res = await GET(link, {credentials: 'include', redirect: 'follow'});
 | 
			
		||||
        const contentType = res.headers.get('content-type');
 | 
			
		||||
 | 
			
		||||
        if (contentType.startsWith('image/') && !contentType.startsWith('image/svg')) {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
import $ from 'jquery';
 | 
			
		||||
import {hideElem, showElem} from '../utils/dom.js';
 | 
			
		||||
import {GET} from '../modules/fetch.js';
 | 
			
		||||
 | 
			
		||||
export function initInstall() {
 | 
			
		||||
  const $page = $('.page-content.install');
 | 
			
		||||
@@ -111,7 +112,7 @@ function initPostInstall() {
 | 
			
		||||
  const targetUrl = el.getAttribute('href');
 | 
			
		||||
  let tid = setInterval(async () => {
 | 
			
		||||
    try {
 | 
			
		||||
      const resp = await fetch(targetUrl);
 | 
			
		||||
      const resp = await GET(targetUrl);
 | 
			
		||||
      if (tid && resp.status === 200) {
 | 
			
		||||
        clearInterval(tid);
 | 
			
		||||
        tid = null;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,8 @@
 | 
			
		||||
import {diffTreeStore} from '../modules/stores.js';
 | 
			
		||||
import {setFileFolding} from './file-fold.js';
 | 
			
		||||
import {POST} from '../modules/fetch.js';
 | 
			
		||||
 | 
			
		||||
const {csrfToken, pageData} = window.config;
 | 
			
		||||
const {pageData} = window.config;
 | 
			
		||||
const prReview = pageData.prReview || {};
 | 
			
		||||
const viewedStyleClass = 'viewed-file-checked-form';
 | 
			
		||||
const viewedCheckboxSelector = '.viewed-file-form'; // Selector under which all "Viewed" checkbox forms can be found
 | 
			
		||||
@@ -68,11 +69,7 @@ export function initViewedCheckboxListenerFor() {
 | 
			
		||||
      const data = {files};
 | 
			
		||||
      const headCommitSHA = form.getAttribute('data-headcommit');
 | 
			
		||||
      if (headCommitSHA) data.headCommitSHA = headCommitSHA;
 | 
			
		||||
      fetch(form.getAttribute('data-link'), {
 | 
			
		||||
        method: 'POST',
 | 
			
		||||
        headers: {'X-Csrf-Token': csrfToken},
 | 
			
		||||
        body: JSON.stringify(data),
 | 
			
		||||
      });
 | 
			
		||||
      POST(form.getAttribute('data-link'), {data});
 | 
			
		||||
 | 
			
		||||
      // Fold the file accordingly
 | 
			
		||||
      const parentBox = form.closest('.diff-file-header');
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,10 @@
 | 
			
		||||
import {hideElem, showElem, toggleElem} from '../utils/dom.js';
 | 
			
		||||
import {GET} from '../modules/fetch.js';
 | 
			
		||||
 | 
			
		||||
async function loadBranchesAndTags(area, loadingButton) {
 | 
			
		||||
  loadingButton.classList.add('disabled');
 | 
			
		||||
  try {
 | 
			
		||||
    const res = await fetch(loadingButton.getAttribute('data-fetch-url'));
 | 
			
		||||
    const res = await GET(loadingButton.getAttribute('data-fetch-url'));
 | 
			
		||||
    const data = await res.json();
 | 
			
		||||
    hideElem(loadingButton);
 | 
			
		||||
    addTags(area, data.tags);
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,7 @@ import {htmlEscape} from 'escape-goat';
 | 
			
		||||
import {confirmModal} from './comp/ConfirmModal.js';
 | 
			
		||||
import {showErrorToast} from '../modules/toast.js';
 | 
			
		||||
import {createSortable} from '../modules/sortable.js';
 | 
			
		||||
import {DELETE, POST} from '../modules/fetch.js';
 | 
			
		||||
 | 
			
		||||
function initRepoIssueListCheckboxes() {
 | 
			
		||||
  const $issueSelectAll = $('.issue-checkbox-all');
 | 
			
		||||
@@ -146,13 +147,7 @@ function initPinRemoveButton() {
 | 
			
		||||
      const id = Number(el.getAttribute('data-issue-id'));
 | 
			
		||||
 | 
			
		||||
      // Send the unpin request
 | 
			
		||||
      const response = await fetch(el.getAttribute('data-unpin-url'), {
 | 
			
		||||
        method: 'delete',
 | 
			
		||||
        headers: {
 | 
			
		||||
          'X-Csrf-Token': window.config.csrfToken,
 | 
			
		||||
          'Content-Type': 'application/json',
 | 
			
		||||
        },
 | 
			
		||||
      });
 | 
			
		||||
      const response = await DELETE(el.getAttribute('data-unpin-url'));
 | 
			
		||||
      if (response.ok) {
 | 
			
		||||
        // Delete the tooltip
 | 
			
		||||
        el._tippy.destroy();
 | 
			
		||||
@@ -166,14 +161,7 @@ function initPinRemoveButton() {
 | 
			
		||||
async function pinMoveEnd(e) {
 | 
			
		||||
  const url = e.item.getAttribute('data-move-url');
 | 
			
		||||
  const id = Number(e.item.getAttribute('data-issue-id'));
 | 
			
		||||
  await fetch(url, {
 | 
			
		||||
    method: 'post',
 | 
			
		||||
    body: JSON.stringify({id, position: e.newIndex + 1}),
 | 
			
		||||
    headers: {
 | 
			
		||||
      'X-Csrf-Token': window.config.csrfToken,
 | 
			
		||||
      'Content-Type': 'application/json',
 | 
			
		||||
    },
 | 
			
		||||
  });
 | 
			
		||||
  await POST(url, {data: {id, position: e.newIndex + 1}});
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function initIssuePinSort() {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,8 @@
 | 
			
		||||
import $ from 'jquery';
 | 
			
		||||
import {hideElem, showElem} from '../utils/dom.js';
 | 
			
		||||
import {GET, POST} from '../modules/fetch.js';
 | 
			
		||||
 | 
			
		||||
const {appSubUrl, csrfToken} = window.config;
 | 
			
		||||
const {appSubUrl} = window.config;
 | 
			
		||||
 | 
			
		||||
export function initRepoMigrationStatusChecker() {
 | 
			
		||||
  const $repoMigrating = $('#repo_migrating');
 | 
			
		||||
@@ -13,7 +14,7 @@ export function initRepoMigrationStatusChecker() {
 | 
			
		||||
 | 
			
		||||
  // returns true if the refresh still need to be called after a while
 | 
			
		||||
  const refresh = async () => {
 | 
			
		||||
    const res = await fetch(`${appSubUrl}/user/task/${task}`);
 | 
			
		||||
    const res = await GET(`${appSubUrl}/user/task/${task}`);
 | 
			
		||||
    if (res.status !== 200) return true; // continue to refresh if network error occurs
 | 
			
		||||
 | 
			
		||||
    const data = await res.json();
 | 
			
		||||
@@ -58,12 +59,6 @@ export function initRepoMigrationStatusChecker() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function doMigrationRetry(e) {
 | 
			
		||||
  await fetch($(e.target).attr('data-migrating-task-retry-url'), {
 | 
			
		||||
    method: 'post',
 | 
			
		||||
    headers: {
 | 
			
		||||
      'X-Csrf-Token': csrfToken,
 | 
			
		||||
      'Content-Type': 'application/json',
 | 
			
		||||
    },
 | 
			
		||||
  });
 | 
			
		||||
  await POST($(e.target).attr('data-migrating-task-retry-url'));
 | 
			
		||||
  window.location.reload();
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,8 @@
 | 
			
		||||
import {encodeURLEncodedBase64, decodeURLEncodedBase64} from '../utils.js';
 | 
			
		||||
import {showElem} from '../utils/dom.js';
 | 
			
		||||
import {GET, POST} from '../modules/fetch.js';
 | 
			
		||||
 | 
			
		||||
const {appSubUrl, csrfToken} = window.config;
 | 
			
		||||
const {appSubUrl} = window.config;
 | 
			
		||||
 | 
			
		||||
export async function initUserAuthWebAuthn() {
 | 
			
		||||
  const elPrompt = document.querySelector('.user.signin.webauthn-prompt');
 | 
			
		||||
@@ -13,7 +14,7 @@ export async function initUserAuthWebAuthn() {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const res = await fetch(`${appSubUrl}/user/webauthn/assertion`);
 | 
			
		||||
  const res = await GET(`${appSubUrl}/user/webauthn/assertion`);
 | 
			
		||||
  if (res.status !== 200) {
 | 
			
		||||
    webAuthnError('unknown');
 | 
			
		||||
    return;
 | 
			
		||||
@@ -53,12 +54,8 @@ async function verifyAssertion(assertedCredential) {
 | 
			
		||||
  const sig = new Uint8Array(assertedCredential.response.signature);
 | 
			
		||||
  const userHandle = new Uint8Array(assertedCredential.response.userHandle);
 | 
			
		||||
 | 
			
		||||
  const res = await fetch(`${appSubUrl}/user/webauthn/assertion`, {
 | 
			
		||||
    method: 'POST',
 | 
			
		||||
    headers: {
 | 
			
		||||
      'Content-Type': 'application/json; charset=utf-8'
 | 
			
		||||
    },
 | 
			
		||||
    body: JSON.stringify({
 | 
			
		||||
  const res = await POST(`${appSubUrl}/user/webauthn/assertion`, {
 | 
			
		||||
    data: {
 | 
			
		||||
      id: assertedCredential.id,
 | 
			
		||||
      rawId: encodeURLEncodedBase64(rawId),
 | 
			
		||||
      type: assertedCredential.type,
 | 
			
		||||
@@ -69,7 +66,7 @@ async function verifyAssertion(assertedCredential) {
 | 
			
		||||
        signature: encodeURLEncodedBase64(sig),
 | 
			
		||||
        userHandle: encodeURLEncodedBase64(userHandle),
 | 
			
		||||
      },
 | 
			
		||||
    }),
 | 
			
		||||
    },
 | 
			
		||||
  });
 | 
			
		||||
  if (res.status === 500) {
 | 
			
		||||
    webAuthnError('unknown');
 | 
			
		||||
@@ -88,13 +85,8 @@ async function webauthnRegistered(newCredential) {
 | 
			
		||||
  const clientDataJSON = new Uint8Array(newCredential.response.clientDataJSON);
 | 
			
		||||
  const rawId = new Uint8Array(newCredential.rawId);
 | 
			
		||||
 | 
			
		||||
  const res = await fetch(`${appSubUrl}/user/settings/security/webauthn/register`, {
 | 
			
		||||
    method: 'POST',
 | 
			
		||||
    headers: {
 | 
			
		||||
      'X-Csrf-Token': csrfToken,
 | 
			
		||||
      'Content-Type': 'application/json; charset=utf-8',
 | 
			
		||||
    },
 | 
			
		||||
    body: JSON.stringify({
 | 
			
		||||
  const res = await POST(`${appSubUrl}/user/settings/security/webauthn/register`, {
 | 
			
		||||
    data: {
 | 
			
		||||
      id: newCredential.id,
 | 
			
		||||
      rawId: encodeURLEncodedBase64(rawId),
 | 
			
		||||
      type: newCredential.type,
 | 
			
		||||
@@ -102,7 +94,7 @@ async function webauthnRegistered(newCredential) {
 | 
			
		||||
        attestationObject: encodeURLEncodedBase64(attestationObject),
 | 
			
		||||
        clientDataJSON: encodeURLEncodedBase64(clientDataJSON),
 | 
			
		||||
      },
 | 
			
		||||
    }),
 | 
			
		||||
    },
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  if (res.status === 409) {
 | 
			
		||||
@@ -165,15 +157,11 @@ export function initUserAuthWebAuthnRegister() {
 | 
			
		||||
async function webAuthnRegisterRequest() {
 | 
			
		||||
  const elNickname = document.getElementById('nickname');
 | 
			
		||||
 | 
			
		||||
  const body = new FormData();
 | 
			
		||||
  body.append('name', elNickname.value);
 | 
			
		||||
  const formData = new FormData();
 | 
			
		||||
  formData.append('name', elNickname.value);
 | 
			
		||||
 | 
			
		||||
  const res = await fetch(`${appSubUrl}/user/settings/security/webauthn/request_register`, {
 | 
			
		||||
    method: 'POST',
 | 
			
		||||
    headers: {
 | 
			
		||||
      'X-Csrf-Token': csrfToken,
 | 
			
		||||
    },
 | 
			
		||||
    body,
 | 
			
		||||
  const res = await POST(`${appSubUrl}/user/settings/security/webauthn/request_register`, {
 | 
			
		||||
    data: formData,
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  if (res.status === 409) {
 | 
			
		||||
 
 | 
			
		||||
@@ -2,17 +2,18 @@ import {isObject} from '../utils.js';
 | 
			
		||||
 | 
			
		||||
const {csrfToken} = window.config;
 | 
			
		||||
 | 
			
		||||
// safe HTTP methods that don't need a csrf token
 | 
			
		||||
const safeMethods = new Set(['GET', 'HEAD', 'OPTIONS', 'TRACE']);
 | 
			
		||||
 | 
			
		||||
// fetch wrapper, use below method name functions and the `data` option to pass in data
 | 
			
		||||
// which will automatically set an appropriate content-type header. For json content,
 | 
			
		||||
// only object and array types are currently supported.
 | 
			
		||||
function request(url, {headers, data, body, ...other} = {}) {
 | 
			
		||||
// which will automatically set an appropriate headers. For json content, only object
 | 
			
		||||
// and array types are currently supported.
 | 
			
		||||
export function request(url, {method = 'GET', headers = {}, data, body, ...other} = {}) {
 | 
			
		||||
  let contentType;
 | 
			
		||||
  if (!body) {
 | 
			
		||||
    if (data instanceof FormData) {
 | 
			
		||||
      contentType = 'multipart/form-data';
 | 
			
		||||
      body = data;
 | 
			
		||||
    } else if (data instanceof URLSearchParams) {
 | 
			
		||||
      contentType = 'application/x-www-form-urlencoded';
 | 
			
		||||
      body = data;
 | 
			
		||||
    } else if (isObject(data) || Array.isArray(data)) {
 | 
			
		||||
      contentType = 'application/json';
 | 
			
		||||
@@ -20,12 +21,18 @@ function request(url, {headers, data, body, ...other} = {}) {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const headersMerged = new Headers({
 | 
			
		||||
    ...(!safeMethods.has(method.toUpperCase()) && {'x-csrf-token': csrfToken}),
 | 
			
		||||
    ...(contentType && {'content-type': contentType}),
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  for (const [name, value] of Object.entries(headers)) {
 | 
			
		||||
    headersMerged.set(name, value);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return fetch(url, {
 | 
			
		||||
    headers: {
 | 
			
		||||
      'x-csrf-token': csrfToken,
 | 
			
		||||
      ...(contentType && {'content-type': contentType}),
 | 
			
		||||
      ...headers,
 | 
			
		||||
    },
 | 
			
		||||
    method,
 | 
			
		||||
    headers: headersMerged,
 | 
			
		||||
    ...(body && {body}),
 | 
			
		||||
    ...other,
 | 
			
		||||
  });
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user