[λ Έλ 2] 4μ₯. http λͺ¨λλ‘ μλ² λ§λ€κΈ°
π4μ₯ ν€μλπ
http λͺ¨λ
header, body
REST
μΏ ν€, μΈμ
http2
ν΄λ¬μ€ν°
μ€μ λ‘ λμκ°λ μλ²λ₯Ό λ§λ€κ³ , μλ² λμμ νμν μΏ ν€μ μΈμ μ²λ¦¬λ₯Ό μ΄ν΄λ³΄κ³ μμ² μ£Όμ λΌμ°ν λ°©λ²μ λ°°μΈ κ²μ λλ€.
4.1 μμ²κ³Ό μλ΅ μ΄ν΄νκΈ°
const http = require('http');
http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
res.write('<h1>Hello Node!</h1>');
res.end('<p>Hello Server!</p>');
})
.listen(8080, () => { // μλ² μ°κ²°
console.log('8080λ² ν¬νΈμμ μλ² λκΈ° μ€μ
λλ€!');
});
- http λͺ¨λ μ¬μ©
- createServer λ©μλ
- μΈμλ‘ μμ²μ λν μ½λ°± ν¨μλ₯Ό μ¬μ©ν μ μμ΅λλ€.
- μ½λ°± ν¨μμλ μλ΅μ λ£μ΅λλ€. (μμ²μ΄ λ€μ΄μ¬ λλ§λ€ μ€ν)
- listen λ©μλ
- 곡κ°ν ν¬νΈ λ²νΈλ₯Ό λ£μ΅λλ€.
- ν¬νΈ μ°κ²° μλ£ ν μ€νλ μ½λ°± ν¨μλ₯Ό λ£μ΅λλ€.
- res κ°μ²΄
- writeHead : μλ΅μ λν μ 보 κΈ°λ‘νλ λ©μλ
β 200, HTML, utf-8 ⇒ ν€λ(header)μ κΈ°λ‘λ©λλ€. - write : ν΄λΌμ΄μΈνΈλ‘ λ³΄λΌ λ°μ΄ν°
β λ¬Έμμ΄, λ²νΌ ⇒ λ³Έλ¬Έ(body)μ κΈ°λ‘λ©λλ€. - end : μλ΅ μ’
λ£ λ©μλ
β μΈμκ° μλ€λ©΄ ν΄λΌμ΄μΈνΈλ‘ 보λ΄κ³ μλ΅μ μ’ λ£ν©λλ€.
- writeHead : μλ΅μ λν μ 보 κΈ°λ‘νλ λ©μλ
- createServer λ©μλ
π localhost
localhostλ νμ¬ μ»΄ν¨ν°μ λ΄λΆ μ£Όμμ΄λ©°, μμ μ μ»΄ν¨ν°μμλ§ μ κ·Όν μ μμ΅λλ€. 127.0.0.1μ μ£Όμλ‘ μ¬μ©ν΄λ κ°μ΅λλ€.
π ν¬νΈ
μλ² λ΄μμ νλ‘μΈμ€λ₯Ό ꡬλΆνλ λ²νΈμ΄λ©°, 80λ² ν¬νΈλ₯Ό μ¬μ©νλ©΄ μ£Όμμμ ν¬νΈλ₯Ό μλ΅ν μ μμ΅λλ€.
π HTML νμΌ fs λͺ¨λλ‘ μ½μ΄μ μ μ‘
const http = require('http');
const fs = require('fs').promises;
http.createServer(async (req, res) => { // μμ²μ΄ λ€μ΄μ€λ©΄
try {
const data = await fs.readFile('./server2.html'); // fs λͺ¨λλ‘ HTML νμΌμ μ½λλ€
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
res.end(data);
} catch (err) {
console.error(err);
res.writeHead(500, { 'Content-Type': 'text/plain; charset=utf-8' });
res.end(err.message);
}
})
.listen(8081, () => {
console.log('8081λ² ν¬νΈμμ μλ² λκΈ° μ€μ
λλ€!');
});
4.2 RESTμ λΌμ°ν μ¬μ©νκΈ°
π REST(REpresentational State Transfer)
- μλ²μ μμμ μ μνκ³ μμμ λν μ£Όμλ₯Ό μ§μ νλ λ°©λ²μ λ§ν©λλ€.
- HTTP μμ² λ©μλλ₯Ό μ¬μ©ν©λλ€.
HTTP μμ² λ©μλ | λμ |
GET | μλ² μμμ κ°μ Έμ€κ³ μ ν λ μ¬μ© λ³Έλ¬Έμ λ°μ΄ν°λ₯Ό λ£μ§ μμ λ°μ΄ν°λ₯Ό μλ²λ‘ λ³΄λΌ λ 쿼리μ€νΈλ§ μ¬μ© |
POST | μλ²μ μμμ μλ‘ λ±λ‘νκ³ μ ν λ μ¬μ© μμ²μ λ³Έλ¬Έ(body)μ μλ‘ λ±λ‘ν λ°μ΄ν°λ₯Ό λ£μ΄ 보λ |
PUT | μλ²μ μμμ μμ²μ λ€μ΄ μλ μμμΌλ‘ μΉν μμ²μ λ³Έλ¬Έ(body)μ μΉνν λ°μ΄ν°λ₯Ό λ£μ΄ 보λ |
PATCH | μλ² μμμ μΌλΆλ§ μμ νκ³ μ ν λ μ¬μ© μμ²μ λ³Έλ¬Έμ μΌλΆ μμ ν λ°μ΄ν°λ₯Ό λ£μ΄ 보λ |
DELETE | μλ²μ μμμ μμ ν λ μ¬μ© |
OPTIONS | μμ²μ νκΈ° μ μ ν΅μ μ΅μ μ μ€λͺ νκΈ° μν΄ μ¬μ© |
- μ£Όμ νλλ μμ² λ©μλλ₯Ό μ¬λ¬ κ° κ°μ§ μ μμ΅λλ€.
π/user μ£Όμλ‘ GET λ©μλ(μ¬μ©μ μ 보 κ°μ Έμ€κΈ°), POST λ©μλ(μ¬μ©μ λ±λ‘νκΈ°) - μ£Όμμ λ©μλλ§ λ³΄κ³ μμ²μ λ΄μ©μ μμλ³Ό μ μλ€λ μ₯μ μ΄ μμ΅λλ€.
- GET λ©μλλ λΈλΌμ°μ μμ μΊμ±(κΈ°μ΅)ν μλ μμ΄ GET μμ² λ μΊμμμ κ°μ Έμ¬ μ μμ΅λλ€.
- ν΄λΌμ΄μΈνΈκ° λꡬλ μκ΄μμ΄ κ°μ λ°©μμΌλ‘ μλ²μ μν΅ν©λλ€. (iOS, μλλ‘μ΄λ, μΉ λ±)
const http = require('http');
const fs = require('fs').promises;
const path = require('path');
const users = {}; // λ°μ΄ν° μ μ₯μ©
http.createServer(async (req, res) => { // HTTP μμ² λ©μλ ꡬλΆ
try {
if (req.method === 'GET') { // λ€μ ꡬλΆ
if (req.url === '/') {
const data = await fs.readFile(path.join(__dirname, 'restFront.html'));
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
return res.end(data);
} else if (req.url === '/about') {
const data = await fs.readFile(path.join(__dirname, 'about.html'));
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
return res.end(data);
} else if (req.url === '/users') {
res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });
return res.end(JSON.stringify(users));
}
// /λ /aboutλ /usersλ μλλ©΄
try {
const data = await fs.readFile(path.join(__dirname, req.url));
return res.end(data);
} catch (err) {
// μ£Όμμ ν΄λΉνλ λΌμ°νΈλ₯Ό λͺ» μ°Ύμλ€λ 404 Not Found error λ°μ
}
} else if (req.method === 'POST') {
if (req.url === '/user') {
let body = '';
// μμ²μ bodyλ₯Ό stream νμμΌλ‘ λ°μ
req.on('data', (data) => {
body += data;
});
// μμ²μ bodyλ₯Ό λ€ λ°μ ν μ€νλ¨
return req.on('end', () => {
console.log('POST λ³Έλ¬Έ(Body):', body);
const { name } = JSON.parse(body);
const id = Date.now();
users[id] = name;
res.writeHead(201, { 'Content-Type': 'text/plain; charset=utf-8' });
res.end('λ±λ‘ μ±κ³΅');
});
}
} else if (req.method === 'PUT') {
if (req.url.startsWith('/user/')) {
const key = req.url.split('/')[2];
let body = '';
req.on('data', (data) => {
body += data;
});
return req.on('end', () => {
console.log('PUT λ³Έλ¬Έ(Body):', body);
users[key] = JSON.parse(body).name;
res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });
return res.end(JSON.stringify(users));
});
}
} else if (req.method === 'DELETE') {
if (req.url.startsWith('/user/')) {
const key = req.url.split('/')[2];
delete users[key];
res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });
return res.end(JSON.stringify(users));
}
}
res.writeHead(404);
return res.end('NOT FOUND');
} catch (err) {
console.error(err);
res.writeHead(500, { 'Content-Type': 'text/plain; charset=utf-8' });
res.end(err.message);
}
})
.listen(8082, () => {
console.log('8082λ² ν¬νΈμμ μλ² λκΈ° μ€μ
λλ€');
});
4.3 μΏ ν€μ μΈμ μ΄ν΄νκΈ°
πͺ μΏ ν€
- ν΄λΌμ΄μΈνΈκ° λꡬμΈμ§ μλ³νκΈ° μν΄ μλ²κ° μμ²μ λν μλ΅μ ν λ 보λ΄λ κ²μ λλ€.
- μ ν¨κΈ°κ°μ΄ μμ΅λλ€.
- ν€-κ°μ μμΌλ‘ μ΄λ£¨μ΄μ Έ μμ΅λλ€.
- μΉ λΈλΌμ°μ λ μΏ ν€λ₯Ό μ μ₯ν΄ λλ€κ° λ€μμ μμ²ν λλ§λ€ μΏ ν€λ₯Ό λλ΄ν΄μ 보λ λλ€.
- μμ²μ ν€λ(Cookie)μ λ΄κ²¨ μ μ‘λ©λλ€.
- λΈλΌμ°μ λ μλ΅μ ν€λ(Set-Cookie)μ λ°λΌ μΏ ν€λ₯Ό μ μ₯ν©λλ€.
const http = require('http');
http.createServer((req, res) => { // req κ°μ²΄μ λ΄κ²¨ μλ μΏ ν€λ₯Ό κ°μ Έμ΄
console.log(req.url, req.headers.cookie); // μΏ ν€κ° λ€μ΄μλ μμΉ
res.writeHead(200, { 'Set-Cookie': 'mycookie=test' }); // μλ΅μ ν€λμ μΏ ν€λ₯Ό κΈ°λ‘
res.end('Hello Cookie');
})
.listen(8083, () => {
console.log('8083λ² ν¬νΈμμ μλ² λκΈ° μ€μ
λλ€!');
});
- favicon(νλΉμ½) : μΉ μ¬μ΄νΈ νμ 보μ΄λ μ΄λ―Έμ§
π / undefinded, /favicon.ico mycookie=test λ κ°κ° κΈ°λ‘λ μ΄μ
첫 λ²μ§Έ μμ²(/)μ 보λ΄κΈ° μ μλ λΈλΌμ°μ κ° μ΄λ ν μΏ ν€ μ 보λ κ°κ³ μμ§ μμ undefinedκ° κΈ°λ‘λμμ΅λλ€.
λΈλΌμ°μ λ HTMLμμ νλΉμ½μ΄ λμ§ μ μΆν μ μμΌλ©΄ μλ²μ νλΉμ½ μ 보μ λν μμ²μ 보λ λλ€.
λ λ²μ§Έ μμ²(/favicon.ico)μ ν€λμ μΏ ν€κ° λ€μ΄ μμμ νμΈν μ μμ΅λλ€.
μΏ ν€λ‘ μ¬μ©μ μλ³
const http = require('http');
const fs = require('fs').promises;
const path = require('path');
const parseCookies = (cookie = '') => // μΏ ν€ λ¬Έμμ΄μ μ½κ² μ¬μ©νκΈ° μν΄ μλ°μ€ν¬λ¦½νΈ κ°μ²΄ νμμΌλ‘ λ³κ²½
cookie
.split(';')
.map(v => v.split('='))
.reduce((acc, [k, v]) => {
acc[k.trim()] = decodeURIComponent(v);
return acc;
}, {});
// GET /login μ²λ¦¬ λΆλΆ
http.createServer(async (req, res) => {
const cookies = parseCookies(req.headers.cookie); // { mycookie: 'test' }
// μ£Όμκ° /loginμΌλ‘ μμνλ κ²½μ°
if (req.url.startsWith('/login')) {
const url = new URL(req.url, '<http://localhost:8084>');
const name = url.searchParams.get('name'); // nameμ΄λΌλ Paramsκ° μλμ§ μ°Ύκ³ nameμ λ£λλ€.
const expires = new Date();
// μΏ ν€ μ ν¨ μκ°μ νμ¬μκ° + 5λΆμΌλ‘ μ€μ
expires.setMinutes(expires.getMinutes() + 5);
res.writeHead(302, { // 302 μλ΅μ½λ, 리λ€μ΄λ νΈ μ£Όμμ μΏ ν€λ₯Ό ν€λμ λ£λλ€.
Location: '/',
'Set-Cookie': `name=${encodeURIComponent(name)}; Expires=${expires.toGMTString()}; HttpOnly; Path=/`,
});
res.end();
// nameμ΄λΌλ μΏ ν€κ° μλ κ²½μ°
} else if (cookies.name) {
res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });
res.end(`${cookies.name}λ μλ
νμΈμ`);
} else { // μΏ ν€κ° μλ€.
try {
const data = await fs.readFile(path.join(__dirname, 'cookie2.html'));
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
res.end(data);
} catch (err) {
res.writeHead(500, { 'Content-Type': 'text/plain; charset=utf-8' });
res.end(err.message);
}
}
})
.listen(8084, () => {
console.log('8084λ² ν¬νΈμμ μλ² λκΈ° μ€μ
λλ€!');
});
μΏ ν€μλ νκΈκ³Ό μ€ λ°κΏμ λ£μ μ μμΌλ©°, νκΈμ encodeURIComponentλ‘ κ°μΈμ λ£μ΅λλ€.
λ‘κ·ΈμΈ νμ΄μ§λ‘ μ μνμ§ μμ κ²½μ°, λ¨Όμ μΏ ν€κ° μλμ§ μλμ§ νμΈν©λλ€. μΏ ν€κ° μλ€λ©΄ λ‘κ·ΈμΈν μ μλ νμ΄μ§λ₯Ό 보λ΄κ³ , μλ€λ©΄ λ‘κ·ΈμΈν μνλ‘ κ°μ£Όν΄ μΈμ¬λ§μ 보λ λλ€.
κ·Έλ¬λ μ΄ λ°©μμ μΏ ν€κ° λ ΈμΆλμ΄ μμΌλ©° μ‘°μλ μνμ΄ μμ΅λλ€.
sessionμ μ¬μ©ν΄ μλ²κ° μ¬μ©μ μ 보λ₯Ό κ΄λ¦¬νλλ‘ ν©μλ€.
const http = require('http');
const fs = require('fs').promises;
const path = require('path');
const parseCookies = (cookie = '') =>
cookie
.split(';')
.map(v => v.split('='))
.reduce((acc, [k, v]) => {
acc[k.trim()] = decodeURIComponent(v);
return acc;
}, {});
const session = {};
http.createServer(async (req, res) => {
const cookies = parseCookies(req.headers.cookie);
if (req.url.startsWith('/login')) {
const url = new URL(req.url, '<http://localhost:8085>');
const name = url.searchParams.get('name');
const expires = new Date();
expires.setMinutes(expires.getMinutes() + 5);
const uniqueInt = Date.now();
session[uniqueInt] = {
name,
expires,
};
res.writeHead(302, {
Location: '/',
'Set-Cookie': `session=${uniqueInt}; Expires=${expires.toGMTString()}; HttpOnly; Path=/`,
});
res.end();
// μΈμ
μΏ ν€κ° μ‘΄μ¬νκ³ , λ§λ£ κΈ°κ°μ΄ μ§λμ§ μμλ€λ©΄
} else if (cookies.session && session[cookies.session].expires > new Date()) {
res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });
res.end(`${session[cookies.session].name}λ μλ
νμΈμ`);
} else {
try {
const data = await fs.readFile(path.join(__dirname, 'cookie2.html'));
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
res.end(data);
} catch (err) {
res.writeHead(500, { 'Content-Type': 'text/plain; charset=utf-8' });
res.end(err.message);
}
}
})
.listen(8085, () => {
console.log('8085λ² ν¬νΈμμ μλ² λκΈ° μ€μ
λλ€!');
});
- μΏ ν€μ μ΄λ¦μ λ΄λ κ² λμ uniqueInt μ«μ κ°μ μ¬μ©ν©λλ€.
- μλ²μ μ¬μ©μ μ 보λ₯Ό μ μ₯νκ³ , ν΄λΌμ΄μΈνΈμλ μΈμ μμ΄λλ‘ μν΅ν©λλ€.
- μλ²λ μΈμ μ λ λμ€λ λ©€μΊμλ κ°μ λ°μ΄ν°λ² μ΄μ€μ λ£μ΅λλ€.
4.4 httpsμ http2
π https λͺ¨λ
μΉ μλ²μ SSL μνΈνλ₯Ό μΆκ°νμ¬ λ³΄μμ κ°νν©λλ€.
μΈμ¦ν΄ μ£Όλ κΈ°κ΄μμ ꡬμ ν΄μΌ ν©λλ€.
const https = require('https');
const fs = require('fs');
https.createServer({
cert: fs.readFileSync('λλ©μΈ μΈμ¦μ κ²½λ‘'),
key: fs.readFileSync('λλ©μΈ λΉλ°ν€ κ²½λ‘'),
ca: [
fs.readFileSync('μμ μΈμ¦μ κ²½λ‘'),
fs.readFileSync('μμ μΈμ¦μ κ²½λ‘'),
],
}, (req, res) => {
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
res.write('<h1>Hello Node!</h1>');
res.end('<p>Hello Server!</p>');
})
.listen(443, () => {
console.log('443λ² ν¬νΈμμ μλ² λκΈ° μ€μ
λλ€!');
});
- 첫 λ²μ§Έ μΈμ : μΈμ¦μμ κ΄λ ¨λ μ΅μ
κ°μ²΄λ€
μΈμ¦μλ₯Ό ꡬμ νμ¬ λ°μ νμΌλ€μ fs.readFileSync λ©μλλ‘ μ½μ΄μ cert, key, ca μ΅μ μ μλ§κ² λ£μΌλ©΄ λ©λλ€.
π http2 λͺ¨λ
λ Έλμ http2 λͺ¨λμ SSL μνΈνμ λλΆμ΄ μ΅μ HTTP νλ‘ν μ½μΈ http/2λ₯Ό μ¬μ©ν μ μκ² ν©λλ€.
http/2λ μμ² λ° μλ΅ λ°©μμ΄ κΈ°μ‘΄ http/1.1λ³΄λ€ κ°μ λμ΄ ν¨μ¬ ν¨μ¨μ μΌλ‘ μμ²μ 보λ λλ€.
4.5 cluster
π cluster (ν΄λ¬μ€ν°)
β cluster λͺ¨λμ μ±κΈ νλ‘μΈμ€λ‘ λμνλ λ Έλκ° CPU μ½μ΄λ₯Ό λͺ¨λ μ¬μ©ν μ μκ² ν΄μ£Όλ λͺ¨λμ λλ€.
β μ½μ΄ νλλΉ νλ‘μΈμ€ νλκ° λμκ°κ² νμ¬, μ½μ΄λ₯Ό νλλ§ μ¬μ©ν λμ λΉν΄ μ±λ₯μ΄ κ°μ λ©λλ€.
β λ©λͺ¨λ¦¬λ₯Ό 곡μ νμ§ λͺ»νλ λ¨μ μ΄ μμ΅λλ€.
const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;
if (cluster.isMaster) {
console.log(`λ§μ€ν° νλ‘μΈμ€ μμ΄λ: ${process.pid}`);
// CPU κ°μλ§νΌ μ컀λ₯Ό μμ°
for (let i = 0; i < numCPUs; i += 1) {
cluster.fork();
}
// μμ»€κ° μ’
λ£λμμ λ
cluster.on('exit', (worker, code, signal) => {
console.log(`${worker.process.pid}λ² μμ»€κ° μ’
λ£λμμ΅λλ€.`);
console.log('code', code, 'signal', signal);
cluster.fork();
});
} else {
// μ컀λ€μ΄ ν¬νΈμμ λκΈ°
http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
res.write('<h1>Hello Node!</h1>');
res.end('<p>Hello Cluster!</p>');
setTimeout(() => { // μ컀 μ‘΄μ¬λ₯Ό νμΈνκΈ° μν΄ 1μ΄λ§λ€ κ°μ μ’
λ£
process.exit(1);
}, 1000);
}).listen(8086);
console.log(`${process.pid}λ² μ컀 μ€ν`);
}
ν΄λ¬μ€ν°μλ λ§μ€ν° νλ‘μΈμ€μ μ컀 νλ‘μΈμ€κ° μμ΅λλ€.
λ§μ€ν° νλ‘μΈμ€λ CPU κ°μλ§νΌ μ컀 νλ‘μΈμ€λ₯Ό λ§λ€κ³ , 8086λ² ν¬νΈμμ λκΈ°ν©λλ€.
μμ²μ΄ λ€μ΄μ€λ©΄ λ§λ€μ΄μ§ μ컀 νλ‘μΈμ€μ μμ²μ λΆλ°°ν©λλ€.
λΉμΉΈ μ±μ°κΈ° λ¬Έμ (λΉμΉΈμ λλκ·Έν΄μ μ λ΅μ λ§ν 보μΈμ!)
1. http λͺ¨λμ (createServer) λ©μλλ μΈμλ‘ μμ²μ λν μ½λ°±ν¨μλ₯Ό λ£μ μ μμΌλ©°, μμ²μ΄ λ€μ΄μ¬ λλ§λ€ λ§€λ² μ½λ°± ν¨μλ₯Ό μ€νν©λλ€.
2. μλ΅μ λν μ λ³΄κ° κΈ°λ‘λλ λΆλΆμ (ν€λ)λΌκ³ ν©λλ€. (ν€λ)μλ 200, μ½ν μΈ νμ, charset λ±μ΄ ν¬ν¨λ μ λ³΄κ° μμ΅λλ€.
3. ν΄λΌμ΄μΈνΈλ‘ λ³΄λΌ λ°μ΄ν°κ° κΈ°λ‘λλ λΆλΆμ (λ³Έλ¬Έ(body))μ΄λΌκ³ ν©λλ€. λ¬Έμμ΄, λ²νΌ λ±μ λ³΄λΌ μ μμ΅λλ€.
4. (REST)λ μλ²μ μμμ μ μνκ³ μμμ λν μ£Όμλ₯Ό μ§μ νλ λ°©λ²μ κ°λ¦¬ν΅λλ€.
5. μ£Όμ νλλ μμ² λ©μλλ₯Ό νλλ§ κ°μ§ μ μμ΅λλ€. (O/X)
μ λ΅ : O
6. (μΏ ν€)λ ν΄λΌμ΄μΈνΈκ° λꡬμΈμ§ μλ³νκΈ° μν΄ μλ²κ° μμ²μ λν μλ΅μ ν λ 보λ΄λ κ²μ λλ€.
7. (cluster) λͺ¨λμ μ±κΈ νλ‘μΈμ€λ‘ λμνλ λ Έλκ° CPU μ½μ΄λ₯Ό λͺ¨λ μ¬μ©ν μ μκ² ν΄μ£Όλ λͺ¨λμ λλ€.
μ½λ λ¬Έμ
1. λΉμΉΈμ λ€μ΄κ° μ½λλ₯Ό μμ±ν΄ 보μΈμ.
const http = require('http');
http.createServer((req, res) => {
res.{1λ² λΉμΉΈ}(200, { 'Content-Type': 'text/html; charset=utf-8' });
res.{2λ² λΉμΉΈ}('<h1>Hello Node!</h1>');
res.{3λ² λΉμΉΈ}('<p>Hello Server!</p>');
})
.listen(8080, () => { // μλ² μ°κ²°
console.log('8080λ² ν¬νΈμμ μλ² λκΈ° μ€μ
λλ€!');
});
μ λ΅ : writeHead, write, end
2. λΉμΉΈμ λ€μ΄κ° μ½λλ₯Ό μμ±ν΄ 보μΈμ.
const http = require('http');
const fs = require('fs').promises;
const path = require('path');
const parseCookies = (cookie = '') =>
cookie
.split(';')
.map(v => v.split('='))
.reduce((acc, [k, v]) => {
acc[k.trim()] = decodeURIComponent(v);
return acc;
}, {});
const session = {};
http.createServer(async (req, res) => {
const cookies = parseCookies(req.{1λ² λΉμΉΈ});
if (req.url.startsWith('/login')) {
const url = new URL(req.url, '<http://localhost:8085>');
const name = url.searchParams.get('name');
const expires = new Date();
expires.setMinutes(expires.getMinutes() + 5);
const uniqueInt = Date.now();
session[uniqueInt] = {
name,
expires,
};
res.writeHead(302, {
Location: '/',
'Set-Cookie': `session=${{2λ² λΉμΉΈ}}; Expires=${expires.toGMTString()}; HttpOnly; Path=/`,
});
res.end();
... μλ΅
μ λ΅ : header.cookie, uniqueInt