mirror of
https://github.com/elastic/kibana.git
synced 2025-06-27 18:51:07 -04:00
Add support for PATCH requests in Console (#165634)
## Summary
This PR adds support for PATCH requests in Console.

Closes #154274
### Checklist
- [x]
[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)
was added for features that require explanation or tutorials
- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
### For maintainers
- [x] This was checked for breaking API changes and was [labeled
appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)
## Release note
Adds support for PATCH requests in Console.
---------
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
fac644cc49
commit
b46a737703
11 changed files with 47 additions and 12 deletions
|
@ -53,6 +53,8 @@ Calls to the API endpoints require different operations. To interact with the {k
|
|||
|
||||
* *PUT* - Updates the existing information.
|
||||
|
||||
* *PATCH* - Applies partial modifications to the existing information.
|
||||
|
||||
* *DELETE* - Removes the information.
|
||||
|
||||
[float]
|
||||
|
|
|
@ -2090,6 +2090,12 @@ ace.define(
|
|||
case 'p':
|
||||
next('p');
|
||||
switch (ch) {
|
||||
case 'a':
|
||||
next('a');
|
||||
next('t');
|
||||
next('c');
|
||||
next('h');
|
||||
return 'patch';
|
||||
case 'u':
|
||||
next('u');
|
||||
next('t');
|
||||
|
@ -2106,6 +2112,12 @@ ace.define(
|
|||
case 'P':
|
||||
next('P');
|
||||
switch (ch) {
|
||||
case 'A':
|
||||
next('A');
|
||||
next('T');
|
||||
next('C');
|
||||
next('H');
|
||||
return 'PATCH';
|
||||
case 'U':
|
||||
next('U');
|
||||
next('T');
|
||||
|
@ -2120,7 +2132,7 @@ ace.define(
|
|||
}
|
||||
break;
|
||||
default:
|
||||
error('Expected one of GET/POST/PUT/DELETE/HEAD');
|
||||
error('Expected one of GET/POST/PUT/DELETE/HEAD/PATCH');
|
||||
}
|
||||
},
|
||||
value, // Place holder for the value function.
|
||||
|
@ -2254,7 +2266,7 @@ ace.define(
|
|||
annotate('error', e.message);
|
||||
// snap
|
||||
const substring = text.substr(at);
|
||||
const nextMatch = substring.search(/^POST|HEAD|GET|PUT|DELETE/m);
|
||||
const nextMatch = substring.search(/^POST|HEAD|GET|PUT|DELETE|PATCH/m);
|
||||
if (nextMatch < 1) return;
|
||||
reset(at + nextMatch);
|
||||
}
|
||||
|
|
|
@ -38,13 +38,13 @@ export function parseCURL(text: string) {
|
|||
const EscapedQuotes = /^((?:[^\\"']|\\.)+)/;
|
||||
|
||||
const LooksLikeCurl = /^\s*curl\s+/;
|
||||
const CurlVerb = /-X ?(GET|HEAD|POST|PUT|DELETE)/;
|
||||
const CurlVerb = /-X ?(GET|HEAD|POST|PUT|DELETE|PATCH)/;
|
||||
|
||||
const HasProtocol = /[\s"']https?:\/\//;
|
||||
const CurlRequestWithProto = /[\s"']https?:\/\/[^\/ ]+\/+([^\s"']+)/;
|
||||
const CurlRequestWithoutProto = /[\s"'][^\/ ]+\/+([^\s"']+)/;
|
||||
const CurlData = /^.+\s(--data|-d)\s*/;
|
||||
const SenseLine = /^\s*(GET|HEAD|POST|PUT|DELETE)\s+\/?(.+)/;
|
||||
const SenseLine = /^\s*(GET|HEAD|POST|PUT|DELETE|PATCH)\s+\/?(.+)/;
|
||||
|
||||
if (lines.length > 0 && ExecutionComment.test(lines[0])) {
|
||||
lines.shift();
|
||||
|
|
|
@ -985,7 +985,7 @@ describe('Integration', () => {
|
|||
{
|
||||
name: 'Cursor rows after request end',
|
||||
cursor: { lineNumber: 5, column: 1 },
|
||||
autoCompleteSet: ['GET', 'PUT', 'POST', 'DELETE', 'HEAD'],
|
||||
autoCompleteSet: ['GET', 'PUT', 'POST', 'DELETE', 'HEAD', 'PATCH'],
|
||||
prefixToAdd: '',
|
||||
suffixToAdd: ' ',
|
||||
},
|
||||
|
|
|
@ -967,7 +967,7 @@ export default function ({
|
|||
}
|
||||
|
||||
function addMethodAutoCompleteSetToContext(context: AutoCompleteContext) {
|
||||
context.autoCompleteSet = ['GET', 'PUT', 'POST', 'DELETE', 'HEAD'].map((m, i) => ({
|
||||
context.autoCompleteSet = ['GET', 'PUT', 'POST', 'DELETE', 'HEAD', 'PATCH'].map((m, i) => ({
|
||||
name: m,
|
||||
score: -i,
|
||||
meta: i18n.translate('console.autocomplete.addMethodMetaText', { defaultMessage: 'method' }),
|
||||
|
|
|
@ -33,7 +33,7 @@ export class UrlPatternMatcher {
|
|||
// We'll group endpoints by the methods which are attached to them,
|
||||
//to avoid suggesting endpoints that are incompatible with the
|
||||
//method that the user has entered.
|
||||
['HEAD', 'GET', 'PUT', 'POST', 'DELETE'].forEach((method) => {
|
||||
['HEAD', 'GET', 'PUT', 'POST', 'DELETE', 'PATCH'].forEach((method) => {
|
||||
this[method] = {
|
||||
rootComponent: new SharedComponent('ROOT'),
|
||||
parametrizedComponentFactories: parametrizedComponentFactories || {
|
||||
|
|
|
@ -38,13 +38,13 @@ export function parseCURL(text) {
|
|||
const EscapedQuotes = /^((?:[^\\"']|\\.)+)/;
|
||||
|
||||
const LooksLikeCurl = /^\s*curl\s+/;
|
||||
const CurlVerb = /-X ?(GET|HEAD|POST|PUT|DELETE)/;
|
||||
const CurlVerb = /-X ?(GET|HEAD|POST|PUT|DELETE|PATCH)/;
|
||||
|
||||
const HasProtocol = /[\s"']https?:\/\//;
|
||||
const CurlRequestWithProto = /[\s"']https?:\/\/[^\/ ]+\/+([^\s"']+)/;
|
||||
const CurlRequestWithoutProto = /[\s"'][^\/ ]+\/+([^\s"']+)/;
|
||||
const CurlData = /^.+\s(--data|-d)\s*/;
|
||||
const SenseLine = /^\s*(GET|HEAD|POST|PUT|DELETE)\s+\/?(.+)/;
|
||||
const SenseLine = /^\s*(GET|HEAD|POST|PUT|DELETE|PATCH)\s+\/?(.+)/;
|
||||
|
||||
if (lines.length > 0 && ExecutionComment.test(lines[0])) {
|
||||
lines.shift();
|
||||
|
|
|
@ -90,5 +90,11 @@ describe('Console Proxy Route', () => {
|
|||
});
|
||||
});
|
||||
});
|
||||
describe('PATCH request', () => {
|
||||
it('returns the exact body', async () => {
|
||||
const { payload } = await request('PATCH', '/', 'foobar');
|
||||
expect(await readStream(payload)).toBe('foobar');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -13,11 +13,11 @@ export type Body = TypeOf<typeof routeValidationConfig.body>;
|
|||
|
||||
const acceptedHttpVerb = schema.string({
|
||||
validate: (method) => {
|
||||
return ['HEAD', 'GET', 'POST', 'PUT', 'DELETE'].some(
|
||||
return ['HEAD', 'GET', 'POST', 'PUT', 'DELETE', 'PATCH'].some(
|
||||
(verb) => verb.toLowerCase() === method.toLowerCase()
|
||||
)
|
||||
? undefined
|
||||
: `Method must be one of, case insensitive ['HEAD', 'GET', 'POST', 'PUT', 'DELETE']. Received '${method}'.`;
|
||||
: `Method must be one of, case insensitive ['HEAD', 'GET', 'POST', 'PUT', 'DELETE', 'PATCH']. Received '${method}'.`;
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
it('HTTP methods', async () => {
|
||||
const suggestions = {
|
||||
G: ['GET'],
|
||||
P: ['PUT', 'POST'],
|
||||
P: ['PUT', 'POST', 'PATCH'],
|
||||
D: ['DELETE'],
|
||||
H: ['HEAD'],
|
||||
};
|
||||
|
@ -234,6 +234,8 @@ GET _search
|
|||
dELETE dELETe dELEtE dELEte dELeTE dELeTe dELetE dELete dElETE dElETe dElEtE dElEte dEleTE dEleTe dEletE dElete
|
||||
deLETE deLETe deLEtE deLEte deLeTE deLeTe deLetE deLete delETE delETe delEtE delEte deleTE deleTe deletE delete
|
||||
HEAD HEAd HEaD HEad HeAD HeAd HeaD Head hEAD hEAd hEaD hEad heAD heAd heaD head
|
||||
PATCH PATCh PATcH PATch PAtCH PAtCh PAtcH PAtch PaTCH PaTCh PaTcH PaTch PatCH PatCh PatcH Patch pATCH pATCh pATcH
|
||||
pATch pAtCH pAtCh pAtcH pAtch paTCH paTCh paTcH paTch patCH patCh patcH patch
|
||||
`.split(/\s+/m)
|
||||
),
|
||||
20 // 20 of 112 (approx. one-fifth) should be enough for testing
|
||||
|
|
|
@ -68,6 +68,19 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
expect(initialSize.width).to.be.greaterThan(afterSize.width);
|
||||
});
|
||||
|
||||
it('should return statusCode 400 to unsupported HTTP verbs', async () => {
|
||||
const expectedResponseContains = '"statusCode": 400';
|
||||
await PageObjects.console.enterRequest('\n OPTIONS /');
|
||||
await PageObjects.console.clickPlay();
|
||||
await retry.try(async () => {
|
||||
const actualResponse = await PageObjects.console.getResponse();
|
||||
log.debug(actualResponse);
|
||||
expect(actualResponse).to.contain(expectedResponseContains);
|
||||
|
||||
expect(await PageObjects.console.hasSuccessBadge()).to.be(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('with kbn: prefix in request', () => {
|
||||
before(async () => {
|
||||
await PageObjects.console.clearTextArea();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue