1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
|
---
title: フレームワークなしの Node.js サーバ
slug: Learn/Server-side/Node_server_without_framework
tags:
- JavaScript
- NeedsContent
- Node
- サーバ
- フレームワークなし
translation_of: Learn/Server-side/Node_server_without_framework
---
<div>{{LearnSidebar}}</div>
<p class="summary">この記事では、フレームワークを使用せずに、Node.jsだけで構築された単純な静的ファイルサーバを紹介します。</p>
<p><a href="https://nodejs.org/en/">Node.js</a>用に、サーバを稼働させるのに役立つ多くのフレームワークがあります。</p>
<p>最も人気があるのは、次のようなものです:</p>
<ul>
<li><a href="http://expressjs.com/">Express</a>: 広く使われているフレームワーク</li>
<li><a href="https://hapijs.com/">Hapi.js</a>: アプリケーションとサービスを構築するための豊富なフレームワーク</li>
<li><a href="https://www.totaljs.com/">Total</a>: 他のフレームワークやモジュールに依存しない、オールインワンのNode.jsフレームワーク。</li>
</ul>
<p>これらは、どんな状況にも適しているというわけではありません。開発者は既存のフレームワークに依存することなく、独自のサーバを構築する必要があることもあるでしょう。</p>
<h2 id="静的ファイルサーバーの例">静的ファイルサーバーの例</h2>
<p>Node.jsで構築された、簡単な静的ファイルサーバの例を以下に示します。</p>
<pre class="brush: js line-numbers language-js">var http = require('http');
var fs = require('fs');
var path = require('path');
http.createServer(function (request, response) {
console.log('request ', request.url);
var filePath = '.' + request.url;
if (filePath == './') {
filePath = './index.html';
}
var extname = String(path.extname(filePath)).toLowerCase();
var mimeTypes = {
'.html': 'text/html',
'.js': 'text/javascript',
'.css': 'text/css',
'.json': 'application/json',
'.png': 'image/png',
'.jpg': 'image/jpg',
'.gif': 'image/gif',
'.svg': 'image/svg+xml',
'.wav': 'audio/wav',
'.mp4': 'video/mp4',
'.woff': 'application/font-woff',
'.ttf': 'application/font-ttf',
'.eot': 'application/vnd.ms-fontobject',
'.otf': 'application/font-otf',
'.wasm': 'application/wasm'
};
var contentType = mimeTypes[extname] || 'application/octet-stream';
fs.readFile(filePath, function(error, content) {
if (error) {
if(error.code == 'ENOENT') {
fs.readFile('./404.html', function(error, content) {
response.writeHead(404, { 'Content-Type': 'text/html' });
response.end(content, 'utf-8');
});
}
else {
response.writeHead(500);
response.end('Sorry, check with the site admin for error: '+error.code+' ..\n');
}
}
else {
response.writeHead(200, { 'Content-Type': contentType });
response.end(content, 'utf-8');
}
});
}).listen(8125);
console.log('Server running at http://127.0.0.1:8125/');</pre>
<h3 id="各部の説明">各部の説明</h3>
<p>第1行から第3行までは、Node.jsが提供するモジュールを組み込みます。おおむね「インポート」に似たような手続きです。</p>
<pre class="brush: js language-js">var http = require('http');
var fs = require('fs');
var path = require('path');
</pre>
<p>次にある関数で、サーバーを生成します。 <code>https.createServer</code>は、サーバーオブジェクトを返しますが、下の例ではポート8125で要求の受付を開始します。</p>
<pre class="brush: js language-js">http.createServer(function (request, response) {
...
}).listen(8125);
console.log('Server running at http://127.0.0.1:8125/');
</pre>
<p>次の4行では、要求があったURLから、ファイルへのパスを決定します。ファイル名が明示されていないときは、デフォルト名を使うようにします。</p>
<pre class="brush: js">console.log('request ', request.url);
var filePath = '.' + request.url;
if (filePath == './') {
filePath = './index.html';
}
</pre>
<p>例えば、<code>example.org</code>というURLを要求されたときは、<code>example.org/index.html</code>.のことだと解釈します。</p>
<p>次に、要求されたファイルの拡張子を調べ、以下に定義する<a href="/ja/docs/Web/HTTP/Basics_of_HTTP/MIME_types">MIMEタイプ</a>のどれかと一致したら、そのタイプを使います。一致しない場合には、デフォルトのタイプ<code>application/octet-stream</code>を使うようにします。.</p>
<pre class="brush: js">var extname = String(path.extname(filePath)).toLowerCase();
var mimeTypes = {
'.html': 'text/html',
'.js': 'text/javascript',
'.css': 'text/css',
'.json': 'application/json',
'.png': 'image/png',
'.jpg': 'image/jpg',
'.gif': 'image/gif',
'.svg': 'image/svg+xml',
'.wav': 'audio/wav',
'.mp4': 'video/mp4',
'.woff': 'application/font-woff',
'.ttf': 'application/font-ttf',
'.eot': 'application/vnd.ms-fontobject',
'.otf': 'application/font-otf',
'.wasm': 'application/wasm'
};
var contentType = mimeTypes[extname] || 'application/octet-stream';
</pre>
<p>最後に、ファイルの情報をクライアントに返送します。この関数では、あらかじめ用意してあった<code>filePath</code>変数を使ってファイルを読み込みます。</p>
<pre class="brush: js">fs.readFile(filePath, function(error, content) {
...
});
</pre>
<p>関数のなかで最初にやることは、起こりうるエラーへの対応です。</p>
<pre class="brush: js">if (error) {
..
} else {
..
}
</pre>
<p>一番多いのは、存在しないファイルを要求された場合(<code>ENOENT</code>)で、エラーコード404に対応するページを返してやります。</p>
<pre class="brush: js">if(error.code == 'ENOENT') {
fs.readFile('./404.html', function(error, content) {
response.writeHead(404, { 'Content-Type': 'text/html' });
response.end(content, 'utf-8');
});
}
else {
response.writeHead(500);
response.end('Sorry, check with the site admin for error: '+error.code+' ..\n');
}</pre>
<p>何もエラーが検出されなかったら、MIME型をヘッダーに付けて、要求されたファイルを返してやります。</p>
<pre class="brush: js">response.writeHead(200, { 'Content-Type': contentType });
response.end(content, 'utf-8');</pre>
<h2 id="拡張の検討">拡張の検討</h2>
<p>静的なファイルの返送機能だけでなく、要求の度にページを動的に生成する機能を付け加えることを考えてみてください。</p>
|