expressでswaggerを利用する


## 参考

* https://github.com/Surnet/swagger-jsdoc/blob/master/docs/GETTING-STARTED.md


## 前提知識

### トップダウンかボトムアップか

swaggerには、

* Swagger Specを記述し、それの基づきAPI（モック）を生成する方法（トップダウン）
* 既存のAPIにアノテーションを記述しSwagger Specを生成する方法（ボトムアップ）

の2形式の利用方法がある。もちろん組み合わせもあるとは思います。
私の場合は、後者のボトムアップを使うケースの方が多いのので、その方法を以下に記述します。

>とはいえ、結局アノテーション自体を自動生成してくれるわけじゃないからトップダウンで書いてもいいのでは？と思います。

### swagger-ui

トップダウンにせよボトムアップにせよ仕様のドキュメント化には、記述した（あるいは生成された）Swagger Specをswagger-uiで見ることになります。

swagger-uiは[ここ](https://swagger.io/swagger-ui/)からダウンロードするかcloneして、そのままdist/index.htmlを開くと動きます。

>http経由にすることもないようです。

## 必要なものの準備

### インストール

```bash
npm install express
npm install swagger-jsdoc
```

swagger-uiは既に上記でDownloadしているものとします。

## 実装

通常はいろいろファイルを分けるのでしょうけど、ここでは一旦１つのファイルに記述してみました。

app.get('/api-docs.json', function(req, res){});

を定義するまでが、swaggerを利用するための記述で、api-docs.jsonを返すための記述です。
その他は、app.post('/login', function(req, res){});とその仕様を記述しています（長い・・・）。

```js:index.js
var express = require('express');
var app = express();
var swaggerJSDoc = require('swagger-jsdoc');

//クロスサイト対応。swagger-uiから見た際、クロスサイトのエラーがでることへの対応。
app.use(function(req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    next();
});

//swaggerの基本定義
var options = {
    swaggerDefinition: {
        info: {
            title: 'Hello World',
            version: '1.0.0.'
        },
    },
    apis: ['./index.js'], //自分自身を指定。外部化した場合は、そのファイルを指定。配列で複数指定も可能。
};

var swaggerSpec = swaggerJSDoc(options);

//swagger-ui向けにjsonを返すAPI
app.get('/api-docs.json', function(req, res){
    res.setHeader('Content-Type','application/json');
    res.send(swaggerSpec);
});

// 以下、使用を定義するAPI

/**
 * @swagger
 * /login:
 *   post:
 *     description: Login to the application
 *     produces:
 *       - application/json
 *     parameters:
 *       - name: username
 *         description: Username to use for login.
 *         in: formData
 *         required: true
 *         type: string
 *       - name: password
 *         description: User's password.
 *         in: formData
 *         required: true
 *         type: string
 *     responses:
 *       200:
 *         description: login
 */
app.post('/login', function(req, res) {
    res.json(req.body);
});

//listen
app.listen(3000, function(){
    console.log("Listen on port 3000.");
});

```

わかれば簡単ですが、わかるまでが大変でした。

## 利用

### 起動

```bash
node index.js
```

### api-docs.jsonを取得

http://localhost:3000/api-docs.json

にアクセス。

```js
{"info":{"title":"Hello World","version":"1.0.0."},"swagger":"2.0","paths":{"/login":{"post":{"description":"Login to the application","produces":["application/json"],"parameters":[{"name":"username","description":"Username to use for login.","in":"formData","required":true,"type":"string"},{"name":"password","description":"User's password.","in":"formData","required":true,"type":"string"}],"responses":{"200":{"description":"login"}}}}},"definitions":{},"responses":{},"parameters":{},"securityDefinitions":{},"tags":[]}
```

### swagger-uiで閲覧

swagger-ui/dist/index.htmlを開きます。

http://localhost:3000/api-docs.json を上部の[Explore]左のテキストボックスに入れて、[Explore]ボタンを押します。

HelloWorldのページが表示されればOK。

<img width="979" alt="スクリーンショット 2018-04-15 13.05.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/55188/35f25bc9-818f-542f-97a0-9524b17e2aa5.png">

## その他

### swagger-editor

swagger-editer自体は[オンライン版](http://editor.swagger.io/#/)を使うか、ローカルの落として使えます。試すだけなら取り敢えずオンライン版でいいかと。