Configure swagger with Nestjs + Azure functions - azure

I am trying to develop my nestjs using azure functions following this article:
https://trilon.io/blog/deploy-nestjs-azure-functions
I have configured Swagger in my application as follows:
...
const options = new DocumentBuilder()
.setTitle('App title')
.setDescription('App description')
.setVersion('1.0')
.addBearerAuth(
{
type: 'http',
scheme: 'bearer',
bearerFormat: 'JWT',
},
'authorization',
)
.addTag('freight')
.build();
const document = SwaggerModule.createDocument(app, options);
SwaggerModule.setup('swagger', app, document);
...
When I run the app in development, I can access my swagger UI by navigating to /swagger, however when I run npm run build && func host start, I receive 500 error, which also happens when I hit a non-existing route.
All other routes that are registered in the application work as expected.

Nestjs has a module you need to load for this. nestjs-openapi
Next you will need to specify a few configuration items.
Note: Main.ts is not used at all.
Sync ports with:
func host start --port 3000
!! Use the app instance within the main.azure.ts. Example assumes global prefix defined above the code below.
...
//config
const config = new DocumentBuilder()
.setTitle('My Title')
.setDescription('My Description')
.setVersion('1.0')
.setBasePath('api-docs')
.build();
const document = SwaggerModule.createDocument(app, config);
SwaggerModule.setup('api-docs', app, document, {
useGlobalPrefix: true,
});
// order matters here.
app.init()
// port that is used for swagger ui. Sync with Az Fx.
app.listen(3000)
Now you can route to localhost:3000/{global_prefix}/api-docs to load swagger ui.

Related

How to use Bolt events with the newer Slack API manifests?

I'm building a Slack App using Bolt and I've got the basics working using Socket Mode. The docs say that socket mode apps are not allowed in the public directory, which I do want my App in when it's ready. I've now turned off socket mode and got ngrok working as described here. Slack was able to validate the url anyway.
But what's not working is a slash command. The manifest editor says the url is required for a slash command, but how does that line up with bolt? Are there better docs for non-socket-mode somewhere? It seems like every example of using bolt says "let's use socket mode, it's easy".
Manifest portion:
slash_commands:
- command: /sb
url: https://[my url].ngrok.io/slack/command
Sample code:
const { App } = require('#slack/bolt');
const express = require('express');
const app = express();
const boltApp = new App({
signingSecret: config.slackApp.signingSecret,
token: config.slackApp.token,
endpoints = '/'
});
app.use('/slack/events', boltApp.receiver.router);
Bolt
Slack App Manifests
I got this working with a combination of the following:
setting every url in the manifest (slash_commands, event_subscriptions, interactivity) to https://foo.ngrok.io/slack/
attaching Bolt to an existing Express App, attempting to follow this PR to use app and/or router config prop on ExpressReceiver, but strangely what worked was putting the express app into the router
setting up Bolt like below
Example Code:
const expressApp = express();
...
const boltReceiver = new ExpressReceiver({
router: expressApp,
signingSecret: SLACK_SIGNING_SECRET,
endpoints: '/slack'
});
const boltApp = new App({
token: SLACK_BOT_TOKEN,
receiver: boltReceiver,
appToken: SLACK_APP_TOKEN,
socketMode: false,
});

How to integrate OIDC Provider in Node jS

I tried to Integrate OIDC Provider to Node JS and I have a Sample Code. So, I run this Sample code it's throwing an error(unrecognized route or not allowed method (GET on /api/v1/.well-known/openid-configuration)).The problem is Issuer(https://localhost:3000) this Issuer is working fine. but i will change this Issuer((https://localhost:3000/api/v1/)) it's not working How to fix this Issue and I facing another issue also when I implement oldc-provider in node js. They Routes are override how to fix this issue
Sample.js
const { Provider } = require('oidc-provider');
const configuration = {
// ... see available options /docs
clients: [{
client_id: 'foo',
client_secret: 'bar',
redirect_uris: ['http://localhost:3000/api/v1/'],
true_provider: "pcc"
// + other client properties
}],
};
const oidc = new Provider('http://localhost:3000/api/v1/', configuration);
// express/nodejs style application callback (req, res, next) for use with express apps, see /examples/express.js
oidc.callback()
// or just expose a server standalone, see /examples/standalone.js
const server = oidc.listen(3000, () => {
console.log('oidc-provider listening on port 3000, check http://localhost:3000/api/v1/.well-known/openid-configuration');
});
Error
Defining Issuer Identifier with a path component does not affect anything route-wise.
You have two options, either mount the provider to a path (see docs), or define the actual paths you want for each endpoint to be prefixed (see docs).
I think you're looking for a way to mount, so the first one.

Can Open Telemetry Instrument Two Express Services in the Same Node Program?

Let's say I have a NodeJS program that has two separate instances of an express server running.
const express = require('express')
const app1 = express()
app1.listen(3000, () => { //... })
//...
const app2 = express()
app2.listen(3001, () => { //... })
I've been able to instrument a program like this via open telemetry, and have my spans sent/exported successfully to Zipkin. All I needed to do is/was add code like the following to the start of my program.
const { NodeTracerProvider } = require('#opentelemetry/node');
const { ZipkinExporter } = require('#opentelemetry/exporter-zipkin');
const provider = new NodeTracerProvider({
plugins: {
express: {
enabled: true,
},
http: {
requestHook: (span, request) => {
span.setAttribute("custom request hook attribute", "request");
},
},
}
});
const options = {
url: 'http://localhost:9411/api/v2/spans',
serviceName: 'service-main'
}
const zipkinExporter = new ZipkinExporter(options);
provider.addSpanProcessor(new SimpleSpanProcessor(zipkinExporter))
provider.register();
and make sure that the express and http plugins were/are installed
npm install #opentelemetry/plugin-http #opentelemetry/plugin-express
This all works great -- except for one thing. Open Telemetry sees both my express services running as the same service-main service.
When I instrumented these services directly with Zipkin -- I would add the Zipkin middleware to each running express server
app1.use(zipkinMiddleware({tracer: tracer1}));
app2.use(zipkinMiddleware({tracer: tracer2}));
Each tracer could be instantiated with its own service name, which allowed each service to have its individual name and show up as a different service in Zipkin.
(/main, /hello, and /goobye are all service via a different express service in the above URL)
Is this sort of thing (instrumenting two services in one program) possible with Open Telemetry? Or would I need to separate these two services out into separate programs in order to have each services have an individual name? This question is less about solving a particular problem, and more about understanding the semantics of Open Telemetry.
It is possible to create two separate tracer providers. Only one of them will be the global tracer provider, which the API will use if you call API methods. You can't use the plugins in this configuration, which means you will have to manually instrument your application. If this is a use-case which is important to you, I suggest you create an issue on the github repo.
yes, you can have multiple express running in the same node process (thats how clustering works in node as well)
but you will need to have them running on different ports.;
# const express = require('express')
const app1 = express()
app1.listen(3001, () => { //... })
//...
const app2 = express()
app2.listen(3002, () => { //... })

Get my Action’s server URL in (JavaScript) fulfilment code

I am using actionssdk and I build my Action fulfilments using Javascript and node.js + Express.
I am looking for a way to get the url (protocol + host name + port) of the server where the fulfilment is hosted.
Is there a simple way to do this? E.g. in the MAIN intent? Is there some conv-property I can use? Can I get hold of a req-parameter in the MAIN-intent, from which I can deduct hostname etc?
const express = require('express');
const expressApp = express();
const { actionssdk, ... } = require('actions-on-google');
const app = actionssdk({
ordersv3: true,
clientId: ...
});
expressApp.post('/fulfilment', app);
app.intent('actions.intent.MAIN', (conv) => {
let myUrl: string = ... // ???????
...
});
(background: obviously I know myself to where I deployed my fulfilment code. But I have a reusable template for fulfilment code in which I want to refer to the host url, and I do not want to type that in manually each time I develop a new Action).
You can get access to the request object in a middleware via Framework Metadata which is by default of type BuiltinFrameworkMetadata which contains objects used by Express
For example, you can use it like this, which will be ran before each request:
app.middleware((conv, framework) => {
console.log(framework.express.request.headers.host)
})

Swageer js doc does not instant update api docs on changes?

I am using swagger-jsdoc
I have setup swagger js docs like below in my app.js
//include swagger js doc
var swaggerJSDoc = require('swagger-jsdoc');
const swaggerUi = require('swagger-ui-express');
const pathToSwaggerUi = require('swagger-ui-dist').absolutePath()
const swaggerDefinition = {
swagger: '2.0',
info: {
// API informations (required)
title: 'API', // Title (required)
version: '1.0.0', // Version (required)
description: 'Used for api documentation', // Description (optional)
},
host: `localhost:3000`, // Host (optional)
basePath: '/app/v1', // Base path (optional)
};
// Options for the swagger docs
const options = {
// Import swaggerDefinitions
swaggerDefinition,
// Path to the API docs
// Note that this path is relative to the current directory from which the Node.js is ran, not the application itself.
apis: ['./app/v1/docs/*.yaml']
};
// Initialize swagger-jsdoc -> returns validated swagger spec in json format
const swaggerSpec = swaggerJSDoc(options);
app.use('/v1/docs', swaggerUi.serve, swaggerUi.setup(swaggerSpec));
I have certain yaml files which i have written for document the api. I hit the url from browser
localhost:3000/v1/docs
This shows me documented api in swagger ui. But when i make update in any of the yaml files and refresh the page then i don't see updated changes. I have to stop the nodemon process and restart the process again which i do not want to do. So let me know how can i do this?
By default, nodemon looks for files with the .js, .mjs, .coffee, .litcoffee, and .json extensions.
To add other extensions please use the following command:
nodemon -e yaml
For more details, refer to the official docs: https://www.npmjs.com/package/nodemon

Resources