mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
# Backport This will backport the following commits from `main` to `8.8`: - [[Synthetics] http monitors - account for custom Content-Type headers (#159737)](https://github.com/elastic/kibana/pull/159737) <!--- Backport version: 8.9.7 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) <!--BACKPORT [{"author":{"name":"Dominique Clarke","email":"dominique.clarke@elastic.co"},"sourceCommit":{"committedDate":"2023-06-19T11:49:55Z","message":"[Synthetics] http monitors - account for custom Content-Type headers (#159737)","sha":"fc32999c91760ed399b872d507fd84d308f5829e","branchLabelMapping":{"^v8.9.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["bug","release_note:fix","Team:uptime","v8.9.0","v8.8.2"],"number":159737,"url":"https://github.com/elastic/kibana/pull/159737","mergeCommit":{"message":"[Synthetics] http monitors - account for custom Content-Type headers (#159737)","sha":"fc32999c91760ed399b872d507fd84d308f5829e"}},"sourceBranch":"main","suggestedTargetBranches":["8.8"],"targetPullRequestStates":[{"branch":"main","label":"v8.9.0","labelRegex":"^v8.9.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/159737","number":159737,"mergeCommit":{"message":"[Synthetics] http monitors - account for custom Content-Type headers (#159737)","sha":"fc32999c91760ed399b872d507fd84d308f5829e"}},{"branch":"8.8","label":"v8.8.2","labelRegex":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"}]}] BACKPORT--> Co-authored-by: Dominique Clarke <dominique.clarke@elastic.co>
This commit is contained in:
parent
d2683cba7b
commit
a7a6425553
6 changed files with 73 additions and 6 deletions
|
@ -140,3 +140,7 @@ export const ResponseCheckJSONCodec = t.interface({
|
|||
expression: t.string,
|
||||
});
|
||||
export type ResponseCheckJSON = t.TypeOf<typeof ResponseCheckJSONCodec>;
|
||||
|
||||
export const RequestBodyCheckCodec = t.interface({ value: t.string, type: CodeEditorModeCodec });
|
||||
|
||||
export type RequestBodyCheck = t.TypeOf<typeof RequestBodyCheckCodec>;
|
||||
|
|
|
@ -11,7 +11,6 @@ import { secretKeys } from '../../constants/monitor_management';
|
|||
import { ConfigKey } from './config_key';
|
||||
import { MonitorServiceLocationCodec, ServiceLocationErrors } from './locations';
|
||||
import {
|
||||
CodeEditorModeCodec,
|
||||
DataStream,
|
||||
DataStreamCodec,
|
||||
FormMonitorTypeCodec,
|
||||
|
@ -22,6 +21,7 @@ import {
|
|||
SourceTypeCodec,
|
||||
TLSVersionCodec,
|
||||
VerificationModeCodec,
|
||||
RequestBodyCheckCodec,
|
||||
} from './monitor_configs';
|
||||
import { MetadataCodec } from './monitor_meta_data';
|
||||
import { PrivateLocationCodec } from './synthetics_private_locations';
|
||||
|
@ -195,7 +195,7 @@ export const HTTPSensitiveAdvancedFieldsCodec = t.intersection([
|
|||
[ConfigKey.RESPONSE_BODY_CHECK_NEGATIVE]: t.array(t.string),
|
||||
[ConfigKey.RESPONSE_BODY_CHECK_POSITIVE]: t.array(t.string),
|
||||
[ConfigKey.RESPONSE_HEADERS_CHECK]: t.record(t.string, t.string),
|
||||
[ConfigKey.REQUEST_BODY_CHECK]: t.interface({ value: t.string, type: CodeEditorModeCodec }),
|
||||
[ConfigKey.REQUEST_BODY_CHECK]: RequestBodyCheckCodec,
|
||||
[ConfigKey.REQUEST_HEADERS_CHECK]: t.record(t.string, t.string),
|
||||
[ConfigKey.USERNAME]: t.string,
|
||||
}),
|
||||
|
|
|
@ -106,4 +106,35 @@ describe('<HeaderField />', () => {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('shows custom Content-Type', async () => {
|
||||
const contentMode: CodeEditorMode = CodeEditorMode.PLAINTEXT;
|
||||
const { getByTestId } = render(
|
||||
<HeaderField
|
||||
defaultValue={{ ...defaultValue, 'Content-Type': 'custom' }}
|
||||
onChange={onChange}
|
||||
contentMode={contentMode}
|
||||
/>
|
||||
);
|
||||
|
||||
const key = getByTestId('keyValuePairsKey0') as HTMLInputElement;
|
||||
const value = getByTestId('keyValuePairsValue0') as HTMLInputElement;
|
||||
|
||||
expect(key.value).toBe('Content-Type');
|
||||
expect(value.value).toBe('custom');
|
||||
});
|
||||
|
||||
it('hides default Content-Type', async () => {
|
||||
const contentMode: CodeEditorMode = CodeEditorMode.PLAINTEXT;
|
||||
const { queryByTestId } = render(
|
||||
<HeaderField
|
||||
defaultValue={{ ...defaultValue, 'Content-Type': 'text/plain' }}
|
||||
onChange={onChange}
|
||||
contentMode={contentMode}
|
||||
/>
|
||||
);
|
||||
|
||||
expect(queryByTestId('keyValuePairsKey0')).not.toBeInTheDocument();
|
||||
expect(queryByTestId('keyValuePairsValue0')).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -28,7 +28,9 @@ export const HeaderField = ({
|
|||
'data-test-subj': dataTestSubj,
|
||||
readOnly,
|
||||
}: HeaderFieldProps) => {
|
||||
const defaultValueKeys = Object.keys(defaultValue).filter((key) => key !== 'Content-Type'); // Content-Type is a secret header we hide from the user
|
||||
const defaultValueKeys = Object.keys(defaultValue).filter(
|
||||
filterContentType(defaultValue, contentTypes, contentMode)
|
||||
);
|
||||
const formattedDefaultValues: Pair[] = [
|
||||
...defaultValueKeys.map<Pair>((key) => {
|
||||
return [key || '', defaultValue[key] || '']; // key, value
|
||||
|
@ -72,6 +74,22 @@ export const HeaderField = ({
|
|||
);
|
||||
};
|
||||
|
||||
// We apply default `Content-Type` headers automatically depending on the request body mime type
|
||||
// We hide the default Content-Type headers from the user as an implementation detail
|
||||
// However, If the user applies a custom `Content-Type` header, it should be shown
|
||||
export const filterContentType =
|
||||
(
|
||||
defaultValue: Record<string, string>,
|
||||
contentTypeMap: Record<CodeEditorMode, ContentType>,
|
||||
contentMode?: CodeEditorMode
|
||||
) =>
|
||||
(key: string) => {
|
||||
return (
|
||||
key !== 'Content-Type' ||
|
||||
(key === 'Content-Type' && contentMode && defaultValue[key] !== contentTypeMap[contentMode])
|
||||
);
|
||||
};
|
||||
|
||||
export const contentTypes: Record<CodeEditorMode, ContentType> = {
|
||||
[CodeEditorMode.JSON]: ContentType.JSON,
|
||||
[CodeEditorMode.PLAINTEXT]: ContentType.TEXT,
|
||||
|
|
|
@ -76,6 +76,7 @@ import {
|
|||
ResponseBodyIndexPolicy,
|
||||
ResponseCheckJSON,
|
||||
ThrottlingConfig,
|
||||
RequestBodyCheck,
|
||||
} from '../types';
|
||||
import { AlertConfigKey, ALLOWED_SCHEDULES_IN_MINUTES } from '../constants';
|
||||
import { getDefaultFormFields } from './defaults';
|
||||
|
@ -718,12 +719,20 @@ export const FIELD = (readOnly?: boolean): FieldMap => ({
|
|||
validation: () => ({
|
||||
validate: (headers) => !validateHeaders(headers),
|
||||
}),
|
||||
dependencies: [ConfigKey.REQUEST_BODY_CHECK],
|
||||
error: i18n.translate('xpack.synthetics.monitorConfig.requestHeaders.error', {
|
||||
defaultMessage: 'Header key must be a valid HTTP token.',
|
||||
}),
|
||||
props: (): HeaderFieldProps => ({
|
||||
readOnly,
|
||||
}),
|
||||
// contentMode is optional for other implementations, but required for this implemention of this field
|
||||
props: ({
|
||||
dependencies,
|
||||
}): HeaderFieldProps & { contentMode: HeaderFieldProps['contentMode'] } => {
|
||||
const [requestBody] = dependencies;
|
||||
return {
|
||||
readOnly,
|
||||
contentMode: (requestBody as RequestBodyCheck).type,
|
||||
};
|
||||
},
|
||||
},
|
||||
[ConfigKey.REQUEST_BODY_CHECK]: {
|
||||
fieldKey: ConfigKey.REQUEST_BODY_CHECK,
|
||||
|
|
|
@ -18,6 +18,7 @@ import {
|
|||
FormMonitorType,
|
||||
MonitorFields,
|
||||
ResponseCheckJSON,
|
||||
RequestBodyCheck,
|
||||
} from '../../../../../common/runtime_types/monitor_management';
|
||||
import { AlertConfigKey } from './constants';
|
||||
|
||||
|
@ -38,6 +39,7 @@ export interface FormLocation {
|
|||
isServiceManaged: boolean;
|
||||
label: string;
|
||||
}
|
||||
|
||||
export type FormConfig = MonitorFields & {
|
||||
isTLSEnabled: boolean;
|
||||
['schedule.number']: string;
|
||||
|
@ -57,6 +59,9 @@ export type FormConfig = MonitorFields & {
|
|||
supported_protocols: MonitorFields[ConfigKey.TLS_VERSION];
|
||||
};
|
||||
check: {
|
||||
request: {
|
||||
body: RequestBodyCheck;
|
||||
};
|
||||
response: {
|
||||
json: ResponseCheckJSON[];
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue