How to make URI versioning optional in a nestjs REST application - nestjs

NestJS URI Versioning for HTTP REST applications can be easily enabled when following the docs here.
The docs do however not explain how to make URI versioning optional.
Example:
/api/v1/users
/api/v2/users
/api/users -> should be mapped to v1 to allow existing webhooks to keep working
Question:
How can we make the URI versioning optional in a NestJS REST application so that old versions (without any api version) keep working ?

You should use the VERSION_NEUTRAL version on defaultVersion option like:
app.enableVersioning({
type: VersioningType.URI,
defaultVersion: [VERSION_NEUTRAL, '1', '2'],
});
https://docs.nestjs.com/techniques/versioning

UPDATE:
The following is a hack and results in the global prefix for URI versioning no longer working, please use the accepted answer.
Original Answer:
To make versioning optional, set the versioning prefix to an empty string (default is v) and set the versioning string including the prefix explicitly.
In main.ts:
app.enableVersioning({
type: VersioningType.URI,
defaultVersion: ['', 'v1', 'v2'],
prefix: '',
});
In the v1 controller:
#Controller({ path: 'users', version: ['v1', ''] })

Related

NestJs + Swagger documentation based on versioning

I have built a nestjs webapi and implemented versioning at controller and action level as per https://docs.nestjs.com/techniques/versioning
The solution i am looking into is, i want to generate 2 different swagger based on the controller version.
For example, i have 2 controller defined for 2 different version. if i hit [example.com/v1/swagger] , it should load only v1 version controller swagger doc and similarly for v2
I recently updated my API to support versioning. I couldn't get the Swagger docs to load correctly. Here is my solution, I hope it helps!
Before, we had used app.setGlobalPrefix(APP_ROUTE_PREFIX) to define the prefix.
const APP_ROUTE_PREFIX = 'api/v2';
app.setGlobalPrefix(APP_ROUTE_PREFIX);
Swagger docs were mounted as:
SwaggerModule.setup(`${APP_ROUTE_PREFIX}/docs`, app, document);
To adopt versioning, the following was changed.
Route prefix no longer includes the version; let Nestjs handle it.
const APP_ROUTE_PREFIX = 'api';
Versioning is enabled, with a default of '2', mimicking previous behavior.
app
.enableVersioning({ type: VersioningType.URI, defaultVersion: '2' })
.setGlobalPrefix(APP_ROUTE_PREFIX);
To get Swagger docs to mount correctly, we had to use a variable :version in the path.
SwaggerModule.setup(`${APP_ROUTE_PREFIX}/:version/docs`, app, document);
Next, we changed on a per-controller basis the controllers that need to adopt versioning.
#Controller({ path: 'objects/:id', version: ['2', '3'] })
Finally, we changed on a per-route basis the handlers that support multiple versions.
#Version('2')
getPageV2(): Promise<Observable<unknown>> {
return this.service.getOkayData();
}
#Version('3')
getPageV3(): Promise<Observable<unknown>> {
return this.service.getBetterData();
}

How to solve authorizer issue in Serverless framework 3?

When I use Serverless framework 2, I defined authorizer like the below way.
sample:
handler: sample.handler
events:
- http:
path: sample
method: get
cors: true
authorizer: verify-token
But It's not supported in Serverless framework 3. Now, I am getting the below error.
Incorrect type. Expected "Aws.HttpAuthorizer".yaml-schema: Serverless Framework Configuration
I looked at their deprecated doc But I don't find the solution. How can resolve this issue?
Seems like serverless expects you to define HttpAuthorizer instead of Lambda Authorizer for AWS REST API
Definitions of the settings are here: https://raw.githubusercontent.com/lalcebo/json-schema/master/serverless/reference.json
Rest API (V1) is actually more advanced. see:
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/AWS_ApiGateway.html or https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/AWS_ApiGatewayV2.html
Check the following documentation: https://serverless.com/framework/docs/providers/aws/events/apigateway#http-endpoints-with-custom-authorizers
The authorizer declaration must be completed in v3:
sample:
handler: sample.handler
events:
- http:
path: sample
method: get
cors: true
authorizer:
arn: xxx:xxx:verify-token
managedExternally: false
resultTtlInSeconds: 0
identitySource: method.request.header.Authorization
identityValidationExpression: someRegex

OpenApi 3.0: override global security

In OpenAPI 3, is it possible to define a SecurityScheme at global level but then override it at certain endpoints to not use security (for public accessible endpoints)?
For example (taken from https://swagger.io/docs/specification/authentication/bearer-authentication/)
openapi: 3.0.0
...
# 1) Define the security scheme type (HTTP bearer)
components:
securitySchemes:
bearerAuth: # arbitrary name for the security scheme
type: http
scheme: bearer
bearerFormat: JWT # optional, arbitrary value for documentation purposes
# 2) Apply the security globally to all operations
security:
- bearerAuth: [] # use the same name as above
And then make a given endpoint publicly accessible (unprotected)
paths:
/unprotected/path:
get:
security: []
Or should this be done in another way?
Update this question was marked as duplicate but the other question handles about Swagger 2.x and since syntax is different, I think this question and answers should remain.
You can indeed override security on a path bases in OA3 as follows:
paths:
/unprotected/path:
get:
security: []

Independent NPM library that validates request based on swagger file

We are building APIs using Swagger, AWS API gateway and Lambda functions with NodeJS. The API gateway will do the request validation, however as per the design, the lambda functions need to re-validate the request object as an API Gateway Proxy Request Event. This makes sense as in theory we can reuse the lambda functions by invoking them via other event source (e.g. SNS).
Therefore we need an NodeJS tool which can validate the request (not only body but also params, etc) based on the swagger spec - exactly what the swagger-tools and a few other tools (e.g. swagger-request-validator) are doing, but not as a middleware.
I did some search but could not find one, also looked into swagger-tools source code, reckon its validation component was written in the way that cannot be easily used separately.
Any suggestion is welcome. Thanks in advance.
You can use swagger-model-validator.
var Validator = require('swagger-model-validator');
var swaggerFile = require("./swagger.json");
const validator = new Validator(swaggerFile);
console.log(validator.validate({
name: 'meg'
}, swaggerFile.definitions.Pet, swaggerFile.definitions, true).GetErrorMessages())
This outputs:
[ 'photoUrls is a required field' ]
validator.validate returns an object, so you can also check if the returned object contains anything under the errors attribute. It should be as simple as
if (validator.validate({
name: 'meg'
}, swaggerFile.definitions.Pet, swaggerFile.definitions, true).errors) {
// do something with error
}
I have used Swagger's sample JSON for this answer.

ServiceStack.Swagger.Api supportedSubmitMethods

I have a service set up that uses ServiceStack.Swagger.Api. My service has several endpoints that support OPTIONS requests. Is there a way to configure the SwaggerAPI plugin to add 'options' to the js SwaggerUi.supportedSubmitMethods list in the index.html?
The options requests shows but the 'Try It Out' button does not exists because the supportedSubmitMethods doesn't have options in it.
*Using ServiceStack 4.5.6
ServiceStack Swagger's embedded resource files are overridable using the Virtual File System so you can override Swagger UI's default index.html by taking a copy of index.html and adding it to your Host Project in the /swagger-ui/ folder, e.g:
/swagger-ui/index.html
Then modify your local copy of supportedSubmitMethods to include options, e.g:
window.swaggerUi = new SwaggerUi({
url: url,
dom_id: "swagger-ui-container",
supportedSubmitMethods:['get', 'post', 'put', 'delete', 'patch', 'options'],
...
Note in the latest v4.5.8 Release if you have a lot of OPTIONS Services you can add it to the list of default verbs for Routes that don't explicitly specify an HTTP Verbs with:
Plugins.Add(new SwaggerFeature
{
AnyRouteVerbs = { HttpMethods.Options },
});
Also if you're able to upgrade to v4.5.8 then you may want to consider switching to use the newer Open API Feature which implements v2.0 of the Open API specification which is the successor to Swagger.

Resources