mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
BackendSrv: Uses credentials and defaults to same-origin (#27385)
Co-authored-by: Liu Yang yangliuyu@163.com
This commit is contained in:
@@ -62,8 +62,12 @@ export type BackendSrvRequest = {
|
|||||||
params?: Record<string, any>;
|
params?: Record<string, any>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates whether or not cross-site Access-Control requests should be made using credentials such as cookies, authorization headers or TLS client certificates. Setting withCredentials has no effect on same-site requests.
|
* The credentials read-only property of the Request interface indicates whether the user agent should send cookies from the other domain in the case of cross-origin requests.
|
||||||
* In addition, this flag is also used to indicate when cookies are to be ignored in the response.
|
*/
|
||||||
|
credentials?: RequestCredentials;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated withCredentials is deprecated in favor of credentials
|
||||||
*/
|
*/
|
||||||
withCredentials?: boolean;
|
withCredentials?: boolean;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import 'whatwg-fetch'; // fetch polyfill needed for PhantomJs rendering
|
|||||||
import {
|
import {
|
||||||
isContentTypeApplicationJson,
|
isContentTypeApplicationJson,
|
||||||
parseBody,
|
parseBody,
|
||||||
|
parseCredentials,
|
||||||
parseHeaders,
|
parseHeaders,
|
||||||
parseInitFromOptions,
|
parseInitFromOptions,
|
||||||
parseUrlFromOptions,
|
parseUrlFromOptions,
|
||||||
@@ -27,17 +28,18 @@ describe('parseUrlFromOptions', () => {
|
|||||||
|
|
||||||
describe('parseInitFromOptions', () => {
|
describe('parseInitFromOptions', () => {
|
||||||
it.each`
|
it.each`
|
||||||
method | data | withCredentials | expected
|
method | data | withCredentials | credentials | expected
|
||||||
${undefined} | ${undefined} | ${undefined} | ${{ method: undefined, headers: { map: { accept: 'application/json, text/plain, */*' } }, body: undefined }}
|
${undefined} | ${undefined} | ${undefined} | ${undefined} | ${{ method: undefined, headers: { map: { accept: 'application/json, text/plain, */*' } }, body: undefined, credentials: 'same-origin' }}
|
||||||
${'GET'} | ${undefined} | ${undefined} | ${{ method: 'GET', headers: { map: { accept: 'application/json, text/plain, */*' } }, body: undefined }}
|
${'GET'} | ${undefined} | ${undefined} | ${undefined} | ${{ method: 'GET', headers: { map: { accept: 'application/json, text/plain, */*' } }, body: undefined, credentials: 'same-origin' }}
|
||||||
${'POST'} | ${{ id: '0' }} | ${undefined} | ${{ method: 'POST', headers: { map: { 'content-type': 'application/json', accept: 'application/json, text/plain, */*' } }, body: '{"id":"0"}' }}
|
${'POST'} | ${{ id: '0' }} | ${undefined} | ${undefined} | ${{ method: 'POST', headers: { map: { 'content-type': 'application/json', accept: 'application/json, text/plain, */*' } }, body: '{"id":"0"}', credentials: 'same-origin' }}
|
||||||
${'PUT'} | ${{ id: '0' }} | ${undefined} | ${{ method: 'PUT', headers: { map: { 'content-type': 'application/json', accept: 'application/json, text/plain, */*' } }, body: '{"id":"0"}' }}
|
${'PUT'} | ${{ id: '0' }} | ${undefined} | ${undefined} | ${{ method: 'PUT', headers: { map: { 'content-type': 'application/json', accept: 'application/json, text/plain, */*' } }, body: '{"id":"0"}', credentials: 'same-origin' }}
|
||||||
${'monkey'} | ${undefined} | ${undefined} | ${{ method: 'monkey', headers: { map: { accept: 'application/json, text/plain, */*' } }, body: undefined }}
|
${'monkey'} | ${undefined} | ${undefined} | ${'omit'} | ${{ method: 'monkey', headers: { map: { accept: 'application/json, text/plain, */*' } }, body: undefined, credentials: 'omit' }}
|
||||||
${'GET'} | ${undefined} | ${true} | ${{ method: 'GET', headers: { map: { accept: 'application/json, text/plain, */*' } }, body: undefined, credentials: 'include' }}
|
${'GET'} | ${undefined} | ${true} | ${undefined} | ${{ method: 'GET', headers: { map: { accept: 'application/json, text/plain, */*' } }, body: undefined, credentials: 'include' }}
|
||||||
|
${'GET'} | ${undefined} | ${true} | ${'omit'} | ${{ method: 'GET', headers: { map: { accept: 'application/json, text/plain, */*' } }, body: undefined, credentials: 'omit' }}
|
||||||
`(
|
`(
|
||||||
"when called with method: '$method', data: '$data' and withCredentials: '$withCredentials' then result should be '$expected'",
|
"when called with method: '$method', data: '$data', withCredentials: '$withCredentials' and credentials: '$credentials' then result should be '$expected'",
|
||||||
({ method, data, withCredentials, expected }) => {
|
({ method, data, withCredentials, credentials, expected }) => {
|
||||||
expect(parseInitFromOptions({ method, data, withCredentials, url: '' })).toEqual(expected);
|
expect(parseInitFromOptions({ method, data, withCredentials, credentials, url: '' })).toEqual(expected);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -100,3 +102,28 @@ describe('parseBody', () => {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('parseCredentials', () => {
|
||||||
|
it.each`
|
||||||
|
options | expected
|
||||||
|
${undefined} | ${undefined}
|
||||||
|
${{}} | ${'same-origin'}
|
||||||
|
${{ credentials: undefined }} | ${'same-origin'}
|
||||||
|
${{ credentials: undefined, withCredentials: undefined }} | ${'same-origin'}
|
||||||
|
${{ credentials: undefined, withCredentials: false }} | ${'same-origin'}
|
||||||
|
${{ credentials: undefined, withCredentials: true }} | ${'include'}
|
||||||
|
${{ credentials: 'invalid' }} | ${'invalid'}
|
||||||
|
${{ credentials: 'invalid', withCredentials: undefined }} | ${'invalid'}
|
||||||
|
${{ credentials: 'invalid', withCredentials: false }} | ${'invalid'}
|
||||||
|
${{ credentials: 'invalid', withCredentials: true }} | ${'invalid'}
|
||||||
|
${{ credentials: 'omit' }} | ${'omit'}
|
||||||
|
${{ credentials: 'omit', withCredentials: undefined }} | ${'omit'}
|
||||||
|
${{ credentials: 'omit', withCredentials: false }} | ${'omit'}
|
||||||
|
${{ credentials: 'omit', withCredentials: true }} | ${'omit'}
|
||||||
|
`(
|
||||||
|
"when called with options: '$options' then the result should be '$expected'",
|
||||||
|
({ options, isAppJson, expected }) => {
|
||||||
|
expect(parseCredentials(options)).toEqual(expected);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|||||||
@@ -1,25 +1,19 @@
|
|||||||
import { BackendSrvRequest } from '@grafana/runtime';
|
import { BackendSrvRequest } from '@grafana/runtime';
|
||||||
import omitBy from 'lodash/omitBy';
|
import omitBy from 'lodash/omitBy';
|
||||||
|
import { deprecationWarning } from '@grafana/data';
|
||||||
|
|
||||||
export const parseInitFromOptions = (options: BackendSrvRequest): RequestInit => {
|
export const parseInitFromOptions = (options: BackendSrvRequest): RequestInit => {
|
||||||
const method = options.method;
|
const method = options.method;
|
||||||
const headers = parseHeaders(options);
|
const headers = parseHeaders(options);
|
||||||
const isAppJson = isContentTypeApplicationJson(headers);
|
const isAppJson = isContentTypeApplicationJson(headers);
|
||||||
const body = parseBody(options, isAppJson);
|
const body = parseBody(options, isAppJson);
|
||||||
|
const credentials = parseCredentials(options);
|
||||||
if (options?.withCredentials) {
|
|
||||||
return {
|
|
||||||
method,
|
|
||||||
headers,
|
|
||||||
body,
|
|
||||||
credentials: 'include',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
method,
|
method,
|
||||||
headers,
|
headers,
|
||||||
body,
|
body,
|
||||||
|
credentials,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -114,3 +108,20 @@ export const parseUrlFromOptions = (options: BackendSrvRequest): string => {
|
|||||||
const serializedParams = serializeParams(cleanParams);
|
const serializedParams = serializeParams(cleanParams);
|
||||||
return options.params && serializedParams.length ? `${options.url}?${serializedParams}` : options.url;
|
return options.params && serializedParams.length ? `${options.url}?${serializedParams}` : options.url;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const parseCredentials = (options: BackendSrvRequest): RequestCredentials => {
|
||||||
|
if (!options) {
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.credentials) {
|
||||||
|
return options.credentials;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.withCredentials) {
|
||||||
|
deprecationWarning('BackendSrvRequest', 'withCredentials', 'credentials');
|
||||||
|
return 'include';
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'same-origin';
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user