webserv's People
webserv's Issues
HEAD 구현
sender, reader를 두는게 아닌 client가 두가지를 다 가지고 있고 changelist의 udata가 client를 가지고 있도록 구조 변경
request message의 header를 읽을때 에러처리
value가 들어오지 않는 경우 bad request처리를 해야하며
키의 앞뒤에 공백이 들어가 있으면 bad request 처리를 해야함
CGI Timer 등록
Miniserv 구축
- CSAPP 책 참고하며, Web Serv 구축
이상한 Method 들어왔을 때 적당한 처리 필요합니다.
webserv/srcs/Http/Handler/Handler.cpp
Line 154 in a033584
메소드 빈거 들어오면 404띄우게 했는데 allowed method 대조해서 에러 띄워야할것같습니다.
MaxBodySize 구현
chunked message 처리
RequestMessage Class이 버퍼를 읽으면서 동시에 파싱을 하는 로직. 메시지를 처리하게 되는 로직
연속적으로 버퍼에 input이 들어오면 RequestMessage가 실시간으로 파싱을 하여 현재 읽고 있는 메시지의 위치를 추적한다.
state를 두어서 start-line, header, body중 어느 부분을 읽고 있는지 판단함.
시작할때 timeout시간을 걸어둠- 타임아웃이 끝나면 바로 메시지 처리를 시작
- start-line을 읽고 파싱함.
- 프로토콜을 확인하여 허용되지 않은 버전이면 에러처리
- host 를 읽고 어떤 서버 블록에 해당하는지 확인함
- 메서드를 보고 허용된 메서드인지 확인하여 아니면 에러처리
- POST, PUT일 경우 body가 있을 수도 있음. content-length가 있는지 확인
- content-length가 있거나 chunked 헤더가 있으면 그 사이즈를 보고 본문 여부를 확인함.
- 만약 두 헤더 모두 없으면 본문은 없을것이라 봐도 됨
- content-length보다 작게 들어오거나 body가 없을 경우는 에러처리(bad request)
- RequestTarget이 파일일때, 파일이 존재하는지 확인(404), 권한이 있는지 확인(403)
- RequestTarget이 디렉토리일때, 디렉토리가 존재하는지 확인(404), 권한이 있는지 확인(403), autoindex가 켜져있는지 확인(403)
- RequestTarget이 파일도 디렉토리도 아니라면 404에러...
config파일로부터 default error page 가져오기
탐색개발
HTTP, CGI 등 새로 배우는 개념들에 대해 학습하는 기간입니다.
모르는 개념들에 대해 자주적으로 학습을 진행합니다.
궁금한 사항들은 서로 질문하며, 동료 학습을 진행합니다.
NGINX 실습 환경 구축, NGINX 실습
- 자신의 Mac에서 VM을 활용해 실습 환경에 사용 가능한 NGINX 웹 서버를 설치합니다.
- NGINX의 설정을 바꿔보며, 서버가 어떻게 동작하는지 이해해봅니다.
구조 설계
지금까지 학습한 내용들을 총합해, Webserv의 구조를 설계하고 도출된 내용을 통해 Flowchart를 그립니다.
cgi-bin path를 설정파일로 부터 가져올 수 있게 하기
문제상황
테스터기는 폴더와 파일에다가 POST, PUT을 시도한다. 이경우 파일을 열어 body에 담긴 정보를 파일에 넣고 그 내용을 다시 응답으로 보내줘야한다.
하지만 우리는 URI에 cgi-bin이 들어간 경우에만 cgi를 실행하고 나머지의 경우 static으로 처리한다.
대안
cgi경로인 cgi PATH를 설정파일에서 설정할 수 있도록 하면 테스터기를 통과하지 않더라도 디펜스가 가능 할 것이라 생각함
어떤 요청이 들어오든 서버가 같은 respond를 보내도록 하는 테스트 서버
respond메시지를 만드는 로직부분은 차후 처리하는 방향으로..
PUT 구현
server, location, 등 클래스 파일 정리
Message, RequestMessage, RespondMessage 구조생성
httpVersion Checker
httpVersion이 맞지 않을 경우 505 HTTP Version Not Supported를 띄어줘야함
config file parsing
간단한 config 파일을 파싱하는 모듈작성
말단 토큰 : ; { } WORD (총 4가지)
소켓 프로그래밍 실습
- Socket Echo Server 구현하기
- Socker Multiplexing 구현하기
테스터기를 돌리기 위한 새로운 메서드 구현
- DELETE
- PUT
- HEAD
requestMessageReader와 대응되는 respondMessageWriter 클래스 생성
- 출력 버퍼를 map으로 가지고 있음.
- respondMessage 버퍼를 가지고 있음.
큰 파일 사이즈가 들어올때 읽지 못하는 버그
server_socket event추가시 서버class 주소를 udata로 추가하여 클라이언트와 서버의 연결 간편화
코드 전체 리팩토링
ㅠㅠ
allow method 거르는 로직
cgi처리시 kqueue를 통하여 처리하도록 로직 변경
현재 branch soulee에서는 cgi실행(execve)후에 write와 while문을 이용한 read를 가지고와서 response에 담아주고 있다.
하지만 read와 write는 kqueue를 통해서 해야하므로 FE와 협업을 통해 분리되어 있는 구조를 병합할 필요가 있다.
현재로직
kevent로 request Message read를 받아서 메시지가 완성이 되면 httpRequestManager->handle실행 -> 안에서 cgi실행과 cgi와의 read, write수행중
대안로직
kevent로 request Message read를 받아서 메시지가 완성이 되면,
static(파일로 읽어오는 경우)
- handle에서 uri에 해당하는 파일을 open한 후 read event를 등록
- 다음 순회때 FE에서 read를 하여 파일을 받아옴. 받아온 파일은 responseMessage의 body에 저장
- 전부 받아온 뒤에 read가 성공했는지 여부에 따라, 권한문제에 따라 responseMessage의 startline과 headers를 만들어 responseMessage를 완성함
- responseMessage를 모두 client의 sendBuffer에 넣어주고 write event등록
- 다음 순회때 실제 클라이언트에게 write해줌
dynamic(cgi로 부터 쓰고 읽는 경우)
- handle에서 uri에 해당하는 cgi파일을 특정해줌
- 기존처럼 pipe 2개를 만들어 사용할 fd만 남겨두고 두 fd에대해 read, write 이벤트 모두 설정해줌.(두 fd는 client가 가지고 있어야함)
- env(쿼리등)를 세팅하고 자식프로세스를 만들고 자식 fd는 client가 cgi_fd라고 저장해둠.
- 다음 루프때 write와 read를 순차적으로 실행한후 read의 끝나면 정보를 responseMessage body에 넣어줌.(read또는 write 실패시 stop하고 현재 루프에서 생성한 리소스들 모두 회수 && client에게는 503error보냄)
- 직후에 cgi_fd를 회수하고 pipe역시 close해줌
- responseMessage를 모두 client의 sendBuffer에 넣어주고 write event등록
- 다음 순회때 실제 클라이언트에게 write해줌
HttpRequest 구조 변경
구조가 커지다보니 안쓰는 변수들이 많음. 이 부분 수정 필요
udata 보고 type check 하는 로직 만들기
Server Class가 RequestMessage를 받아 Client에게 응답을 보내주는 로직
- Client의 runServer호출하면
1.server의 runServer 호출이 됨
2.Client의 response Message에 복사 - MessageSender로 response Message를 보냄
- Sender는 출력 버퍼로 입력
- ServerManager에서 kevnet에 출력 이벤트 등록
에러 분기별 ErrorHandler 등록
default.conf가 있는 경우 자동적으로 conf 불러오기
client class가 가지는 respond message class의 구조
#19 에서 만들 client class 가 가지는 respond message class의 구조를 설정해야함.
Class Message를 상속받은 뒤 string으로 statusCode, reasonPhrase를 추가하여
std::string statusCode;
std::string reasonPhrase;
std::vector<unsigned char> raw;
std::string startLine;
std::string httpVersion;
std::map<std::string, std::string> headers;
std::vector<unsigned char> body;
를 가지게 됨
request의 시작 라인을 읽을때 partial write가 잘 되지 않는 문제
TEST CASE:
GET (EOF) / (EOF) HTTP/1.1
중간중간 파싱이 끝나버리는 현상이 있음
client class 를 만들고, server manager 의 구조를 바꿔야 함.
client 클래스를 만들고,
request message,
response message,
server 등 을 가지고 있어야함.
server manager 가 가지고 있는 request message map 을 client 맵으로 변경,
manager 내부에서 사용하는 때에도 편리하게 사용할 수 있도록 레퍼런스로 적용
중복 포트 서버 블록 파싱 에러
server {
listen 80 ;
server_name 127.0.0.1 ;
location / {
allow_method GET POST ;
}
}
server {
listen 80 ;
server_name localhost ;
location /a {
allow_method GET POST
}
}
처럼 중복된 포트가 있는 서버블록이 있으면 파싱에러가 되도록 수정.
std::map<PORT, std::vector<Server> > servers
->
std::map<PORT, Server> servers
동시에 위같은 map을 가지도록 변경해야함
Request를 받는 속도와 서버가 처리하는 속도를 모르는 상황에서 req, res변수를 하나만 뒀을때 문제상황
서버의 처리가 오래 걸릴경우 다음 request를 받지 못하는것이 부자연스러워 서버가 처리중이더라도 request를 받을 수도 있도록, requestMessage(HttpRequest)를 queue자료구조에 저장함.
동시에 response메시지도 사이즈가 클 수 있기때문에 queue로 생성함
두 자료구조 동일하게 최신것은 back에 넣고 가장 오래된게 front에 있음.
requestTarget이름 uri로 변경하기
FE와 BE간 용어가 일치하지 않아 불편한 점이 있음
HTTP Request에 Body가 있는 경우 파싱이 정상적으로 이뤄지지 않음
Body가 있는 경우 파싱 부분에서 Loop에 빠짐
serverManager structure 변경
servermanager에 client의 request 를 처리하고, response 를 담고 있는 client 구조체의 map 을 적용 하고,
server를 찾아서 client 에 넣어주는 함수 적용
parse단계에서 찾은 에러종류를 BE에 넘김
requestMessage에
enum ParseErrorCode
{
BAD_REQUEST = 400,
HTTP_VERSION_NOT_SUPPORT = 505,
}; // 해당내용은 추가변경될 수 있음
를 추가하고, ParseState가 Error가 될 때 errorCode(requestMessage안에 변수로 선언해둠) 세팅해둠. 문제가 없을시 0으로 초기화 되어있을 예정
to_string 11버전 수정필요
Status 파싱
cgi_tester
Message Reader 생성
ReqToCgiWriteProcess 함수의 반환값에 따른 처리분기 완성안됨
// -1 : write error, 1 : buffer->size == 0, 0 : buffer left
POST인 경우 Static으로 안 넘어감
CGI 인자 추가
setenv("REQUEST_METHOD", "POST", 1);
setenv("SERVER_PROTOCOL", "HTTP/1.1", 1);
setenv("PATH_INFO", "/", 1);
setenv("CONTENT_LENGTH", size_cstr, 1);
setenv("QUERY_STRING", "fnum=1&snum=2", 1);
CGI 에러 수정
Server manager 구조 설계
Server_manager
- 서버 구조체를 가진 벡터
- 포트별 서버네임 벡터를 가진 맵 (std::map<port, std::vec<servername(string)> >)
- <client_socket, 서버주소>인 맵**(deprecated)**
- kqueue관련 정보 아카이브
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.