개요
WebServ는 ecole42의 프로젝트로, C++을 사용하여 HTTP/1.1 표준을 준수하는 웹서버를 처음부터 구현한 프로젝트다. 이 프로젝트를 통해 소켓 프로그래밍, 멀티플렉싱, HTTP 프로토콜, CGI 등의 개념을 학습한다.
주요 기능
1. 멀티플렉싱
select()시스템 콜을 사용한 I/O 멀티플렉싱- 단일 스레드에서 여러 클라이언트 동시 처리
- 읽기/쓰기 이벤트 동시 모니터링
2. 설정 파일 파싱
- Nginx 스타일의 설정 파일 지원
- 여러 서버 블록 설정 가능
- 각 서버별 포트, 호스트명, 루트 디렉토리 설정
- Location 블록을 통한 라우팅 설정
3. HTTP 메서드 지원
- GET: 리소스 조회
- POST: 리소스 생성 및 데이터 전송
- PUT: 리소스 업데이트
- DELETE: 리소스 삭제
- OPTIONS: 지원하는 메서드 확인
- TRACE: 요청 추적
4. CGI 지원
- PHP, Python 등 스크립트 언어 실행
- 확장자별 CGI 프로그램 매핑
- 환경 변수 전달 및 표준 입출력 처리
5. 파일 업로드
- POST/PUT 메서드를 통한 파일 업로드
- 업로드 폴더 지정 가능
- 클라이언트 본문 크기 제한
6. 에러 처리
- HTTP 상태 코드 처리
- 커스텀 에러 페이지 설정
- 타임아웃 처리 (클라이언트: 30초, 서버: 3초)
7. 디렉토리 리스팅
- autoindex 옵션을 통한 디렉토리 목록 표시
- index 파일 자동 검색
빌드 및 실행
요구사항
- C++ 컴파일러 (clang++ 또는 g++)
- Make
- libft 라이브러리 (프로젝트에 포함됨)
빌드
make
실행
# 기본 설정 파일 사용
./webserv
# 커스텀 설정 파일 지정
./webserv [설정파일경로]
정리
make clean # 오브젝트 파일 삭제
make fclean # 빌드 파일 모두 삭제
make re # 재빌드
설정 파일
설정 파일은 Nginx 스타일의 문법을 따른다. 기본 설정 파일은 webserv.conf다.
기본 구조
server {
listen 8080; # 포트 번호
server_name localhost; # 서버 이름
root ./www/; # 루트 디렉토리
client_max_body_size 200M; # 최대 본문 크기
error_page ./www/error.html; # 에러 페이지 경로
location / {
allow GET POST; # 허용할 HTTP 메서드
index index.html index.php; # 기본 인덱스 파일
autoindex on; # 디렉토리 리스팅 활성화
root ./www/; # Location별 루트 디렉토리
}
location /cgi-bin/ {
cgi .php /usr/bin/php-cgi; # CGI 설정 (확장자: 실행파일)
root ./www/;
}
location /upload/ {
upload_folder ./www/upload/; # 업로드 폴더 지정
allow PUT POST;
root ./www/;
}
}
서버 블록 속성
listen: 포트 번호 (필수)server_name: 서버 이름root: 루트 디렉토리 경로client_max_body_size: 클라이언트 요청 본문 최대 크기error_page: 에러 페이지 경로
Location 블록 속성
root: Location별 루트 디렉토리autoindex: 디렉토리 리스팅 활성화 (on/off)index: 기본 인덱스 파일 목록allow: 허용할 HTTP 메서드 목록cgi: CGI 설정 (확장자 실행파일경로)upload_folder: 파일 업로드 폴더 경로client_max_body_size: Location별 본문 크기 제한
지원하는 HTTP 메서드
| 메서드 | 설명 | 구현 상태 |
|---|---|---|
| GET | 리소스 조회 | ✅ |
| POST | 리소스 생성/데이터 전송 | ✅ |
| PUT | 리소스 업데이트 | ✅ |
| DELETE | 리소스 삭제 | ✅ |
| OPTIONS | 지원 메서드 확인 | ✅ |
| TRACE | 요청 추적 | ✅ |
| HEAD | 헤더만 조회 | ✅ |
프로젝트 구조
webserv/
├── srcs/ # 소스 코드
│ ├── main.cpp # 진입점
│ ├── HTTP.cpp # HTTP 서버 핵심 로직
│ ├── HTTP.hpp
│ ├── ConfigParser.cpp # 설정 파일 파서
│ ├── ConfigParser.hpp
│ ├── webserv.hpp # 공통 헤더 및 구조체 정의
│ ├── HttpStatus.hpp # HTTP 상태 코드 정의
│ ├── handle_get.cpp # GET 메서드 핸들러
│ ├── handle_post.cpp # POST 메서드 핸들러
│ ├── handle_put.cpp # PUT 메서드 핸들러
│ ├── handle_delete.cpp # DELETE 메서드 핸들러
│ ├── handle_options.cpp # OPTIONS 메서드 핸들러
│ ├── handle_trace.cpp # TRACE 메서드 핸들러
│ ├── req_interpreter.cpp # 요청 파싱
│ ├── res_generator.cpp # 응답 생성
│ ├── res_cgi.cpp # CGI 처리
│ ├── res_make.cpp # 응답 메시지 생성
│ ├── res_send.cpp # 응답 전송
│ ├── mimetype.cpp # MIME 타입 처리
│ └── utils.cpp # 유틸리티 함수
├── lib/ # libft 라이브러리
├── config/ # 설정 파일 예시
├── www/ # 웹 루트 디렉토리
├── client/ # 테스트 클라이언트
├── Makefile # 빌드 스크립트
└── webserv.conf # 기본 설정 파일
주요 구조체
t_server
서버 설정 및 소켓 정보를 담는 구조체
socket: 서버 소켓 파일 디스크립터listen: 포트 번호server_name: 서버 이름root: 루트 디렉토리location: Location 블록 맵
t_client
클라이언트 연결 정보 및 요청/응답 데이터
socket: 클라이언트 소켓 파일 디스크립터req: 요청 정보 (t_req)res: 응답 정보 (t_res)server: 연결된 서버 정보
t_req
HTTP 요청 정보
method: HTTP 메서드path: 요청 경로headers: HTTP 헤더 맵body: 요청 본문is_cgi: CGI 요청 여부
t_res
HTTP 응답 정보
status_code: HTTP 상태 코드headers: HTTP 헤더 맵body: 응답 본문is_cgi: CGI 응답 여부
사용 예시
기본 실행
./webserv
커스텀 설정 파일 사용
./webserv config/configTest.conf
curl을 사용한 테스트
# GET 요청
curl http://localhost:8080/
# POST 요청
curl -X POST http://localhost:8080/post_body --data "test data"
# PUT 요청 (파일 업로드)
curl -X PUT http://localhost:8080/put_test/file.txt --data-binary @local_file.txt
# DELETE 요청
curl -X DELETE http://localhost:8080/delete_test/file.txt
# 특정 호스트명으로 요청
curl --resolve example.com:8080:127.0.0.1 http://example.com:8080/
브라우저에서 접속
브라우저에서 http://localhost:8080으로 접속하여 웹서버를 테스트할 수 있다.
기술 스택
- 언어: C++98
- 시스템 콜:
socket(),bind(),listen(),accept()- 소켓 통신select()- I/O 멀티플렉싱read(),write()- 데이터 입출력fork(),execve()- CGI 실행
- 라이브러리:
- libft (커스텀 C 라이브러리)
- 표준 C++ 라이브러리
주요 특징
1. 비동기 I/O 처리
select()를 사용하여 단일 스레드에서 여러 클라이언트 처리- 논블로킹 소켓 사용
- 읽기/쓰기 이벤트 분리 처리
2. 요청 파싱
- HTTP 요청 라인 파싱
- 헤더 파싱 및 저장
- 본문 처리 (Content-Length, Chunked Transfer Encoding)
3. 응답 생성
- HTTP 상태 코드에 따른 응답 생성
- 적절한 헤더 설정
- 파일 읽기 및 전송
- 디렉토리 리스팅 HTML 생성
4. 에러 처리
- 클라이언트 타임아웃 처리
- 연결 종료 감지
- 잘못된 요청 처리
- 메모리 누수 방지
참고 자료
- RFC 7230 - HTTP/1.1: Message Syntax and Routing
- RFC 7231 - HTTP/1.1: Semantics and Content
- RFC 7232 - HTTP/1.1: Conditional Requests
- RFC 7233 - HTTP/1.1: Range Requests
- RFC 7234 - HTTP/1.1: Caching
- RFC 7235 - HTTP/1.1: Authentication
라이선스
이 프로젝트는 42 Seoul의 교육용 프로젝트다.