Skip to content

Commit eb29ab8

Browse files
authored
Provide url rewritten in onPreRouting interceptor (#80810)
* keep url rewritten in onPreRouting interceptor * update docs * add test on undefined
1 parent 45cb813 commit eb29ab8

6 files changed

Lines changed: 86 additions & 3 deletions

File tree

docs/development/core/server/kibana-plugin-core-server.kibanarequest.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ export declare class KibanaRequest<Params = unknown, Query = unknown, Body = unk
3030
| [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. |
3131
| [params](./kibana-plugin-core-server.kibanarequest.params.md) | | <code>Params</code> | |
3232
| [query](./kibana-plugin-core-server.kibanarequest.query.md) | | <code>Query</code> | |
33+
| [rewrittenUrl](./kibana-plugin-core-server.kibanarequest.rewrittenurl.md) | | <code>Url</code> | URL rewritten in onPreRouting request interceptor. |
3334
| [route](./kibana-plugin-core-server.kibanarequest.route.md) | | <code>RecursiveReadonly&lt;KibanaRequestRoute&lt;Method&gt;&gt;</code> | matched route details |
3435
| [socket](./kibana-plugin-core-server.kibanarequest.socket.md) | | <code>IKibanaSocket</code> | [IKibanaSocket](./kibana-plugin-core-server.ikibanasocket.md) |
3536
| [url](./kibana-plugin-core-server.kibanarequest.url.md) | | <code>Url</code> | a WHATWG URL standard object. |
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
2+
3+
[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)
4+
5+
## KibanaRequest.rewrittenUrl property
6+
7+
URL rewritten in onPreRouting request interceptor.
8+
9+
<b>Signature:</b>
10+
11+
```typescript
12+
readonly rewrittenUrl?: Url;
13+
```

src/core/server/http/integration_tests/lifecycle.test.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,62 @@ describe('OnPreRouting', () => {
117117
expect(urlAfterForwarding).toBe('/redirectUrl');
118118
});
119119

120+
it('provides original request url', async () => {
121+
const { registerOnPreRouting, server: innerServer, createRouter } = await server.setup(
122+
setupDeps
123+
);
124+
const router = createRouter('/');
125+
126+
router.get({ path: '/login', validate: false }, (context, req, res) => {
127+
return res.ok({ body: { rewrittenUrl: req.rewrittenUrl?.path } });
128+
});
129+
130+
registerOnPreRouting((req, res, t) => t.rewriteUrl('/login'));
131+
132+
await server.start();
133+
134+
await supertest(innerServer.listener)
135+
.get('/initial?name=foo')
136+
.expect(200, { rewrittenUrl: '/initial?name=foo' });
137+
});
138+
139+
it('provides original request url if rewritten several times', async () => {
140+
const { registerOnPreRouting, server: innerServer, createRouter } = await server.setup(
141+
setupDeps
142+
);
143+
const router = createRouter('/');
144+
145+
router.get({ path: '/reroute-2', validate: false }, (context, req, res) => {
146+
return res.ok({ body: { rewrittenUrl: req.rewrittenUrl?.path } });
147+
});
148+
149+
registerOnPreRouting((req, res, t) => t.rewriteUrl('/reroute-1'));
150+
registerOnPreRouting((req, res, t) => t.rewriteUrl('/reroute-2'));
151+
152+
await server.start();
153+
154+
await supertest(innerServer.listener)
155+
.get('/initial?name=foo')
156+
.expect(200, { rewrittenUrl: '/initial?name=foo' });
157+
});
158+
159+
it('does not provide request url if interceptor does not rewrite url', async () => {
160+
const { registerOnPreRouting, server: innerServer, createRouter } = await server.setup(
161+
setupDeps
162+
);
163+
const router = createRouter('/');
164+
165+
router.get({ path: '/login', validate: false }, (context, req, res) => {
166+
return res.ok({ body: { rewrittenUrl: req.rewrittenUrl?.path } });
167+
});
168+
169+
registerOnPreRouting((req, res, t) => t.next());
170+
171+
await server.start();
172+
173+
await supertest(innerServer.listener).get('/login').expect(200, {});
174+
});
175+
120176
it('supports redirection from the interceptor', async () => {
121177
const { registerOnPreRouting, server: innerServer, createRouter } = await server.setup(
122178
setupDeps

src/core/server/http/lifecycle/on_pre_routing.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import {
2525
KibanaResponse,
2626
lifecycleResponseFactory,
2727
LifecycleResponseFactory,
28+
KibanaRequestState,
2829
} from '../router';
2930

3031
enum ResultType {
@@ -108,6 +109,9 @@ export function adoptToHapiOnRequest(fn: OnPreRoutingHandler, log: Logger) {
108109
}
109110

110111
if (preRoutingResult.isRewriteUrl(result)) {
112+
const appState = request.app as KibanaRequestState;
113+
appState.rewrittenUrl = appState.rewrittenUrl ?? request.url;
114+
111115
const { url } = result;
112116
request.setUrl(url);
113117
// We should update raw request as well since it can be proxied to the old platform

src/core/server/http/router/request.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ export interface KibanaRouteOptions extends RouteOptionsApp {
4545
export interface KibanaRequestState extends ApplicationState {
4646
requestId: string;
4747
requestUuid: string;
48+
rewrittenUrl?: Url;
4849
}
4950

5051
/**
@@ -186,6 +187,11 @@ export class KibanaRequest<
186187
isAuthenticated: boolean;
187188
};
188189

190+
/**
191+
* URL rewritten in onPreRouting request interceptor.
192+
*/
193+
public readonly rewrittenUrl?: Url;
194+
189195
/** @internal */
190196
protected readonly [requestSymbol]: Request;
191197

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

207215
this.url = request.url;
208216
this.headers = deepFreeze({ ...request.headers });

src/core/server/server.api.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,6 +1007,7 @@ export class KibanaRequest<Params = unknown, Query = unknown, Body = unknown, Me
10071007
readonly params: Params;
10081008
// (undocumented)
10091009
readonly query: Query;
1010+
readonly rewrittenUrl?: Url;
10101011
readonly route: RecursiveReadonly<KibanaRequestRoute<Method>>;
10111012
// (undocumented)
10121013
readonly socket: IKibanaSocket;

0 commit comments

Comments
 (0)