diff --git a/packages/core/http/core-http-browser-internal/src/fetch.test.ts b/packages/core/http/core-http-browser-internal/src/fetch.test.ts index cbf6cde1a90c5..b46a34f768b66 100644 --- a/packages/core/http/core-http-browser-internal/src/fetch.test.ts +++ b/packages/core/http/core-http-browser-internal/src/fetch.test.ts @@ -29,6 +29,7 @@ describe('Fetch', () => { const fetchInstance = new Fetch({ basePath: new BasePath(BASE_PATH), kibanaVersion: 'VERSION', + buildNumber: 1234, executionContext: executionContextMock, }); afterEach(() => { @@ -160,6 +161,7 @@ describe('Fetch', () => { expect(fetchMock.lastOptions()!.headers).toMatchObject({ 'content-type': 'application/json', 'kbn-version': 'VERSION', + 'kbn-build-number': '1234', 'x-elastic-internal-origin': 'Kibana', myheader: 'foo', }); @@ -178,6 +180,19 @@ describe('Fetch', () => { `"Invalid fetch headers, headers beginning with \\"kbn-\\" are not allowed: [kbn-version]"` ); }); + it('should not allow overwriting of kbn-build-number header', async () => { + fetchMock.get('*', {}); + await expect( + fetchInstance.fetch('/my/path', { + headers: { + myHeader: 'foo', + 'kbn-build-number': 4321, + }, + }) + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"Invalid fetch headers, headers beginning with \\"kbn-\\" are not allowed: [kbn-build-number]"` + ); + }); it('should not allow overwriting of x-elastic-internal-origin header', async () => { fetchMock.get('*', {}); diff --git a/packages/core/http/core-http-browser-internal/src/fetch.ts b/packages/core/http/core-http-browser-internal/src/fetch.ts index 0683824628972..f6aa29c497d43 100644 --- a/packages/core/http/core-http-browser-internal/src/fetch.ts +++ b/packages/core/http/core-http-browser-internal/src/fetch.ts @@ -31,6 +31,7 @@ import { HttpInterceptHaltError } from './http_intercept_halt_error'; interface Params { basePath: IBasePath; kibanaVersion: string; + buildNumber: number; executionContext: ExecutionContextSetup; } @@ -135,6 +136,7 @@ export class Fetch { 'Content-Type': 'application/json', ...options.headers, 'kbn-version': this.params.kibanaVersion, + 'kbn-build-number': this.params.buildNumber, [ELASTIC_HTTP_VERSION_HEADER]: version, [X_ELASTIC_INTERNAL_ORIGIN_REQUEST]: 'Kibana', ...(!isEmpty(context) ? new ExecutionContextContainer(context).toHeader() : {}), diff --git a/packages/core/http/core-http-browser-internal/src/http_service.ts b/packages/core/http/core-http-browser-internal/src/http_service.ts index d2d0913afae94..d097dc7a14c9a 100644 --- a/packages/core/http/core-http-browser-internal/src/http_service.ts +++ b/packages/core/http/core-http-browser-internal/src/http_service.ts @@ -31,13 +31,14 @@ export class HttpService implements CoreService { public setup({ injectedMetadata, fatalErrors, executionContext }: HttpDeps): HttpSetup { const kibanaVersion = injectedMetadata.getKibanaVersion(); + const buildNumber = injectedMetadata.getKibanaBuildNumber(); const basePath = new BasePath( injectedMetadata.getBasePath(), injectedMetadata.getServerBasePath(), injectedMetadata.getPublicBaseUrl() ); - const fetchService = new Fetch({ basePath, kibanaVersion, executionContext }); + const fetchService = new Fetch({ basePath, kibanaVersion, buildNumber, executionContext }); const loadingCount = this.loadingCount.setup({ fatalErrors }); loadingCount.addLoadingCountSource(fetchService.getRequestCount$()); diff --git a/test/plugin_functional/plugins/core_http/server/plugin.ts b/test/plugin_functional/plugins/core_http/server/plugin.ts index f767f96c44408..0f1d8915825bc 100644 --- a/test/plugin_functional/plugins/core_http/server/plugin.ts +++ b/test/plugin_functional/plugins/core_http/server/plugin.ts @@ -22,6 +22,15 @@ export class CoreHttpPlugin implements Plugin { return res.ok(); } ); + router.get( + { + path: '/api/core_http/headers', + validate: false, + }, + async (ctx, req, res) => { + return res.ok({ body: req.headers }); + } + ); } public start() {} diff --git a/test/plugin_functional/test_suites/core_plugins/http.ts b/test/plugin_functional/test_suites/core_plugins/http.ts index 78682da70e608..6f67daa11e335 100644 --- a/test/plugin_functional/test_suites/core_plugins/http.ts +++ b/test/plugin_functional/test_suites/core_plugins/http.ts @@ -7,6 +7,7 @@ */ import expect from '@kbn/expect'; +import SemVer from 'semver'; import { PluginFunctionalProviderContext } from '../../services'; export default function ({ getService, getPageObjects }: PluginFunctionalProviderContext) { @@ -29,5 +30,22 @@ export default function ({ getService, getPageObjects }: PluginFunctionalProvide const canceledErrorName = await getCancelationErrorName(); expect(canceledErrorName).to.eql('AbortError'); }); + + it('sets the expected headers', async () => { + const headers = await browser.executeAsync>(async (cb) => { + cb(await window._coreProvider.setup.core.http.get('/api/core_http/headers')); + }); + expect(headers).to.have.property('kbn-version'); + expect(!!SemVer.valid(headers['kbn-version'])).to.be(true); + + expect(headers).to.have.property('kbn-build-number'); + expect(headers['kbn-build-number']).to.match(/^\d+$/); + + expect(headers).to.have.property('x-elastic-internal-origin'); + expect(headers['x-elastic-internal-origin']).to.be.a('string'); + + expect(headers).to.have.property('x-kbn-context'); + expect(headers['x-kbn-context']).to.be.a('string'); + }); }); }