Open ctippur opened 4 years ago
Any takers on this pls?
var cors = require("cors");
...
var app = expressAppConfig.getApp();
app.use(cors());
Hope this would be helpful.
Hello,
The problem comes from the fact that this plugin configure the app in a bad way. Just to deactivate a type of logs, I had to create a pull request with a simple parameter which deactivate logging.
Your problem comes from the configuration of the app in the ExpressAppConfig of the module:
class ExpressAppConfig { constructor(definitionPath, appOptions) { this.definitionPath = definitionPath; this.routingOptions = appOptions.routing; this.setOpenApiValidatorOptions(definitionPath, appOptions); this.app = express(); const spec = fs.readFileSync(definitionPath, 'utf8'); const swaggerDoc = jsyaml.safeLoad(spec); this.app.use(bodyParser.urlencoded()); this.app.use(bodyParser.text()); this.app.use(bodyParser.json()); this.app.use(this.configureLogger(appOptions.logging)); this.app.use(express.json()); this.app.use(express.urlencoded({ extended: false })); this.app.use(cookieParser()); const swaggerUi = new swagger_ui_1.SwaggerUI(swaggerDoc, appOptions.swaggerUI); this.app.use(swaggerUi.serveStaticContent()); this.app.use(OpenApiValidator.middleware(this.openApiValidatorOptions)); this.app.use(new swagger_parameters_1.SwaggerParameters().checkParameters()); this.app.use(new swagger_router_1.SwaggerRouter().initialize(this.routingOptions)); this.app.use(this.errorHandler); }
Here you can see that the whole stack of middleware is injected ("app.use") in the app before defining the routes from the open api contract. The problem is that it is really hard to modify the Express middleware stack once you have set the routes.
Using app.use(cors()); after you received your app from expressAppConfig, like suggested above without testing it, will be simply ignored because the middleware layers added before by the app configurator will fill some unknown logic before getting to the one added by the cors middleware (probably some header "Access-Control-Allow-Origin" related logic).
So, if you modify the module and simply add:
this.app.use(express.urlencoded({ extended: false })); this.app.use(cookieParser()); **this.app.use(cors());** const swaggerUi = new swagger_ui_1.SwaggerUI(swaggerDoc, appOptions.swaggerUI); this.app.use(swaggerUi.serveStaticContent());
You can now use CORS without problems.
In the future, this should be included by default in the module as an option.
thanks a lot @thomasgainant for your comment. I'll keep this in mind for future changes.
I think that the same happens with errorHandler, I haven't override default error format
my solution for this problem was this:
const openApiApp = expressAppConfig.getApp();
const app = express();
// Add headers
app.use(/.*/, cors());
for (let i = 2; i < openApiApp._router.stack.length; i++) {
app._router.stack.push(openApiApp._router.stack[i])
}
Hi,
i just fixed it in my fork https://github.com/slavomir-sidor/oas3-tools
you can use it in your index.js
'use strict';
var path = require('path'); var http = require('http');
var oas3Tools = require('oas3-tools'); var serverPort = 8080; app=express() // swaggerRouter configuration var options = { routing: { controllers: path.join(__dirname, './controllers') }, cors:{ "optionsSuccessStatus": 200, "credentials": true, "origin": ["http://localhost:4200"], "methods": "GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS,CONNECT,TRACE", "exposedHeaders": true, "preflightContinue": false, } };
var expressAppConfig = oas3Tools.expressAppConfig(path.join(__dirname, 'api/openapi.yaml'), options); var app = expressAppConfig.getApp();
// Initialize the Swagger middleware http.createServer(app).listen(serverPort, function () { console.log('Your server is listening on port %d (http://localhost:%d)', serverPort, serverPort); console.log('Swagger-ui is available on http://localhost:%d/docs', serverPort); });
Hi Slavomir, Thanks for the updates. In our project we want to use two Swagger definitions, one for the customer and one for internal testing purpose. I want to know how to integrate that in the same project. When we create server side node js code (which consists of the apis to be given to the customer), we get the directory structure as follows: app | openapi.yaml controllers | Default.js service | DefaultService.js utils | writer.js index.js In this directory structure, we edit the index.js and add the code similar what you have explained above.
Now If i create another server side nodejs code (for internal) the same directory structure repeats. Now My question is how to add the code in the secondly generated nodejs code index.js. We may need to use different server port may be 8081. Can you please give your suggestions how to handle this.
my solution for this problem was this:
const openApiApp = expressAppConfig.getApp(); const app = express(); // Add headers app.use(/.*/, cors()); for (let i = 2; i < openApiApp._router.stack.length; i++) { app._router.stack.push(openApiApp._router.stack[i]) }
I've found that when you add a middleware to express with app.use it simply add it to the end of the stack (here you can see the app.use function). The problem with oas3-tools is in the line 50 of express.app.config.js, and happens because middlewares are executed in the same order of the stack array therefore every middleware after that will be "skipped".
I've wrote a workaroudn that firstly add the middleware to the stack, then move the "SwaggerRouter" and the "ErrorHandler" at the end of the stack (after the new middleware)
function insertMiddleware(app, middleware) {
const stackLength = app._router.stack.length;
app.use(middleware);
app._router.stack.push(...app._router.stack.splice(stackLength - 2, 2));
}
insertMiddleware(app, cors());
I'm not an expert therefore i'm not sure that works every time, but i've tried with cors and it works.
P.S. i've noticed that with the newer version the problem should be fixed, but it is not released in npm
I still facing with this problem.
I can solve it on local with the solutions proposed, but I can't fix it on my remote server. I deploy the API server with docker-compose and I can't make this patch on the docker image.
Has someone a solution for this?
For one's who looking for easy solution: go to generated code utils/writer.js
and modify resposne.writeHead
code:
response.writeHead(code, {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': "GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS,CONNECT,TRACE"
});
Have tried all the suggested solutions in this thread in my code and still running into the same issue. Anyone have an updated suggestion?
Edit:
Was a bit put off editing the source code as it seems a bit extreme, most other server implementations I've used have an option you can set that will work for this kind of thing.
Making the change to the source of the oas3-tools source as suggested by @thomasgainant resolved the issue for me. Thank you.
This is how I made it
const app = expressAppConfig.getApp();
app.use(cors());
// Get a reference to the router stack
let stack = app._router.stack;
// Find the indices of corsMiddleware and expressInit
let corsIndex = stack.findIndex(layer => layer.name === 'corsMiddleware');
let expressInitIndex = stack.findIndex(layer => layer.name === 'expressInit');
// Check if both middleware are in the stack
if (corsIndex !== -1 && expressInitIndex !== -1) {
// Remove corsMiddleware from its current position
let corsMiddleware = stack.splice(corsIndex, 1)[0];
// If cors was after expressInit in the stack, decrement expressInitIndex
if (corsIndex > expressInitIndex) {
expressInitIndex--;
}
// Insert corsMiddleware before expressInit
stack.splice(expressInitIndex, 0, corsMiddleware);
}
Thanks @bouchaala-sabri , this is elegant workaround and it works
For one's who looking for easy solution: go to generated code
utils/writer.js
and modifyresposne.writeHead
code:response.writeHead(code, { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': "GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS,CONNECT,TRACE" });
This works with simple requests, but for all others it will fail to answer preflight check. For non-simple requests, browser sends OPTIONS and expects 2xx response, Express responds with 405 Method not allowed, unless you properly initialize CORS middleware...
Hello, I am struggling to add CORS support to my app running on swagger server. I tried using swagger-express-middleware but that dint do the trick. Looks like they are not yet supporting openapi 3.0 specs.
Need some pointers please.
I have a middleware code as shown in the example:
My curl call is resulting in a 405 error.
I am sure I am doing something wrong. Appreciate any pointers.