今、Node.jsをwebサーバとして、クライアントからリクエストがあればファイルを返すことや、DBにアクセスして取得したデータを返すということを行っている。
その一つの処理となっているDBアクセスで躓いている。
できたこと
Node.jsからMongoDBにアクセスかつデータ取得は実現できた。
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 ] } ]
やりたいこと
実際やりたいことは
- クライアントからサーバにhtmlファイルをリクエスト
- サーバはhtmlファイルを返す
- そのhtmlファイルに仕込まれたコードでサーバに再びリクエスト
- サーバはMongoDBにアクセスし、データを取得して返す
しかし、「できたこと」で使ったコードをそのまま使ってもMongoDBにアクセスできない。
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からアクセスしているから問題ないのか。