Swagger EditorのGenerate Serverで生成したNode.js serverのcors問題を解消した話

備忘録代わりとして書きます。
間違い、より楽なやり方もあると思いますのでご指摘大歓迎です。


#概要
openapi3.0でYAMLファイルを書き、
Swagger EditorのGenerate Server機能を用いてNode.jsを自動生成し、
HerokuへデプロイしてMock Serverにしようとしました。


#やり方
Mock Serverコードを記述したらGenerate Server > nodejs-serverを選択し、サーバコードをダウンロードする。
![https___qiita-image-store.s3.amazonaws.com_0_19698_498beaf3-8a46-a99b-0db2-c3741602b8f2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/694565/79a3616d-ae92-2f34-58f1-2e7fb44628c8.png)


ダウンロードしたNode.jsを解凍し、index.jsを変更する。

```javascript:./index.js

'use strict';

var path = require('path');
var http = require('http');

var oas3Tools = require('oas3-tools');
//var serverPort = 8080;//ここを変更
var serverPort = process.env.PORT || 8080;

// swaggerRouter configuration
var options = {
    routing: {
        controllers: path.join(__dirname, './controllers')
    },
};

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);
});
```

#発生した問題
Herokuへデプロイし、確認した所

```
Access to XMLHttpRequest at 'http://localhost:8081' from origin 'https://test-app-20210113.herokuapp.com/
' has been blocked by CORS policy:
```

のようなエラーが発生。
調べてみたところ、CORS policyというものが問題のよう。

cors modulesをインポートしてexpress moduleを使う際に
app.(use(cors))とすると解決できるようですが、そもそもexpress moduleはどこ・・・

#解決法
index.jsを読んでみるとoas3Toolsという独自モジュールを使っているらしい。
node_modules -> oas3-tools -> dist -> middleware ->express.app.config.jsにcorsをインポート

```javascript:./node_modules/oas3-tools/dist/middleware/express.app.config.js

'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
exports.ExpressAppConfig = void 0;
const express = require("express");
const cors = require("cors");//追加
const cookieParser = require("cookie-parser");
const bodyParser = require("body-parser");
const swagger_ui_1 = require("./swagger.ui");
const swagger_router_1 = require("./swagger.router");
const swagger_parameters_1 = require("./swagger.parameters");
const logger = require("morgan");
const fs = require("fs");
const jsyaml = require("js-yaml");
const OpenApiValidator = require("express-openapi-validator");
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(cors());//追加
        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);
    }
```

gitignoreからnode_modulesを削除し、この状態でHerokuへデプロイした所きちんと動くようになりました。

#patch-packageの利用
直すことは出来ましたが、node_modulesを直接いじり、
node_modulesごとHerokuへデプロイするのは色々な面で問題がある実装なので
patch-package moduleをインポートして利用することに
（node_moduleを手動で変更している時点で本来良くないですが・・・）
詳しくは参考文献をご覧ください。

#参考文献
[なんとなく CORS がわかる...はもう終わりにする。](https://qiita.com/att55/items/2154a8aad8bf1409db2b)
[Swagger x Heroku で手軽に API モック＆ドキュメントを作る](https://qiita.com/tanabee/items/e6cedfcc75a4e50e3ad2)
[かゆいところに手が届く！patch-packageでnpmパッケージを乗りこなそう](https://bagelee.com/programming/javascript-2/patch-package/)