Adam FreemanによるApressの「Pro JavaScript for Web Apps」の提案に従ってNodeをセットアップしようとしています。Mac (OS 10.6.8) マシンに Node (0.10.7) をインストールし、Node が動作していることを証明するさまざまな例を実行しました。
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World\n');
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');
そのため、ターミナルから Node を起動し、ブラウザで「Hello World」を取得できます。これまでのところ、すべて順調に見えます。
次に、本で提案されている特定のパッケージを追加するコマンドを発行します。
npm install node-static jqtpl
それも機能します。HTTP GET コマンドを介して大量のものを取得し、エラーなしでそれらをインストールしているようです。
Adam のサンプル ファイルには 2 つのコンポーネントがあります。「server.js」ファイルと、各章のサンプルを含む「content」ディレクトリです。私の問題は、ファイルとコンテンツディレクトリの間のパス、またはこの EACCESS エラーのグーグル検索に基づいて、いくつかの権限の問題に関係しているようです。私はさまざまな構成を試しました (server.js を Mac のユーザー ディレクトリである「dave」ディレクトリに配置し、「content」ディレクトリを「dave」のサブディレクトリとして配置しました。それが彼が望んでいるようです)。本の指示から; または server.js をコンテンツ ディレクトリに配置する; パス エラーのために動作しないようです。
いずれにせよ、「server.js」を「dave」ディレクトリに置き、「content」も「dave」ディレクトリに存在させると(実際には、server.jsがディレクトリ内に存在するすべてのディレクトリに当てはまるようです。コンテンツも同じディレクトリに存在します)、私はこれを取得します:
dave$ node server.js
Ready on port 80
events.js:72
throw er; // Unhandled 'error' event
^
Error: listen EACCES
at errnoException (net.js:884:11)
at Server._listen2 (net.js:1003:19)
at listen (net.js:1044:10)
at Server.listen (net.js:1110:5)
at Object.<anonymous> (/Users/dave/NodeJsTesting/server.js:92:34)
at Module._compile (module.js:456:26)
at Object.Module._extensions..js (module.js:474:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
at Function.Module.runMain (module.js:497:10)
警告: 私はほとんど Unix の初心者 (私は .Net 開発者です) であるため、Unix のアクセス許可、パス、または PATH 変数について理解できないことがある可能性があります。Adam は、「Node.js ディレクトリに」何かを入れることについて話していますが、これはおそらく十分に具体的ではないと思います。ローカル マシンでの動作についての私の観察では、NODE 実行可能ファイルは明らかに PATH にあるということです。これは、ユーザー ディレクトリから上記のコマンドを実行できるためです。とにかく、これはいくつかの権限の問題だと思います。
完全を期すために、Adam のコードを次に示します。
var http = require('http');
var url = require('url');
var fs = require('fs');
var nodestatic = require('node-static');
var jqtpl = require("jqtpl");
var querystring = require('querystring');
var fileserver = new(nodestatic.Server)("./content", { cache: 1 });
var productData = JSON.parse(fs.readFileSync("./content/products.json"));
function handleRequest(req, res) {
console.log(req.method + " request for " + req.url);
if (req.method == "POST") {
var fullBody = '';
req.on('data', function(chunk) {fullBody += chunk.toString();});
req.on('end', function() {
var data = createDataObject(querystring.parse(fullBody));
if (req.headers['x-http-method-override']) {
var productID = req.url.split("/").pop();
switch (req.headers['x-http-method-override']) {
case "delete":
data.deleteItem(productID);
break;
case "put":
var item = data.getItem(productID);
if (item) {
item.name = data.getAndRemoveDataProp("name");
item.price = data.getAndRemoveDataProp("price")
}
break;
}
writeJSONData(res, productData);
} else {
switch (req.url) {
case "/formecho":
case "/basket":
case "/basket":
case "/shipping":
case "/summary":
res.write(jqtpl.tmpl(loadTemplate(req.url.substring(1)), data));
break;
}
res.end();
}
});
} else {
if (req.url.indexOf("/shortJSONP") == 0) {
var callback = querystring.parse(url.parse(req.url).query)["callback"];
res.setHeader("Content-Type", "text/javascript");
res.write(callback + "(" + JSON.stringify([productData[0]]) + ")");
res.end();
} else {
if (req.headers["origin"] && req.headers["origin"].indexOf("cheeselux") > -1) {
res.setHeader("Access-Control-Allow-Origin", req.headers["origin"]);
}
switch (req.url) {
case "/cheeselux.appcache":
fileserver.serveFile("cheeselux.appcache", 200,
{"Content-Type": "text/cache-manifest"}, req, res);
break;
case "/products.json.slow":
setTimeout(function() {
fileserver.serveFile("products.json", 200, null, req, res);
}, 1000);
break;
case "/shortJSONList":
writeJSONData(res, [productData[0]]);
break;
case "/admin/products":
writeJSONData(res, productData);
break;
default:
if (req.url == "/") {
req.url = "/example.html";
}
fileserver.serve(req, res);
break;
};
}
}
}
http.createServer(handleRequest).listen(80);
console.log("Ready on port 80");
function loadTemplate(name) {
return fs.readFileSync("content/" + name + ".html").toString();
}
function writeJSONData(res, data) {
res.setHeader("Content-Type", "application/json");
res.write(JSON.stringify(data));
res.end();
}
function createDataObject(reqData) {
var data = {
properties: [],
getItem: function(id) {
for (var i = 0; i < productData.length; i++) {
for (var j = 0; j < productData[i].items.length; j++) {
if (productData[i].items[j].id == id) {
return productData[i].items[j];
}
}
}
return null;
},
deleteItem: function(id) {
for (var i = 0; i < productData.length; i++) {
for (var j = 0; j < productData[i].items.length; j++) {
if (productData[i].items[j].id == id) {
productData[i].items.splice(j, 1);
}
}
}
},
getProp: function (id, prop) {
for (var i = 0; i < productData.length; i++) {
for (var j = 0; j < productData[i].items.length; j++) {
if (productData[i].items[j].id == id) {
return productData[i].items[j][prop];
}
}
}
return "";
},
getAndRemoveDataProp: function(prop) {
for (var i = 0; i < this.properties.length; i++) {
if (this.properties[i].propName == prop) {
var result = this.properties[i].propVal;
this.properties.splice(i, 1);
return result;
}
}
return "";
},
total: 0,
getSubtotal: function(id, quantity) {
var price = this.getProp(id, "price") * quantity;
this.total += price;
return price;
}
}
for (var prop in reqData) {
data.properties.push({propName: prop, propVal: reqData[prop]})
}
return data;
}