길고 길었던 웹서브 과제가 끝남에 따라, 그 동안 했던것들을 정리해보고자 한다.
웹서버와 HTTP
웹서브 서브젝트를 보면 이런 글귀가 있다.
This is when you finally understand why a URL starts with HTTP
URL이 HTTP로 시작하는 이유를 마침내 이해할 때가 왔다는 뜻이다. 그렇다면, 웹서버를 만드는 데에는 HTTP와 URL의 이해가 필수가 되어야하겠다.
서브젝트에서는 HTTP에 대해 이렇게 설명하고 있다.
- HTTP(Hypertext Transfer Protocol)는 분산, 협업, 하이퍼미디어 정보 시스템을 위한 애플리케이션 프로토콜입니다.
- HTTP는 하이퍼텍스트 문서가 사용자가 쉽게 액세스할 수 있는 다른 리소스에 대한 하이퍼링크를 포함하는 World Wide Web을 위한 데이터 통신의 기반입니다.
- 예를 들어 마우스를 클릭하거나 웹 브라우저에서 화면을 탭합니다. HTTP는 하이퍼텍스트와 월드 와이드 웹을 용이하게 하기 위해 개발되었습니다.
- 웹 서버의 주요 기능은 웹 페이지를 저장, 처리 및 클라이언트에 전달하는 것입니다. 클라이언트와 서버 간의 통신은 HTTP(Hypertext Transfer Protocol)를 사용하여 이루어집니다. 전달되는 페이지는 텍스트 콘텐츠 외에 이미지, 스타일 시트 및 스크립트를 포함할 수 있는 HTML 문서인 경우가 가장 많습니다.
- 트래픽이 많은 웹 사이트에는 여러 웹 서버를 사용할 수 있습니다.
- 일반적으로 웹 브라우저 또는 웹 크롤러인 사용자 에이전트는 HTTP를 사용하여 특정 리소스를 요청하여 통신을 시작하고 서버는 해당 리소스의 콘텐츠 또는 그렇게 할 수 없는 경우 오류 메시지로 응답합니다. 리소스는 일반적으로 서버의 보조 스토리지에 있는 실제 파일이지만 반드시 그런 것은 아니며 어떻게 웹서버가 구현되었습니다.
- 기본 기능은 콘텐츠를 제공하는 것이지만 HTTP의 전체 구현에는 클라이언트에서 콘텐츠를 수신하는 방법도 포함됩니다. 이 기능은 파일 업로드를 포함하여 웹 양식을 제출하는 데 사용됩니다.
간단하게 설명되어있지만, 어떻게 보면 우리가 구현해야하는 전체적인 웹서버의 모든 기능들을 다 설명해주고 있기도 하다.
웹서브 서브젝트를 보고있으면, 뭔가 구현해야하는 것들이 엄청나게 나열되어있는것을 알 수 있다. 진행하다보면 어느샌가 전부 구현할 수 있을테니 쫄지말자.
초반에 감을 잡기 위해서 봤던 페이지들 중, 웹서브 튜토리얼이라는 페이지를 자주 봤었다.
Webserv tutorials - webserv
이 튜토리얼은 여러분이 미처 생각지도 못했던 부분들까지 케어합니다. 정도의 차이는 있겠지만, 짧은 양과 범위가 아니기 때문에 누구에게든 어디에선가 큰 도움이 될 것입니다. 하지만 동시
42seoul.gitbook.io
이 게시글도 여러분들이 웹서브를 수행하는데 필요한 다양한 구성품 중 하나가 되기를 바란다.
서브젝트 요구사항
C++ 98로 HTTP 서버를 작성해야 합니다.
실행 파일은 다음과 같이 실행됩니다: ./webserv \[구성 파일]
제목과 평가 척도에 poll()이 언급되어 있지만, select(), kqueue(), 또는 epoll()과 같은 동등한 기능을 사용할 수 있습니다.
프로젝트를 시작하기 전에 RFC를 읽고 telnet 및 NGINX를 사용하여 몇 가지 테스트를 수행해야 합니다.
RFC를 모두 구현할 필요는 없지만, 읽는 것은 필요한 기능을 개발하는 데 도움이 됩니다.
Requirements
- 프로그램은 구성 파일을 인수로 받거나 기본 경로를 사용해야 합니다.
- 다른 웹 서버를 execve 할 수 없습니다.
- 서버는 절대 블로킹되면 안 되며, 클라이언트가 필요한 경우 적절하게 다루어져야 합니다.
- 블로킹되지 않고, 모든 I/O 작업 (리스닝 포함)에 대해 1개의 poll() (또는 이와 동등한)만 사용해야 합니다.
- poll() (또는 동등한)은 읽기와 쓰기를 동시에 확인해야 합니다.
- 읽기 또는 쓰기 작업을 poll() (또는 동등한) 없이 수행해서는 안 됩니다.
- read 또는 write 작업 후에 errno 값을 확인하는 것은 엄격히 금지됩니다.
- 구성 파일을 읽기 전에는 poll() (또는 동등한)을 사용할 필요가 없습니다.
블로킹되지 않는 파일 디스크립터를 사용해야 하기 때문에, read/recv 또는 write/send 함수를 사용할 수 있지만, poll() (또는 동등한)을 사용하지 않으면 서버가 블로킹될 수 있습니다. 그러므로, poll() (또는 동등한)을 사용하지 않고 파일 디스크립터의 읽기/수신 또는 쓰기/송신을 시도하면, 점수가 0점이 됩니다.
- FD_SET, FD_CLR, FD_ISSET, FD_ZERO와 같은 모든 매크로와 정의를 사용할 수 있습니다. (그것들이 무엇을 하는지 이해하는 것이 매우 유용합니다.)
- 서버 요청은 영원히 멈춰서는 안 됩니다.
- 서버는 사용자가 선택한 웹 브라우저와 호환되어야 합니다.
- NGINX가 HTTP 1.1 호환성을 가지고 있고 헤더 및 응답 동작을 비교할 수 있다고 가정합니다.
- HTTP 응답 상태 코드는 정확해야 합니다.
- 기본 오류 페이지가 제공되지 않은 경우에도 서버가 있어야 합니다.
- CGI 외에는 fork를 사용할 수 없습니다. (예: PHP, Python 등)
- 정적 웹 사이트를 완전히 제공할 수 있어야 합니다.
- 클라이언트는 파일 업로드를 할 수 있어야 합니다.
- GET, POST, DELETE 방법이 최소한 있어야 합니다.
- 서버를 스트레스 테스트해야 합니다. 비용이든 무엇이든 상관없이 항상 사용 가능해야 합니다.
- 서버는 여러 port의 신호를 처리할 수 있어야 합니다.
For MacOS only
MacOS에서는 다른 유닉스 OS와는 다르게 write()를 구현하지 않으므로, fcntl()을 사용할 수 있습니다. 파일 디스크립터를 논블로킹 모드로 사용하여 다른 유닉스 OS와 비슷한 동작을 얻을 수 있습니다.
하지만, 다음과 같은 방식으로만 fcntl()을 사용할 수 있습니다. fcntl(fd, F_SETFL, O_NONBLOCK); 다른 플래그는 허용되지 않습니다.
Configuration file
설정 파일에서는 다음과 같은 기능을 구현해야합니다
- 각 서버의 포트와 호스트를 선택할 수 있습니다.
- 서버 이름을 설정하거나 설정하지 않을 수 있습니다.
- 호스트:포트의 첫 번째 서버는 해당 호스트:포트의 기본값입니다. (즉, 다른 서버에 속하지 않는 모든 요청에 대해 응답합니다.)
- 기본 오류 페이지를 설정할 수 있습니다.
- 클라이언트 본문 크기를 제한할 수 있습니다.
- 라우트를 다음 규칙/구성 중 하나 이상으로 설정할 수 있습니다 (라우트는 정규식을 사용하지 않습니다):
- 라우트에 대한 수락된 HTTP 메소드 목록을 정의합니다.
- HTTP 리디렉션을 정의합니다.
- 파일이나 디렉토리를 정의하여 해당 파일이나 디렉토리에서 검색하도록 설정합니다. (예: url /kapouet이 /tmp/www로 루트되면 url /kapouet/pouic/toto/pouet은 /tmp/www/pouic/toto/pouet입니다.)
- 디렉토리 목록을 켜거나 끌 수 있습니다.
- 디렉토리가 요청인 경우 응답할 기본 파일을 설정할 수 있습니다.
- 특정 파일 확장자를 기반으로 CGI를 실행할 수 있습니다 (예: .php).
- POST 및 GET 메소드와 함께 작동하도록 할 수 있습니다.
- 라우트가 업로드된 파일을 수락하고 저장되는 위치를 구성할 수 있도록 합니다.
- CGI가 무엇인지 궁금한가요?
- 직접 CGI를 호출하지 않으므로 PATH_INFO를 전체 경로로 사용합니다.
- 청크 요청의 경우 서버에서 청크를 해제해야하며 CGI는 본문의 끝으로 EOF를 기대합니다.
- CGI에서 content_length가 반환되지 않으면 EOF가 반환된 데이터의 끝을 나타냅니다.
- 프로그램은 요청된 파일을 첫 번째 인수로 CGI를 호출해야합니다.
- CGI는 상대 경로 파일 액세스를 위해 올바른 디렉토리에서 실행되어야합니다.
- 서버는 하나의 CGI (php-CGI, Python 등)와 함께 작동해야합니다.
평가 중에는 모든 기능이 작동하는 것을 테스트하고 보여주기 위한 구성 파일 및 기본 파일을 제공해야합니다.
만약 특정 동작에 대한 질문이 있다면, 자신의 프로그램 동작을 NGINX와 비교해 보아야 합니다. 예를 들어, server_name이 어떻게 동작하는지 확인해보세요. 작은 테스터를 제공해 드렸지만, 브라우저 및 테스트를 통해 모든 것이 원활하게 동작한다면 이를 통과할 필요는 없지만, 버그를 찾는 데 도움이 될 수 있습니다.
중요한 것은 내구성입니다. 서버는 절대로 멈추지 않아야 합니다.
하나의 프로그램으로만 테스트하지 마십시오. 좀 더 편리한 언어인 Python, Golang 등으로 테스트를 작성하십시오. C 또는 C++로도 작성할 수 있습니다.
Bonus part
추가할 수 있는 추가 기능은 다음과 같습니다.
- 쿠키 및 세션 관리를 지원합니다(빠른 예제 준비).
- 여러 CGI를 처리합니다.
보너스 부분은 필수 부분이 PERFECT인 경우에만 평가됩니다. 완벽한 것은 필수 부분이 통합적으로 이루어졌으며 오작동 없이 작동한다는 것을 의미합니다. 모든 필수 요구 사항을 통과하지 못한 경우 보너스 부분은 전혀 평가되지 않습니다.
'42SEOUL > Circle5' 카테고리의 다른 글
[42Seoul] webserv - 02 (0) | 2023.06.30 |
---|---|
[42Seoul] Webserv - 01 (0) | 2023.06.26 |
[42SEOUL] CPP Module 09 (0) | 2023.04.11 |
[42SEOUL] CPP Module 08 (0) | 2023.02.18 |
[42SEOUL] CPP Module 07 (0) | 2023.02.18 |