ブラウザからNode.js(webサーバ)にアクセスした時のみMongoDBにアクセスできない

今、Node.jsをwebサーバとして、クライアントからリクエストがあればファイルを返すことや、DBにアクセスして取得したデータを返すということを行っている。
その一つの処理となっているDBアクセスで躓いている。

#できたこと
Node.jsからMongoDBにアクセスかつデータ取得は実現できた。
![スクリーンショット 2019-08-16 13.31.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351843/76c6209d-67fc-0192-40fb-a053dd3ff69d.png)

sample.js

```sample.js
const MongoClient = require('mongodb').MongoClient;
const assert = require('assert');

// Connection URL
const url = 'mongodb://localhost:27017';

// Database Name
const dbName = 'study';

//結果
var value;

const client = new MongoClient(url,{useNewUrlParser: true});

const findDocuments = function(db, callback) {
    // Get the documents collection
    const collection = db.collection('user');
    // Find some documents
    collection.find({}).toArray(function(err, docs) {
        assert.equal(err, null);
        console.log("Found the following records");
        value=docs
        console.log(value);
        callback(docs);
    });
}

// Use connect method to connect to the server
client.connect(function(err) {
    assert.equal(null, err);
    console.log("Connected correctly to server");

    const db = client.db(dbName);

    findDocuments(db, function() {
        client.close(); 
    });
});

            
```

###実行結果

```
hasegawa@hasegawa-W76OC:~/デスクトップ/akiyama/Node.js$ sudo node sample.js
[sudo] hasegawa のパスワード: 
[ { _id: 5d5364026ed8a1d78076d1f4,
    dist:
     [ 456,
       442,
       //省略
       461,
       461,
       ... 1900 more items ],
    rot:
     [ 0.05797865190578781,
       0.14626504446713978,
       //省略
       19.726678416929172,
       ... 1900 more items ] } ]

```





#やりたいこと
実際やりたいことは
1. クライアントからサーバにhtmlファイルをリクエスト
2. サーバはhtmlファイルを返す
3. そのhtmlファイルに仕込まれたコードでサーバに再びリクエスト
4. サーバはMongoDBにアクセスし、データを取得して返す

しかし、「できたこと」で使ったコードをそのまま使ってもMongoDBにアクセスできない。
![スクリーンショット 2019-08-16 13.41.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351843/8061bfa2-db27-8974-9b98-b970ea67ca92.png)


webserver.js

```webserver.js
// 必要なファイルを読み込み
var http = require('http');
var url = require('url');
var fs = require('fs');
var server = http.createServer();

// http.createServerがrequestされたら、(イベントハンドラ)
server.on('request', function (req, res) {
    // Responseオブジェクトを作成し、その中に必要な処理を書いていき、条件によって対応させる
    var Response = {
        "renderHTML": function () {
            var template = fs.readFile('./template/index.html', 'utf-8', function (err, data) {
                // HTTPレスポンスヘッダを出力する
                res.writeHead(200, {
                    'content-Type': 'text/html'
                });

                // HTTPレスポンスボディを出力する
                res.write(data);
                res.end();

            });

        },
        "getThree": function () {
            var template = fs.readFile('./js/three.js-master/build/three.min.js', 'utf-8', function (err, data) {
                // HTTPレスポンスヘッダを出力する
                res.writeHead(200, {
                    'content-Type': 'text/javascript'
                });

                // HTTPレスポンスボディを出力する
                res.write(data);
                res.end();
            });
         },
         "getOrbit": function () {
            var template = fs.readFile('./js/OrbitControls.js', 'utf-8', function (err, data) {
                 // HTTPレスポンスヘッダを出力する
                 res.writeHead(200, {
                     'content-Type': 'text/javascript'
                 });

                 // HTTPレスポンスボディを出力する
                 res.write(data);
                 res.end();
             });
          },
          "getValue": function () {
            const MongoClient = require('mongodb').MongoClient;
            const url = 'mongodb://localhost:27017';

            // Database Name
            const dbName = 'study';

            //結果
            var value;

            const client = new MongoClient(url,{useNewUrlParser: true});

            const findDocuments = function(db, callback) {
             // Get the documents collection
             const collection = db.collection('user');
             // Find some documents
             collection.find({}).toArray(function(err, docs) {
              assert.equal(err, null);
              console.log("Found the following records");
              value=docs
              console.log(value);
              callback(docs);
             });
            }

           // Use connect method to connect to the server
           client.connect(function(err) {
            assert.equal(null, err);
            console.log("Connected correctly to server");

            const db = client.db(dbName);

            findDocuments(db, function() {
             client.close(); 
            });
          });  
    
            // HTTPレスポンスヘッダを出力する
            res.writeHead(200, {
                'content-Type': 'text/html',
                'Access-Control-Allow-Origin': '*'
            });

            console.log("レスポンス");
            //console.log(result);

            // HTTPレスポンスボディを出力する
            res.write(value);
            res.end();
           }
  };
    // urlのpathをuriに代入
    var uri = url.parse(req.url).pathname;
    console.log(uri);


    // URIで行う処理を分岐させる
    if (uri === "/") {
        // URLが「http://localhost:8080/」の場合、"renderHTML"の処理を行う
        Response["renderHTML"]();
        return;
    } else if (uri === "/js/three.js-master/build/three.min.js") {
        // URLが「http://localhost:8080/js/three.js-master/build/three.min.js」の場合、"getThree"の処理を行う
        Response["getThree"]();
        return;
    } else if (uri === "/js/OrbitControls.js") {
        // URLが「http://localhost:8080/js/OrbitControls.js」の場合、"getOrbit"の処理を行う
        Response["getOrbit"]();
        return;
    } else if (uri === "/get_value") {
        // URLが「http://localhost:8080/get_value」の場合、"getThree"の処理を行う
        Response["getValue"]();
        return;
    };
  });

  // 指定されたポート(1234)でコネクションの受け入れを開始する
  server.listen(1234);
  console.log('Server running at http://localhost:80/');

```

index.html

```index.html
<html>
<head>
    <script type="text/javascript" src="js/three.js-master/build/three.min.js"></script>
    <script type="text/javascript" src="js/OrbitControls.js"></script>
</head>

<body>
    <div id="WebGL-area"></div>

    <script type="text/javascript">
    function getValue() {
      //promiseを使うことで簡潔に記述できる
      return new Promise((resolve, reject) => { //resolveまたはrejectの結果を返す
        var req = new XMLHttpRequest(); // HTTPでファイルを読み込むためのXMLHttpRrequestオブジェクトを生成、サーバと非同期通信するためのAPI
        req.open("get", "http://***:1234/get_value", false);
        req.setRequestHeader("Access-Control-Allow-Origin", "*");
        //受信が成功した時に呼び出されるイベント
        req.onload = () => {
          //通信が正常に終了したかを確認する
          if (req.readyState === 4 && req.status === 200) {
            resolve(req.responseType);
          } else {
            alert(req.status);
            reject(new Error(req.statusText));
          }
        };
        //受信が失敗した時に呼び出されるイベント
        req.onerror = () => {
          reject(new Error(req.statusText));
        };
        
        req.send(null); // HTTPリクエストの発行
      });
    }




    async function init() {
        var scene = new THREE.Scene();

        var renderer = new THREE.WebGLRenderer();
        renderer.setSize(900, 600);

        document.getElementById("WebGL-area").appendChild(renderer.domElement);




        var camera = new THREE.PerspectiveCamera(45, 1.5, 0.1, 1000);
        camera.position.set(30, 45, 30);
        camera.lookAt(scene.position);

        var controls = new THREE.OrbitControls(camera);
        controls.autoRotate = true; //自動周回


        // 座標軸を表示
        var axes = new THREE.AxisHelper(100);
        scene.add(axes);

        //形状オブジェクトの宣言と生成
        var geometry= new THREE.Geometry();

        var value;
        var dis=[];
        var rot=[];
        //dis,rot = await getCSV();
        value = await getValue();
        dis=value.dist;
        rot=value.rot;
        //dis=value.slice(0,2000);
        //rot=value.slice(2001,4000);
        //alert(dis[0]);
        //alert(rot[0]);
        //alert(dis);
        //alert(rot);


        // for(var i=0;i<1000;i++){
        //   geometry.vertices[i]= new THREE.Vector3((data[i][0] * Math.cos( data[i][1] * (Math.PI / 180) ))/2,
        //                                             0,
        //                                             (data[i][0] * Math.sin( data[i][1] * (Math.PI / 180) ))/2);
        // }

        for(var i=0;i<2000;i++){
          var x=(dis[i] * Math.cos( rot[i] * (Math.PI / 180) ))/2;
          var y=(dis[i] * Math.sin( rot[i] * (Math.PI / 180) ))/2;
          //alert(x);
          //alert(y);
          geometry.vertices[i]= new THREE.Vector3(x,0,y);
        }

        //材質オブジェクトの宣言と生成
        var material=new THREE.ParticleBasicMaterial({color: 0xFF0000, size: 10.0});
        //点オブジェクトの生成
        var particles = new THREE.ParticleSystem(geometry,material);
        //点オブジェクトのシーンへの追加
        scene.add(particles);



        render();

        function render() {
            controls.update();
            requestAnimationFrame(render);
            renderer.render(scene, camera);
        }
    }
      window.onload = init
    </script>
</body>
</html>

```

###実行結果

```
hasegawa@hasegawa-W76OC:~/デスクトップ/akiyama/Node.js$ sudo node webServer.js
[sudo] hasegawa のパスワード: 
Server running at http://localhost:80/
/
/js/three.js-master/build/three.min.js
/js/OrbitControls.js
/get_value
レスポンス
_http_outgoing.js:595
    throw new ERR_INVALID_ARG_TYPE('first argument',
    ^

TypeError [ERR_INVALID_ARG_TYPE]: The first argument must be one of type string or Buffer. Received type undefined
    at write_ (_http_outgoing.js:595:11)
    at ServerResponse.write (_http_outgoing.js:567:10)
    at Object.getValue (/home/hasegawa/デスクトップ/akiyama/Node.js/webServer.js:91:17)
    at Server.<anonymous> (/home/hasegawa/デスクトップ/akiyama/Node.js/webServer.js:115:29)
    at Server.emit (events.js:198:13)
    at parserOnIncoming (_http_server.js:677:12)
    at HTTPParser.parserOnHeadersComplete (_http_common.js:109:17)
```

実行結果をみるとclient.connectに入ることができていないことがわかります。




#確認したこと
サーバとDBだけのやりとりだとできているので、おそらくネットワーク的な問題。

- クライアントとサーバ両方のファイアウォールをオフ

```
hasegawa@hasegawa-W76OC:/etc$ sudo ufw status
状態: 非アクティブ
```

- ポート番号
mongodbのポート番号がLISTENになっていることを確認

```
hasegawa@hasegawa-W76OC:/etc$ netstat -an | grep 27017
tcp        0      0 127.0.0.1:27017         0.0.0.0:*               LISTEN     
unix  2      [ ACC ]     STREAM     LISTENING     1073161  /tmp/mongodb-27017.sock

```

127.0.0.1:27017となっているのはこのPCからしかアクセスできないということか。
結局今回はこのPCからアクセスしているから問題ないのか。