Skip to content

Commit

Permalink
Provide url rewritten in onPreRouting interceptor (elastic#80810)
Browse files Browse the repository at this point in the history
* keep url rewritten in onPreRouting interceptor

* update docs

* add test on undefined
  • Loading branch information
mshustov committed Oct 20, 2020
1 parent 175751a commit 2f1278b
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export declare class KibanaRequest<Params = unknown, Query = unknown, Body = unk
| [isSystemRequest](./kibana-plugin-core-server.kibanarequest.issystemrequest.md) | | <code>boolean</code> | Whether or not the request is a "system request" rather than an application-level request. Can be set on the client using the <code>HttpFetchOptions#asSystemRequest</code> option. |
| [params](./kibana-plugin-core-server.kibanarequest.params.md) | | <code>Params</code> | |
| [query](./kibana-plugin-core-server.kibanarequest.query.md) | | <code>Query</code> | |
| [rewrittenUrl](./kibana-plugin-core-server.kibanarequest.rewrittenurl.md) | | <code>Url</code> | URL rewritten in onPreRouting request interceptor. |
| [route](./kibana-plugin-core-server.kibanarequest.route.md) | | <code>RecursiveReadonly&lt;KibanaRequestRoute&lt;Method&gt;&gt;</code> | matched route details |
| [socket](./kibana-plugin-core-server.kibanarequest.socket.md) | | <code>IKibanaSocket</code> | [IKibanaSocket](./kibana-plugin-core-server.ikibanasocket.md) |
| [url](./kibana-plugin-core-server.kibanarequest.url.md) | | <code>Url</code> | a WHATWG URL standard object. |
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-core-server](./kibana-plugin-core-server.md) &gt; [KibanaRequest](./kibana-plugin-core-server.kibanarequest.md) &gt; [rewrittenUrl](./kibana-plugin-core-server.kibanarequest.rewrittenurl.md)

## KibanaRequest.rewrittenUrl property

URL rewritten in onPreRouting request interceptor.

<b>Signature:</b>

```typescript
readonly rewrittenUrl?: Url;
```
56 changes: 56 additions & 0 deletions src/core/server/http/integration_tests/lifecycle.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,62 @@ describe('OnPreRouting', () => {
expect(urlAfterForwarding).toBe('/redirectUrl');
});

it('provides original request url', async () => {
const { registerOnPreRouting, server: innerServer, createRouter } = await server.setup(
setupDeps
);
const router = createRouter('/');

router.get({ path: '/login', validate: false }, (context, req, res) => {
return res.ok({ body: { rewrittenUrl: req.rewrittenUrl?.path } });
});

registerOnPreRouting((req, res, t) => t.rewriteUrl('/login'));

await server.start();

await supertest(innerServer.listener)
.get('/initial?name=foo')
.expect(200, { rewrittenUrl: '/initial?name=foo' });
});

it('provides original request url if rewritten several times', async () => {
const { registerOnPreRouting, server: innerServer, createRouter } = await server.setup(
setupDeps
);
const router = createRouter('/');

router.get({ path: '/reroute-2', validate: false }, (context, req, res) => {
return res.ok({ body: { rewrittenUrl: req.rewrittenUrl?.path } });
});

registerOnPreRouting((req, res, t) => t.rewriteUrl('/reroute-1'));
registerOnPreRouting((req, res, t) => t.rewriteUrl('/reroute-2'));

await server.start();

await supertest(innerServer.listener)
.get('/initial?name=foo')
.expect(200, { rewrittenUrl: '/initial?name=foo' });
});

it('does not provide request url if interceptor does not rewrite url', async () => {
const { registerOnPreRouting, server: innerServer, createRouter } = await server.setup(
setupDeps
);
const router = createRouter('/');

router.get({ path: '/login', validate: false }, (context, req, res) => {
return res.ok({ body: { rewrittenUrl: req.rewrittenUrl?.path } });
});

registerOnPreRouting((req, res, t) => t.next());

await server.start();

await supertest(innerServer.listener).get('/login').expect(200, {});
});

it('supports redirection from the interceptor', async () => {
const { registerOnPreRouting, server: innerServer, createRouter } = await server.setup(
setupDeps
Expand Down
4 changes: 4 additions & 0 deletions src/core/server/http/lifecycle/on_pre_routing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
KibanaResponse,
lifecycleResponseFactory,
LifecycleResponseFactory,
KibanaRequestState,
} from '../router';

enum ResultType {
Expand Down Expand Up @@ -108,6 +109,9 @@ export function adoptToHapiOnRequest(fn: OnPreRoutingHandler, log: Logger) {
}

if (preRoutingResult.isRewriteUrl(result)) {
const appState = request.app as KibanaRequestState;
appState.rewrittenUrl = appState.rewrittenUrl ?? request.url;

const { url } = result;
request.setUrl(url);
// We should update raw request as well since it can be proxied to the old platform
Expand Down
14 changes: 11 additions & 3 deletions src/core/server/http/router/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export interface KibanaRouteOptions extends RouteOptionsApp {
export interface KibanaRequestState extends ApplicationState {
requestId: string;
requestUuid: string;
rewrittenUrl?: Url;
}

/**
Expand Down Expand Up @@ -186,6 +187,11 @@ export class KibanaRequest<
isAuthenticated: boolean;
};

/**
* URL rewritten in onPreRouting request interceptor.
*/
public readonly rewrittenUrl?: Url;

/** @internal */
protected readonly [requestSymbol]: Request;

Expand All @@ -199,10 +205,12 @@ export class KibanaRequest<
private readonly withoutSecretHeaders: boolean
) {
// The `requestId` and `requestUuid` properties will not be populated for requests that are 'faked' by internal systems that leverage
// KibanaRequest in conjunction with scoped Elaticcsearch and SavedObjectsClient in order to pass credentials.
// KibanaRequest in conjunction with scoped Elasticsearch and SavedObjectsClient in order to pass credentials.
// In these cases, the ids default to a newly generated UUID.
this.id = (request.app as KibanaRequestState | undefined)?.requestId ?? uuid.v4();
this.uuid = (request.app as KibanaRequestState | undefined)?.requestUuid ?? uuid.v4();
const appState = request.app as KibanaRequestState | undefined;
this.id = appState?.requestId ?? uuid.v4();
this.uuid = appState?.requestUuid ?? uuid.v4();
this.rewrittenUrl = appState?.rewrittenUrl;

this.url = request.url;
this.headers = deepFreeze({ ...request.headers });
Expand Down
1 change: 1 addition & 0 deletions src/core/server/server.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -1043,6 +1043,7 @@ export class KibanaRequest<Params = unknown, Query = unknown, Body = unknown, Me
readonly params: Params;
// (undocumented)
readonly query: Query;
readonly rewrittenUrl?: Url;
readonly route: RecursiveReadonly<KibanaRequestRoute<Method>>;
// (undocumented)
readonly socket: IKibanaSocket;
Expand Down

0 comments on commit 2f1278b

Please sign in to comment.