C++98λ‘ κ΅¬νν HTTP/1.1 μΉ μλ² νλ‘μ νΈμ λλ€. Nginxμ μ μ¬ν μ€μ λ°©μμ μ¬μ©νλ©°, μ μ νμΌ μ 곡, CGI μ€ν, νμΌ μ λ‘λ λ± λ€μν κΈ°λ₯μ μ 곡ν©λλ€.
- HTTP/1.1 νλ‘ν μ½ μ§μ: νμ€ HTTP μμ²/μλ΅ μ²λ¦¬
- λ©ν° μλ² μ§μ: μ¬λ¬ ν¬νΈμμ λμμ κ°μ νΈμ€νΈ μ΄μ
- μ΄λ²€νΈ λλ¦¬λΈ μν€ν μ²: kqueueλ₯Ό μ¬μ©ν λΉλκΈ° I/O μ²λ¦¬
- HTTP λ©μλ μ§μ: GET, POST, PUT, DELETE, HEAD
- CGI μ§μ: λμ μ½ν μΈ μμ±μ μν CGI μ€ν¬λ¦½νΈ μ€ν
- νμΌ μ λ‘λ: POST/PUT λ©μλλ₯Ό ν΅ν νμΌ μ λ‘λ
- 리λ€μ΄λ μ : 301 리λ€μ΄λ νΈ μ§μ
- μλ μΈλ±μ±: λλ ν 리 λͺ©λ‘ μλ μμ±
- 컀μ€ν μλ¬ νμ΄μ§: HTTP μν μ½λλ³ λ§μΆ€ μλ¬ νμ΄μ§
- μμ² λ°λ ν¬κΈ° μ ν: Locationλ³ μ λ‘λ ν¬κΈ° μ ν μ€μ
webserv/
βββ config/
β βββ default.conf # κΈ°λ³Έ μλ² μ€μ νμΌ
βββ html/
β βββ error_pages/ # μλ¬ νμ΄μ§ ν
νλ¦Ώ
β βββ www/ # κΈ°λ³Έ μΉμ¬μ΄νΈ νμΌ
β βββ YoupiBanane/ # ν
μ€νΈ μ½ν
μΈ
βββ srcs/
β βββ Client.cpp/.hpp # ν΄λΌμ΄μΈνΈ μ°κ²° μ²λ¦¬
β βββ ClientManager.cpp/.hpp # λ€μ€ ν΄λΌμ΄μΈνΈ κ΄λ¦¬
β βββ Server.cpp/.hpp # μλ² μ€μ ν΄λμ€
β βββ ServerManager.cpp/.hpp # λ©ν° μλ² κ΄λ¦¬
β βββ Event.cpp/.hpp # Kqueue μ΄λ²€νΈ μ²λ¦¬
β βββ Location.cpp/.hpp # Location λΈλ‘ μ²λ¦¬
β βββ Config/
β β βββ ConfigParser.cpp/.hpp # μ€μ νμΌ νμ±
β β βββ ConfigFunctions.cpp # μ€μ ν¬νΌ ν¨μ
β βββ Message/
β β βββ Message.cpp/.hpp # HTTP λ©μμ§ κΈ°λ³Έ ν΄λμ€
β β βββ Request.cpp/.hpp # HTTP μμ² νμ±
β β βββ Response.cpp/.hpp # HTTP μλ΅ μμ±
β βββ Http/
β β βββ HttpRequestManager.cpp/.hpp # μμ² μ²λ¦¬ μ€μΌμ€νΈλ μ΄μ
β β βββ Handler/
β β βββ Handler.cpp/.hpp # νΈλ€λ¬ κΈ°λ³Έ ν΄λμ€
β β βββ StaticHandler.cpp/.hpp # μ μ νμΌ μλΉ
β β βββ DynamicHandler.cpp/.hpp # CGI μ²λ¦¬
β β βββ ErrorHandler.cpp/.hpp # μλ¬ μλ΅
β β βββ DeleteHandler.cpp/.hpp # DELETE μμ² μ²λ¦¬
β β βββ RedirectHandler.cpp/.hpp # 리λ€μ΄λ νΈ μ²λ¦¬
β β βββ HttpStatusCodes.cpp/.hpp # HTTP μν μ½λ
β βββ main.cpp # νλ‘κ·Έλ¨ μ§μ
μ
βββ tester/ # ν
μ€νΈ μ€ν¬λ¦½νΈ
βββ Makefile # λΉλ μ€μ
βββ README.md
- μ»΄νμΌλ¬: C++98 νμ€μ μ§μνλ C++ μ»΄νμΌλ¬
- μ΄μ체μ : BSD κ³μ΄ (macOS, FreeBSD λ±) - kqueue μ¬μ©
- λΉλ λꡬ: GNU Make
# νλ‘μ νΈ λΉλ
make
# ν΄λ¦° λΉλ
make re
# μ€λΈμ νΈ νμΌ μμ
make clean
# μ 체 μμ (μ€ν νμΌ ν¬ν¨)
make fcleanλΉλκ° μλ£λλ©΄ webserv μ€ν νμΌμ΄ μμ±λ©λλ€.
# κΈ°λ³Έ μ€μ νμΌ(config/default.conf) μ¬μ©
./webserv
# 컀μ€ν
μ€μ νμΌ μ¬μ©
./webserv path/to/config.conf# μΉ λΈλΌμ°μ μμ μ μ
http://localhost:80
# curlμ μ¬μ©ν ν
μ€νΈ
curl http://localhost:80
curl -X POST -d "data=test" http://localhost:80/post_test
curl -X DELETE http://localhost:80/soulee/test.htmlμ€μ νμΌμ Nginxμ μ μ¬ν λ¬Έλ²μ μ¬μ©ν©λλ€.
server {
listen 80; # 리μ€λ ν¬νΈ
server_name localhost; # μλ² μ΄λ¦
error_page 403 404 405 40x.html; # μλ¬ νμ΄μ§
upload_path uploaded_files; # μ
λ‘λ λλ ν 리
location / {
allow_method GET; # νμ© HTTP λ©μλ
root ./html/www; # λ¬Έμ 루νΈ
index index.html index.htm; # κΈ°λ³Έ μΈλ±μ€ νμΌ
autoindex on; # μλ μΈλ±μ± νμ±ν
}
}location /api {
allow_method GET POST DELETE; # λ€μ€ λ©μλ νμ©
root ./html/api;
index index.html;
autoindex on;
}
location /upload {
allow_method POST PUT;
root ./html/uploads;
client_max_body_size 1000; # μ΅λ λ°λ ν¬κΈ° (λ°μ΄νΈ)
}
location /redirect {
allow_method GET;
return 301 http://www.example.com; # 리λ€μ΄λ νΈ
}| μ§μμ΄ | μ€λͺ | μμ |
|---|---|---|
listen |
리μ€λ ν¬νΈ λ²νΈ | listen 80; |
server_name |
κ°μ νΈμ€νΈ μ΄λ¦ | server_name localhost; |
error_page |
컀μ€ν μλ¬ νμ΄μ§ | error_page 404 error.html; |
upload_path |
νμΌ μ λ‘λ κ²½λ‘ | upload_path uploads; |
allow_method |
νμ©ν HTTP λ©μλ | allow_method GET POST; |
root |
λ¬Έμ λ£¨νΈ λλ ν 리 | root ./html/www; |
index |
κΈ°λ³Έ μΈλ±μ€ νμΌ | index index.html; |
autoindex |
μλ λλ ν 리 μΈλ±μ± | autoindex on; |
client_max_body_size |
μ΅λ μμ² λ°λ ν¬κΈ° | client_max_body_size 1000; |
return |
HTTP 리λ€μ΄λ νΈ | return 301 http://...; |
μ μ νμΌμ μ 곡νκ±°λ CGI μ€ν¬λ¦½νΈλ₯Ό μ€νν©λλ€.
curl http://localhost:80/index.htmlλ°μ΄ν°λ₯Ό μλ²λ‘ μ μ‘νκ±°λ νμΌμ μ λ‘λν©λλ€.
curl -X POST -d "key=value" http://localhost:80/post_body
curl -X POST -F "file=@test.txt" http://localhost:80/uploadνμΌμ μμ±νκ±°λ μ λ°μ΄νΈν©λλ€.
curl -X PUT -d "content" http://localhost:80/put_test/file.txtμ§μ λ 리μμ€λ₯Ό μμ ν©λλ€.
curl -X DELETE http://localhost:80/soulee/file.txtμΉμλ²λ λμ μ½ν μΈ μμ±μ μν΄ CGI(Common Gateway Interface)λ₯Ό μ§μν©λλ€.
#!/usr/bin/env python3
print("Content-Type: text/html\n")
print("<html><body>")
print("<h1>Hello from CGI!</h1>")
print("</body></html>")CGI μ€ν¬λ¦½νΈλ μ€ν κΆνμ΄ νμνλ©°, μ μ ν shebang λΌμΈμ ν¬ν¨ν΄μΌ ν©λλ€.
Client Request
β
ServerManager (kqueue μ΄λ²€νΈ λκΈ°)
β
ClientManager (ν΄λΌμ΄μΈνΈ μ°κ²° κ΄λ¦¬)
β
Request Parser (HTTP μμ² νμ±)
β
HttpRequestManager (μμ² λΌμ°ν
)
β
Handler μ ν (Static/Dynamic/Error/Redirect/Delete)
β
Response Builder (HTTP μλ΅ μμ±)
β
Client Response
- ServerManager: μ¬λ¬ μλ² μΈμ€ν΄μ€λ₯Ό κ΄λ¦¬νκ³ kqueueλ₯Ό ν΅ν΄ μ΄λ²€νΈλ₯Ό μ²λ¦¬
- ClientManager: ν΄λΌμ΄μΈνΈ μ°κ²°μ μΆμ νκ³ κ΄λ¦¬
- ConfigParser: μ€μ νμΌμ νμ±νμ¬ μλ² κ΅¬μ± μμ±
- HttpRequestManager: HTTP μμ²μ μ μ ν νΈλ€λ¬λ‘ λΌμ°ν
- Handler κ³μΈ΅: μμ² μ νλ³λ‘ νΉνλ μ²λ¦¬ λ‘μ§ μ 곡
- μΈμ΄: C++98
- νμ€ λΌμ΄λΈλ¬λ¦¬: STL (Standard Template Library)
- I/O λͺ¨λΈ: kqueue (BSD μ΄λ²€νΈ μλ¦Ό μΈν°νμ΄μ€)
- νλ‘ν μ½: HTTP/1.1
- λΉλ μμ€ν : GNU Make
- μ»΄νμΌ νλκ·Έ:
-Wall -Werror -Wextra -std=c++98 -g3
νλ‘μ νΈλ νλ°ν κ°λ° μ€μ΄λ©°, μ΅κ·Ό μ»€λ° λ΄μμ λ€μκ³Ό κ°μ΅λλ€:
- CGI μλ¬ μ²λ¦¬ κ°μ
- νμΌ μ‘΄μ¬νμ§ μμ λ 500 μλ¬ λ°ν
- μλ² λΉλ μ΅μ ν
tester/ λλ ν 리μ ν
μ€νΈ μ€ν¬λ¦½νΈκ° ν¬ν¨λμ΄ μμ΅λλ€. μλ²μ λ€μν κΈ°λ₯μ κ²μ¦νλ λ° μ¬μ©ν μ μμ΅λλ€.
μ΄ νλ‘μ νΈλ κ΅μ‘ λͺ©μ μΌλ‘ μ μλμμ΅λλ€.
Git νμ€ν 리λ₯Ό μ°Έμ‘°νμ¬ νλ‘μ νΈ κΈ°μ¬μλ₯Ό νμΈν μ μμ΅λλ€.
λ λ§μ μ 보λ λ²κ·Έ 리ν¬νΈλ νλ‘μ νΈ μ μ₯μμ μ΄μ νΈλ컀λ₯Ό μ΄μ©ν΄μ£ΌμΈμ.