Node-REDのHTTPノードでクライアントのIPアドレスを取得する


本来取得したかったのはNode-REDのdashboardに接続しているクライアントのIPアドレスだったのだが、HTTPノードを利用する方法に落ち着いた。

方法

http inノードでエンドポイントを作成し、functionノードで取り出す。

functionノードの中身
msg.payload = msg.req.ip;
return msg;
フロー
[{"id":"9dad23b5.fd644","type":"http response","z":"4e3881be.18f2e","name":"","statusCode":"","headers":{},"x":550,"y":820,"wires":[]},{"id":"ea07abe6.815c98","type":"http in","z":"4e3881be.18f2e","name":"","url":"/clientip","method":"get","upload":false,"swaggerDoc":"","x":160,"y":820,"wires":[["a30561c.749e7a"]]},{"id":"a30561c.749e7a","type":"function","z":"4e3881be.18f2e","name":"set client ip to payload","func":"msg.payload = msg.req.ip;\nreturn msg;","outputs":1,"noerr":0,"x":360,"y":820,"wires":[["9dad23b5.fd644"]]}]

このフローをデプロイし、http://[node-redのhost]/clientip にアクセスすると、クライアントのIPアドレスが表示される。

ポイント

http inノードから出てくるmsgをdebugノードで見てもmsg.res.ipという要素が見つからないのだが、Node-REDはHTTPにExpressを使っているのでExpressの要素が使えるらしい。

参考

dashboardからこのAPIにアクセスする

さあ、HTTPのAPIができたのでdashboardでアクセスするか、と思い、下記のフローを作成。

しかし、返ってきたクライアントのIPアドレスは 127.0.0.1。Node-REDのホストから自分のAPIにHTTPリクエストしているので当然ですね…

仕方なくdashboardのtemplateノードを使って、ちゃんとクライアント側からHTTPリクエストが飛ぶようにした。

templateノードの中身
<script>
this.scope.action = function() {
    let xhr = new XMLHttpRequest();
    xhr.open("GET", "../clientip", false);
    try {
        xhr.send();
        if (xhr.status != 200) {
            return `Error ${xhr.status}: ${xhr.statusText}`;
        } else {
            return xhr.response;
        }
    } catch(err) {
        return "Request failed";
    }
}
</script>
<md-button ng-click="send({payload:action()})">
    Get IP Address
</md-button>
フロー
[{"id":"5eb60b39.a89a64","type":"ui_template","z":"4e3881be.18f2e","group":"4e09a2b6.c91f8c","name":"[button]Get IP Address","order":2,"width":0,"height":0,"format":"<script>\nthis.scope.action = function() {\n    let xhr = new XMLHttpRequest();\n    xhr.open(\"GET\", \"../clientip\", false);\n    try {\n        xhr.send();\n        if (xhr.status != 200) {\n            return `Error ${xhr.status}: ${xhr.statusText}`;\n        } else {\n            return xhr.response;\n        }\n    } catch(err) {\n        return \"Request failed\";\n    }\n}\n</script>\n<md-button ng-click=\"send({payload:action()})\">\n    Get IP Address\n</md-button>","storeOutMessages":true,"fwdInMessages":true,"templateScope":"local","x":300,"y":1060,"wires":[["2f5c3897.ce4548"]]},{"id":"2f5c3897.ce4548","type":"debug","z":"4e3881be.18f2e","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":510,"y":1060,"wires":[]},{"id":"4e09a2b6.c91f8c","type":"ui_group","z":"","name":"デフォルト","tab":"531fac22.ff06a4","disp":true,"width":"6","collapse":false},{"id":"531fac22.ff06a4","type":"ui_tab","z":"","name":"ホーム","icon":"dashboard","disabled":false,"hidden":false}]

これでちゃんとdashboardからクライアントのIPアドレスが取得できた。