KibanaRequest provides headers as a property. (#39506)

* use property instead of method. not all header names are known

* fix tag name and re-generate docs
This commit is contained in:
Mikhail Shustov 2019-06-26 10:04:34 +02:00 committed by GitHub
parent 8ec14e07ae
commit 484351bdac
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 35 additions and 123 deletions

View file

@ -1,22 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-server](./kibana-plugin-server.md) &gt; [KibanaRequest](./kibana-plugin-server.kibanarequest.md) &gt; [getFilteredHeaders](./kibana-plugin-server.kibanarequest.getfilteredheaders.md)
## KibanaRequest.getFilteredHeaders() method
<b>Signature:</b>
```typescript
getFilteredHeaders(headersToKeep: string[]): Pick<Record<string, string | string[] | undefined>, string>;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| headersToKeep | <code>string[]</code> | |
<b>Returns:</b>
`Pick<Record<string, string | string[] | undefined>, string>`

View file

@ -4,10 +4,15 @@
## KibanaRequest.headers property
This property will be removed in future version of this class, please use the `getFilteredHeaders` method instead
Readonly copy of incoming request headers.
<b>Signature:</b>
```typescript
readonly headers: Headers;
```
## Remarks
This property will contain a `filtered` copy of request headers.

View file

@ -23,19 +23,9 @@ export declare class KibanaRequest<Params = unknown, Query = unknown, Body = unk
| Property | Modifiers | Type | Description |
| --- | --- | --- | --- |
| [body](./kibana-plugin-server.kibanarequest.body.md) | | <code>Body</code> | |
| [headers](./kibana-plugin-server.kibanarequest.headers.md) | | <code>Headers</code> | This property will be removed in future version of this class, please use the <code>getFilteredHeaders</code> method instead |
| [headers](./kibana-plugin-server.kibanarequest.headers.md) | | <code>Headers</code> | Readonly copy of incoming request headers. |
| [params](./kibana-plugin-server.kibanarequest.params.md) | | <code>Params</code> | |
| [query](./kibana-plugin-server.kibanarequest.query.md) | | <code>Query</code> | |
| [route](./kibana-plugin-server.kibanarequest.route.md) | | <code>RecursiveReadonly&lt;KibanaRequestRoute&gt;</code> | |
| [url](./kibana-plugin-server.kibanarequest.url.md) | | <code>Url</code> | |
## Methods
| Method | Modifiers | Description |
| --- | --- | --- |
| [getFilteredHeaders(headersToKeep)](./kibana-plugin-server.kibanarequest.getfilteredheaders.md) | | |
## Remarks
The `headers` property will be deprecated and removed in future versions of this class. Please use the `getFilteredHeaders` method to acesss the list of headers available

View file

@ -406,35 +406,6 @@ test('handles deleting', async () => {
});
});
test('filtered headers', async () => {
expect.assertions(1);
const router = new Router('/foo');
let filteredHeaders: any;
router.get({ path: '/', validate: false }, (req, res) => {
filteredHeaders = req.getFilteredHeaders(['x-kibana-foo', 'host']);
return res.noContent();
});
const { registerRouter, server: innerServer } = await server.setup(config);
registerRouter(router);
await server.start();
await supertest(innerServer.listener)
.get('/foo/?bar=quux')
.set('x-kibana-foo', 'bar')
.set('x-kibana-bar', 'quux');
expect(filteredHeaders).toEqual({
host: `127.0.0.1:${config.port}`,
'x-kibana-foo': 'bar',
});
});
describe('with `basepath: /bar` and `rewriteBasePath: false`', () => {
let configWithBasePath: HttpConfig;
let innerServerListener: Server;
@ -756,7 +727,7 @@ describe('#registerAuth', () => {
]);
});
it('is the only place with access to the authorization header', async () => {
it.skip('is the only place with access to the authorization header', async () => {
const token = 'Basic: user:password';
const {
registerAuth,
@ -768,26 +739,26 @@ describe('#registerAuth', () => {
let fromRegisterOnPreAuth;
await registerOnPreAuth((req, t) => {
fromRegisterOnPreAuth = req.getFilteredHeaders(['authorization']);
fromRegisterOnPreAuth = req.headers.authorization;
return t.next();
});
let fromRegisterAuth;
await registerAuth((req, t) => {
fromRegisterAuth = req.getFilteredHeaders(['authorization']);
fromRegisterAuth = req.headers.authorization;
return t.authenticated();
}, cookieOptions);
let fromRegisterOnPostAuth;
await registerOnPostAuth((req, t) => {
fromRegisterOnPostAuth = req.getFilteredHeaders(['authorization']);
fromRegisterOnPostAuth = req.headers.authorization;
return t.next();
});
let fromRouteHandler;
const router = new Router('');
router.get({ path: '/', validate: false }, (req, res) => {
fromRouteHandler = req.getFilteredHeaders(['authorization']);
fromRouteHandler = req.headers.authorization;
return res.ok({ content: 'ok' });
});
registerRouter(router);

View file

@ -59,8 +59,7 @@ describe('http service', () => {
it('runs auth for legacy routes and proxy request to legacy server route handlers', async () => {
const { http } = await root.setup();
const { sessionStorageFactory } = await http.registerAuth<StorageData>((req, t) => {
const headers = req.getFilteredHeaders(['authorization']);
if (headers.authorization) {
if (req.headers.authorization) {
const user = { id: '42' };
const sessionStorage = sessionStorageFactory.asScoped(req);
sessionStorage.set({ value: user, expires: Date.now() + sessionDurationMs });
@ -90,8 +89,7 @@ describe('http service', () => {
const token = 'Basic: name:password';
const { http } = await root.setup();
const { sessionStorageFactory } = await http.registerAuth<StorageData>((req, t) => {
const headers = req.getFilteredHeaders(['authorization']);
if (headers.authorization) {
if (req.headers.authorization) {
const user = { id: '42' };
const sessionStorage = sessionStorageFactory.asScoped(req);
sessionStorage.set({ value: user, expires: Date.now() + sessionDurationMs });
@ -129,8 +127,7 @@ describe('http service', () => {
const { http } = await root.setup();
const { sessionStorageFactory } = await http.registerAuth<StorageData>((req, t) => {
const headers = req.getFilteredHeaders(['authorization']);
if (headers.authorization) {
if (req.headers.authorization) {
const sessionStorage = sessionStorageFactory.asScoped(req);
sessionStorage.set({ value: user, expires: Date.now() + sessionDurationMs });
return t.authenticated({ state: user });

View file

@ -30,41 +30,25 @@ describe('KibanaRequest', () => {
});
});
describe('#getFilteredHeaders', () => {
it('returns request headers', () => {
describe('headers property', () => {
it('provides a frozen copy of request headers', () => {
const rawRequestHeaders = { custom: 'one' };
const request = httpServerMock.createRawRequest({
headers: { custom: 'one' },
headers: rawRequestHeaders,
});
const kibanaRequest = KibanaRequest.from(request);
expect(kibanaRequest.getFilteredHeaders(['custom'])).toEqual({
custom: 'one',
});
expect(kibanaRequest.headers).toEqual({ custom: 'one' });
expect(kibanaRequest.headers).not.toBe(rawRequestHeaders);
expect(Object.isFrozen(kibanaRequest.headers)).toBe(true);
});
it('normalizes a header name', () => {
const request = httpServerMock.createRawRequest({
headers: { custom: 'one' },
});
const kibanaRequest = KibanaRequest.from(request);
expect(kibanaRequest.getFilteredHeaders(['CUSTOM'])).toEqual({
custom: 'one',
});
});
it('returns an empty object is no headers were specified', () => {
const request = httpServerMock.createRawRequest({
headers: { custom: 'one' },
});
const kibanaRequest = KibanaRequest.from(request);
expect(kibanaRequest.getFilteredHeaders([])).toEqual({});
});
it("doesn't expose authorization header by default", () => {
it.skip("doesn't expose authorization header by default", () => {
const request = httpServerMock.createRawRequest({
headers: { custom: 'one', authorization: 'token' },
});
const kibanaRequest = KibanaRequest.from(request);
expect(kibanaRequest.getFilteredHeaders(['custom', 'authorization'])).toEqual({
expect(kibanaRequest.headers).toEqual({
custom: 'one',
});
});
@ -74,7 +58,7 @@ describe('KibanaRequest', () => {
headers: { custom: 'one', authorization: 'token' },
});
const kibanaRequest = KibanaRequest.from(request, undefined, false);
expect(kibanaRequest.getFilteredHeaders(['custom', 'authorization'])).toEqual({
expect(kibanaRequest.headers).toEqual({
custom: 'one',
authorization: 'token',
});

View file

@ -18,11 +18,12 @@
*/
import { Url } from 'url';
import { ObjectType, TypeOf } from '@kbn/config-schema';
import { Request } from 'hapi';
import { ObjectType, TypeOf } from '@kbn/config-schema';
import { deepFreeze, RecursiveReadonly } from '../../../utils';
import { filterHeaders, Headers } from './headers';
import { Headers } from './headers';
import { RouteMethod, RouteSchemas, RouteConfigOptions } from './route';
const requestSymbol = Symbol('request');
@ -37,15 +38,8 @@ export interface KibanaRequestRoute {
options: Required<RouteConfigOptions>;
}
const secretHeaders = ['authorization'];
/**
* Kibana specific abstraction for an incoming request.
*
* @remarks
* The `headers` property will be deprecated and removed in future versions
* of this class. Please use the `getFilteredHeaders` method to acesss the
* list of headers available
*
* @public
* */
export class KibanaRequest<Params = unknown, Query = unknown, Body = unknown> {
@ -104,8 +98,9 @@ export class KibanaRequest<Params = unknown, Query = unknown, Body = unknown> {
public readonly url: Url;
public readonly route: RecursiveReadonly<KibanaRequestRoute>;
/**
* This property will be removed in future version of this class, please
* use the `getFilteredHeaders` method instead
* Readonly copy of incoming request headers.
* @remarks
* This property will contain a `filtered` copy of request headers.
*/
public readonly headers: Headers;
@ -117,10 +112,12 @@ export class KibanaRequest<Params = unknown, Query = unknown, Body = unknown> {
readonly params: Params,
readonly query: Query,
readonly body: Body,
// @ts-ignore we will use this flag as soon as http request proxy is supported in the core
// until that time we have to expose all the headers
private readonly withoutSecretHeaders: boolean
) {
this.url = request.url;
this.headers = request.headers;
this.headers = deepFreeze({ ...request.headers });
// prevent Symbol exposure via Object.getOwnPropertySymbols()
Object.defineProperty(this, requestSymbol, {
@ -131,14 +128,6 @@ export class KibanaRequest<Params = unknown, Query = unknown, Body = unknown> {
this.route = deepFreeze(this.getRouteInfo());
}
public getFilteredHeaders(headersToKeep: string[]) {
return filterHeaders(
this[requestSymbol].headers,
headersToKeep,
this.withoutSecretHeaders ? secretHeaders : []
);
}
private getRouteInfo() {
const request = this[requestSymbol];
return {

View file

@ -189,8 +189,6 @@ export class KibanaRequest<Params = unknown, Query = unknown, Body = unknown> {
//
// @internal
static from<P extends ObjectType, Q extends ObjectType, B extends ObjectType>(req: Request, routeSchemas?: RouteSchemas<P, Q, B>, withoutSecretHeaders?: boolean): KibanaRequest<P["type"], Q["type"], B["type"]>;
// (undocumented)
getFilteredHeaders(headersToKeep: string[]): Pick<Record<string, string | string[] | undefined>, string>;
readonly headers: Headers;
// (undocumented)
readonly params: Params;