diff --git a/packages/rest/src/rest.application.ts b/packages/rest/src/rest.application.ts index 9ecfb576f48a..a4f3cb021d0c 100644 --- a/packages/rest/src/rest.application.ts +++ b/packages/rest/src/rest.application.ts @@ -244,7 +244,7 @@ export class RestApplication extends Application implements HttpServerLike { */ redirect( fromPath: string, - toPathOrUrl: string, + toPathOrUrl: string | Function, statusCode?: number, ): Binding { return this.restServer.redirect(fromPath, toPathOrUrl, statusCode); diff --git a/packages/rest/src/rest.server.ts b/packages/rest/src/rest.server.ts index 206d880b570c..638de6498858 100644 --- a/packages/rest/src/rest.server.ts +++ b/packages/rest/src/rest.server.ts @@ -683,11 +683,11 @@ export class RestServer extends Context implements Server, HttpServerLike { */ redirect( fromPath: string, - toPathOrUrl: string, + toPathOrUrl: string | Function, statusCode?: number, ): Binding { return this.route( - new RedirectRoute(fromPath, this._basePath + toPathOrUrl, statusCode), + new RedirectRoute(fromPath, toPathOrUrl, statusCode), ); } diff --git a/packages/rest/src/router/redirect-route.ts b/packages/rest/src/router/redirect-route.ts index 71da6fdd64d4..c9ae3228b010 100644 --- a/packages/rest/src/router/redirect-route.ts +++ b/packages/rest/src/router/redirect-route.ts @@ -2,7 +2,7 @@ import {RouteEntry, ResolvedRoute} from '.'; import {RequestContext} from '../request-context'; import {OperationObject, SchemasObject} from '@loopback/openapi-v3-types'; import {OperationArgs, OperationRetval, PathParameterValues} from '../types'; - +import {Request} from "express"; export class RedirectRoute implements RouteEntry, ResolvedRoute { // ResolvedRoute API readonly pathParams: PathParameterValues = []; @@ -19,15 +19,22 @@ export class RedirectRoute implements RouteEntry, ResolvedRoute { constructor( private readonly sourcePath: string, - private readonly targetLocation: string, + private readonly targetLocation: string | Function, private readonly statusCode: number = 303, ) {} async invokeHandler( - {response}: RequestContext, + {response,request}: RequestContext, args: OperationArgs, ): Promise { - response.redirect(this.statusCode, this.targetLocation); + let basePath = this._getBasePath(request) || ''; + let targetLocation :string = typeof this.targetLocation === 'function' + ? this.targetLocation( + this._getProtocolForRequest(request), + this._getHost(request), + basePath + ) : basePath + this.targetLocation; + response.redirect(this.statusCode,targetLocation); } updateBindings(requestContext: RequestContext) { @@ -39,4 +46,24 @@ export class RedirectRoute implements RouteEntry, ResolvedRoute { this.targetLocation }"`; } + + private _getHost(request: Request) { + return request.get('x-forwarded-host') || request.headers.host; + } + + private _getProtocolForRequest(request: Request) { + return ( + (request.get('x-forwarded-proto') || '').split(',')[0] || + request.protocol || + 'http' + ); + } + + private _getBasePath(request: Request) { + let basePath = ''; + if (request.baseUrl && request.baseUrl !== '/') { + basePath = request.baseUrl + basePath; + } + return basePath; + } } diff --git a/packages/rest/src/run.ts b/packages/rest/src/run.ts new file mode 100644 index 000000000000..2a971dfc43f8 --- /dev/null +++ b/packages/rest/src/run.ts @@ -0,0 +1,29 @@ +import {RestApplication, RestServer, RestServerConfig, get} from '.'; + +function givenApplication(options?: {rest: RestServerConfig}) { + options = options || {rest: {port: 4000, host: '127.0.0.1'}}; + return new RestApplication(options); +} + +async function main() { + let restApp = givenApplication(); + class PingController { + @get('/ping') + ping(): string { + return 'Hi'; + } + @get('/bye') + bye(): string { + return 'Bye'; + } + } + restApp.controller(PingController); + restApp.redirect('/ping',(protocol:string, host:string, basePath:string)=>{ + console.log(protocol+host+basePath); + return protocol+'://'+host+basePath+'/bye'; + }); + //restApp.redirect('/ping','/bye'); + await restApp.start(); +} + +main(); \ No newline at end of file