Node-RED で IBM MQ on CloudにREST-APIで送受信するWebアプリ作成

[IBM MQ on Cloud を試してみる](https://qiita.com/nishikyon/items/751136ae0ccd2b0a634a)という記事の続編で、Node-REDでこのIBM MQ on CloudにREST-APIで送受信するWebアプリ作成してみましたので、その手順を説明します。

# 0. 前提
REST APIが使用できるMQがあること。
ない場合は「[IBM MQ on Cloud を試してみる](https://qiita.com/nishikyon/items/751136ae0ccd2b0a634a)」を参考に準備してください。

# 1. Node-REDの準備
[もう無料のCloud Foundry環境はIBM Cloudにはない](https://www.ibm.com/blogs/solutions/jp-ja/cloud-foundry-eos/)ので、移行先として推奨されている IBM Cloud 上のCode Engineで構築しました。
無料枠があるので、お遊び程度なら費用は発生しない「はず」です。絶対無料枠におさまるかは不明ですので、ご注意ください。
方法は
[Node-REDをIBM Cloud Code Engineで動かしてみる](https://qiita.com/satokota/items/9c2d9d16cb61eeb182f8)を参照させていただき、作成しました。

準備ができたら、Node-REDを開いてください。

もし、1つ1つではなくて、一気に完成フローがほしい場合は

- https://github.com/kyokonishito/node-red-mq/blob/main/mqtool-flows.json

に完成フローを置いていますので、こちらを読み込んでお使いください。

# 2. Webページ表示部分の作成
Node-REDの基本的な部分ですよね。Webページを表示させるのは。
今回はMQのREST-APIに必要な情報をフォームに入れた上で、MQのGETとPUTができるようなシングルページアプリケーション(SPA)のwebページのhtmlファイルを作りました。(このページの作り方はNode-REDと関係ないので今回は説明しません。)


まずは以下の3つのノードをつなげます:
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/0c84a0c2-8e35-abb3-b3c1-047601e3d663.png)

以下ノードの編集画面を貼っていくいので、同じように入力してください。
### #1 http in ノード
GETリクエストを受ける部分です。　
`https://[Nore-REDのホスト名]/mqtool`がWebページのurlとなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/847dc313-9c25-7bff-a9f6-7d5fa2ced5d7.png)

### #2 template ノード
表示するwebページをセットします。
https://github.com/kyokonishito/node-red-mq/blob/main/mqtool.html から表示されたhtml(javascript含む)全体をコピーします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/4fa0374d-e23a-21d8-957f-80693c33e559.png)


その後、template ノードのテンプレート部分に貼り付けます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/16a4cf6f-d1a3-e8cc-7603-f8c1f15e58f6.png)

### #3 http responseノード
出力を返します。中身の編集は不要です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/29f8875b-27ac-33f9-18a7-d1a7676ec9e0.png)

全てのノードの編集が完了したら、「デプロイ」を実施します。

デプロイ完了後、`https://[Nore-REDのホスト名]/mqtool`にWebブラウザーでアクセスしてみてください。以下のようなWebページが表示されればOKです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/f9b1fa18-8abc-5ada-514b-5e1738e1c2dd.png)


MQ Server 情報と送付するメッセージを入力して「送信」ボタンをクリックすると指定したMQのキューにメッセージが送付されます。

MQ Server 情報入力の上、「Get Message from　XXXX」ボタンをクリックすると、MQのキューから1メッセージ取得します。


# 3. [送信]ボタン処理の作成
[送信]ボタンはMQ Server 情報と送付するメッセージを`./send-message`へPOSTします。その後Node-RED上でMQにREST APIでメッセージをPUTし、結果を受け取ります。

まずは以下の5つのノードをつなげます。深緑のdebugノードはdebug用なので説明は省略します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/e9c735e2-83b4-4222-30a5-c28ca992354f.png)

以下ノードの編集画面を貼っていくいので、同じように入力してください。

### #1 http in ノード
POSTリクエストを受ける部分です。　
`https://[Nore-REDのホスト名]/send-message`がPOST用のurlとなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/9433eac3-b81a-d250-dfda-ab60437cf84d.png)

### #2 function ノード
POSTで受け取ったパラメータをMQのREST APIに沿った形で次のhttp requestノードに渡せるように加工しています。
基本認証用のhttp request headerもここでセットしています。
またPUTするメッセージの前に現在日時を付与する加工をしています。
コードタブのコード入力部分に以下をコピペします。
```javascript
// send-message 
// POST Dataの取得
var hostname = msg.payload.mq_hostname;
var qmgr_name = msg.payload.qmgr_name;
var q_name= msg.payload.q_name;
var send_message= msg.payload.send_message;

// REST API URL
msg.api_url = hostname+'/ibmmq/rest/v1/messaging/qmgr/'+qmgr_name+'/queue/'+q_name+'/message'

// Set Basic Auth
msg.headers = {};
msg.headers['Authorization'] = 'Basic ' + new Buffer(msg.payload.mq_userid + ':' + msg.payload.mq_password).toString('base64');
msg.headers['content-type'] = 'text/plain;charset=utf-8';
msg.headers['ibm-mq-rest-csrf-token'] = 'blank';

// メッセージの前に現在日時を付与
const date1 = new Date();
msg.payload = date1.toLocaleString('ja-JP', { timeZone: 'Asia/Tokyo' }) + ': ' +  send_message ;
msg.send_message=msg.payload;

return msg;
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/281bf9b9-06a6-2128-4241-9fa2c4a88221.png)


### #3 http request ノード
前ノードから受け取った情報を使ってMQにREST APIでアクセスし、メッセージをPUTする部分です。

URLには前ノードでセットしたmsg.api_urlの値を使用するため、`{{{api_url}}}`と入れています。
基本認証については前ノードでセットしたmsg.headersの値が使用されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/7c725b1e-93e8-fcc5-72f0-c115bcaee739.png)


### #4 function ノード
MQのREST APIのレスポンスをWebブラウザーへのレスポンス用に加工しています。
レスポンスのエラーコードの判断もここでしています。

コードタブのコード入力部分に以下をコピペします。
```javascript
// post-message
// parse respose
var status_code = msg.statusCode;
var result = ''
var ibm_mq_md_messageid = ''
var message = ''

if(status_code == 201){
    result = 'OK';
    ibm_mq_md_messageid = msg.headers['ibm-mq-md-messageid'];
    message = msg.send_message;
}
else{
    result = 'NG';
    message = msg.payload;
}


msg.payload = {
    'result': result,
    'message': message,
    'status_code': status_code,
    'ibm_mq_md_messageid': ibm_mq_md_messageid
};
return msg;
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/7be66a0c-262a-6fd0-33d7-3d689da13371.png)


### #5 http responseノード
出力を返します。中身の編集は不要です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/cdc91aa7-f158-e321-c2e3-222207d036b8.png)

全てのノードの編集が完了したら、「デプロイ」を実施します。

デプロイ完了後、MQ Server 情報と送付するMessageを入力して「送信」ボタンをクリックして、メッセージをPUTしてみます。

MQ Server 情報の取得方法がわからない場合は「[IBM MQ on Cloud を試してみる - 5.1 必要情報の取得](https://qiita.com/nishikyon/items/751136ae0ccd2b0a634a#51-%E5%BF%85%E8%A6%81%E6%83%85%E5%A0%B1%E3%81%AE%E5%8F%96%E5%BE%97)」を参照してみてください。

ちなみに`RESTAPI endpoint hostname`は上のLink先の方法ではパスもついたendpointが取得できるのですが、**ホスト名のみ**を入れてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/766cecdf-988d-3b04-d4e9-298585c0e82c.png)

表示されたResultがOKであれば送付成功です。

# 4. [Get Message from xx]ボタン処理の作成
xxにはキュー名が入ります。
[Get Message from xx]ボタンはMQ Server 情報を`./get-message`へPOSTします。その後Node-RED上でMQにREST APIでメッセージをGETし、結果を受け取ります。

まずは以下の5つのノードをつなげます。深緑のdebugノードはdebug用なので説明は省略します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/fce5aa27-3195-0280-cf5c-2af6b9a35c9d.png)

### #1 http in ノード
POSTリクエストを受ける部分です。　
`https://[Nore-REDのホスト名]/get-message`がPOST用のurlとなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/47517b2e-4099-5038-f460-e94666b3f50c.png)


### #2 function ノード
POSTで受け取ったパラメータをMQのREST APIに沿った形で次のhttp requestノードに渡せるように加工しています。
基本認証用のhttp request headerをここでセットしています。

コードタブのコード入力部分に以下をコピペします。
```javascript
// get-message 
// POST Dataの取得
var hostname = msg.payload.mq_hostname;
var qmgr_name = msg.payload.qmgr_name;
var q_name= msg.payload.q_name;

// REST API URL
msg.api_url = hostname+'/ibmmq/rest/v1/messaging/qmgr/'+qmgr_name+'/queue/'+q_name+'/message'

// Set Basic Auth
msg.headers = {};
msg.headers['Authorization'] = 'Basic ' + new Buffer(msg.payload.mq_userid + ':' + msg.payload.mq_password).toString('base64');
msg.headers['content-type'] = 'text/plain;';
msg.headers['ibm-mq-rest-csrf-token'] = 'blank';


return msg;
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/db9b0aa2-621e-36fc-0457-e2ada98fc7bc.png)



### #3 http request ノード
前ノードから受け取った情報を使ってMQにREST APIでアクセスし、メッセージをGETする部分です。

URLには前ノードでセットしたmsg.api_urlの値を使用するため、`{{{api_url}}}`と入れています。
基本認証については前ノードでセットしたmsg.headersの値が使用されます。
メソッドは`DELETE`　なのでご注意ください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/5b3c3051-19a8-7a73-1c50-cbd881e89a5f.png)



### #4 function ノード
MQのREST APIのレスポンスをWebブラウザーへのレスポンス用に加工しています。
レスポンスのエラーコードの判断もここでしています。

コードタブのコード入力部分に以下をコピペします。
```javascript
// get-message
// parse reponse
var status_code = msg.statusCode;
var result = ''
var ibm_mq_md_messageid = ''
var message = ''

if(status_code == 200){
    result = 'OK';
    ibm_mq_md_messageid = msg.headers['ibm-mq-md-messageid'];
}
else{
    result = 'NG';
}

message = msg.payload;


msg.payload = {
    'result': result,
    'message': message,
    'status_code': status_code,
    'ibm_mq_md_messageid': ibm_mq_md_messageid
};
return msg;
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/19c025bb-6b08-3a32-06f6-adf636e8e285.png)


### #5 http responseノード
出力を返します。中身の編集は不要です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/cdc91aa7-f158-e321-c2e3-222207d036b8.png)

全てのノードの編集が完了したら、「デプロイ」を実施します。

デプロイ完了後、MQ Server 情報を入力して[Get Message from xx]ボタン(xxにはキュー名が入ります)をクリックして、メッセージをGetしてみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/ce087793-432f-da61-eb1d-b6583f6f340d.png)


表示されたResultがOKであれば送付成功です。GETしたメッセージはキューから削除されます。

# 5. まとめ
全体のフローは3つになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/9ffe2dc0-623a-a48f-ea6f-225041155b56.png)

画面のhtmlファイルの説明をしてませんが、[Vue v2](https://jp.vuejs.org/v2/guide/index.html)と[bootswatch](https://bootswatch.com/)を使用して作成しています。


以上です。