node.jsによるサーバの基本構造

# プログラム例
node.js演習用のプログラム例をいくつか覚えとして、掲載しておきます。

## 最も基本的なサーバプログラム
リクエストがあれば、単にコンテンツを返す例。
アロー関数とコールバック関数という概念に慣れてもらうことが必要です。

```javascript
const http = require('http');

const server = http.createServer((req, res) => {
    res.writeHead(200, { 'Content-Type': 'text/plain' });
    res.end('Hello, World!');
});

const PORT = 3000;
server.listen(PORT, () => {
    console.log(`Server running at http://localhost:${PORT}/`);
});
```


## POSTメソッドの確認
POSTメソッドを確認するためのnode.jsプログラム。

```javascript
const http = require('http');

const server = http.createServer((req, res) => {
    // CORSヘッダーを設定
    res.setHeader('Access-Control-Allow-Origin', '*');
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
    res.setHeader('Access-Control-Allow-Headers', 'Content-Type');

    if (req.method === 'OPTIONS') {
        // プリフライトリクエストに対応
        res.writeHead(204);
        res.end();
        return;
    }

    if (req.method === 'POST' && req.url === '/submit') {
        let body = '';

        req.on('data', chunk => {
            body += chunk.toString();
        });

        req.on('end', () => {
            try {
                const data = JSON.parse(body);
                // サーバー側での処理
                console.log('Received JSON:', data);

                // ここにサーバー側で行いたい処理を追加
                const responseMessage = {
                    message: `Hello, ${data.name}! Your age is ${data.age}.`
                };

                res.writeHead(200, { 'Content-Type': 'application/json' });
                res.end(JSON.stringify(responseMessage));
            } catch (error) {
                res.writeHead(400, { 'Content-Type': 'text/plain' });
                res.end('Invalid JSON');
            }
        });
    } else {
        res.writeHead(404, { 'Content-Type': 'text/plain' });
        res.end('404 Not Found');
    }
});

const PORT = 3000;
server.listen(PORT, () => {
    console.log(`Server running at http://localhost:${PORT}/`);
});
```
以上のnode.jsプログラムにアクセスをかけるためのhtmlファイル。
それとは別に、

```bash
curl -v -H "Content-Type: application/json" -d "{\"name\": \"Taro\", \"age\": 30}" http://127.0.0.1:3000/submit
```
として、curlでのPOSTメソッドアクセスを確認しておくと良いです。


```html
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Submit Form</title>
</head>

<body>
    <h1>Submit Your Information</h1>
    <form id="submitForm">
        <label for="name">Name:</label>
        <input type="text" id="name" name="name" required><br><br>
        <label for="age">Age:</label>
        <input type="number" id="age" name="age" required><br><br>
        <button type="submit">Submit</button>
    </form>

    <script>
        document.getElementById('submitForm').addEventListener('submit', function (event) {
            event.preventDefault();

            const name = document.getElementById('name').value;
            const age = document.getElementById('age').value;

            const data = {
                name: name,
                age: age
            };

            fetch('http://127.0.0.1:3000/submit', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify(data)
            })
                .then(response => response.json())
                .then(data => {
                    console.log('Success:', data);
                    alert(`Server Response: ${data.message}`);
                })
                .catch((error) => {
                    console.error('Error:', error);
                });
        });
    </script>
</body>

</html>
```

## コンテンツルーティングの例
コンテンツに対するルーティングの例。
/formを指定すると、HTMLの本体にformを埋め込みます。
また、POSTメソッドに対しての応答も同一プログラム内に入れています。


```javascript
const http = require('http');
const url = require('url');
const querystring = require('querystring');

const renderTemplate = (title, content) => {
    return `
        <!DOCTYPE html>
        <html>
        <head>
            <title>${title}</title>
        </head>
        <body>
            <h1>${title}</h1>
            ${content}
        </body>
        </html>
    `;
};

const server = http.createServer((req, res) => {
    const parsedUrl = url.parse(req.url, true);
    const pathname = parsedUrl.pathname;

    if (req.method === 'GET') {
        switch (pathname) {
            case '/':
                res.writeHead(200, { 'Content-Type': 'text/html' });
                res.end(renderTemplate('Home Page', 'This is the content of the home page.'));
                break;
            case '/about':
                res.writeHead(200, { 'Content-Type': 'text/html' });
                res.end(renderTemplate('About Us', 'This page contains information about us.'));
                break;
            case '/form':
                const form = `
                    <form action="/form" method="post">
                        <label for="name">Name:</label><br>
                        <input type="text" id="name" name="name"><br>
                        <label for="message">Message:</label><br>
                        <textarea id="message" name="message"></textarea><br>
                        <input type="submit" value="Submit">
                    </form>
                `;
                res.writeHead(200, { 'Content-Type': 'text/html' });
                res.end(renderTemplate('Contact Form', form));
                break;
            default:
                res.writeHead(404, { 'Content-Type': 'text/html' });
                res.end(renderTemplate('404 Not Found', 'The page you are looking for does not exist.'));
        }
    } else if (req.method === 'POST' && pathname === '/form') {
        let body = '';
        req.on('data', chunk => {
            body += chunk.toString();
        });
        req.on('end', () => {
            const postData = querystring.parse(body);
            const responseContent = `
                <p>Thank you for your message, ${postData.name}.</p>
                <p>Your message: ${postData.message}</p>
            `;
            res.writeHead(200, { 'Content-Type': 'text/html' });
            res.end(renderTemplate('Contact Form - Received', responseContent));
        });
    } else {
        res.writeHead(404, { 'Content-Type': 'text/html' });
        res.end(renderTemplate('404 Not Found', 'The page you are looking for does not exist.'));
    }
});

const PORT = 3000;
server.listen(PORT, () => {
    console.log(`Server running at http://localhost:${PORT}/`);
});
```


## httpとhttps比較用

curl -v -kで両者のアクセスを比較しましょう。
TCPからHTTPに向けてのレイヤーで何が起こっているか確認すると良いと思います。

```javascript
const http = require('http');
const https = require('https');
const fs = require('fs');

// HTTP Server
const httpServer = http.createServer((req, res) => {
    res.writeHead(200, { 'Content-Type': 'text/plain' });
    res.end('Hello from HTTP!');
});

// HTTPS Server
const httpsOptions = {
    key: fs.readFileSync('my0627server.key'),
    cert: fs.readFileSync('my0627server.cert')
};

const httpsServer = https.createServer(httpsOptions, (req, res) => {
    res.writeHead(200, { 'Content-Type': 'text/plain' });
    res.end('Hello from HTTPS!');
});

// Start both servers
const HTTP_PORT = 3000;
const HTTPS_PORT = 3001;

httpServer.listen(HTTP_PORT, () => {
    console.log(`HTTP Server running at http://localhost:${HTTP_PORT}/`);
});

httpsServer.listen(HTTPS_PORT, () => {
    console.log(`HTTPS Server running at https://localhost:${HTTPS_PORT}/`);
});
```