This line of code
app.{{method}}('{{../../basePath}}/{{../path}}{{path}}'
in _src/routeGeneration/templates/express.ts_ template adds hardcoded / between base path and controller path.
Additionally this line of code
this.path = decoratorArgument ? `/${decoratorArgument.text}` : '';
in _src/metadataGeneration/methodGenerator.ts_ adds hardcoded / as prefix to every action path.
So if i have base path /api/v2 and
@Route()
export class LoginController {
@Post('login')
public async login(...): Promise<...> { ... }
}
generated route will be
app.post('/api/v2//login',
function(request: any, response: any, next: any) {
...
});
As you can see there is a double / in the path because of hardcoded symbols mentioned above.
Note that Swagger doc gets generated fine though.
This makes /api/v2//login endpoint working instead of /api/v2/login, call to latter returns 404.
Some servers are ignoring that and probably Express can ignore as well, but it would be great if TSOA can generate normal routes which are fully working on any server.
Here is the possible way to solve the problem:
1) Remove hardcoded / in code mentioned above.
2) Normalise all route paths to avoid redundant or missing / signs, possible way to do this shown below in the modified part of code from _src/routeGeneration/routeGenerator.ts_
/**
* Removes all '/', '\', and spaces at the beginning and at the end of the path
* Adds prefix and suffix if supplied
*/
function normalisePath(pathStr: string, withPrefix?: string, withSuffix?: string): string {
if(!pathStr || typeof pathStr !== 'string') {
return pathStr;
}
let normalised = pathStr.replace(/^[/\\ ]+|[/\\ ]+$/g, '');
normalised = withPrefix ? withPrefix + normalised : normalised;
normalised = withSuffix ? normalised + withSuffix : normalised;
return normalised
}
return routesTemplate({
authenticationModule,
basePath: this.options.basePath === '/' ? '' : normalisePath(this.options.basePath as string, '/'),
canImportByAlias,
controllers: this.metadata.controllers.map(controller => {
return {
actions: controller.methods.map(method => {
const parameterObjs: { [name: string]: TsoaRoute.ParameterSchema } = {};
method.parameters.forEach(parameter => {
parameterObjs[parameter.parameterName] = this.buildParameterSchema(parameter);
});
return {
method: method.method.toLowerCase(),
name: method.name,
parameters: parameterObjs,
path: normalisePath(pathTransformer(method.path), '/'),
security: method.security,
};
}),
modulePath: this.getRelativeImportPath(controller.location),
name: controller.name,
path: normalisePath(controller.path, '/'),
};
}),
environment: process.env,
iocModule,
models: this.buildModels(),
useSecurity: this.metadata.controllers.some(
controller => controller.methods.some(method => !!method.security.length),
),
});
3) Normalise paths in swagger doc same way as for routes.
Fix looks pretty simple.
Thank you for making this great framework!
Here is PR
https://github.com/lukeautry/tsoa/pull/161
Most helpful comment
Here is PR
https://github.com/lukeautry/tsoa/pull/161