구현 | CGI 실행하기

CGI 환경변수 세팅하기

CGI에서 가장 먼저 해야 할 것은 CGI 환경변수를 세팅하는 것입니다. 메인 프로그램에서 환경변수를 받은 뒤 Config 객체에 저장해두다가, 추가로 CGI 실행을 위한 환경변수를 할당하여 새로운 환경변수(char **)를 만들고 CGI 프로그램을 실행합니다. 코드는 다음과 같습니다. 이런 환경변수들이 제대로 세팅되지 않으면 42에서 제공하는 tester CGI 프로그램이 정상적으로 동작하지 않기 때문에 주의를 기울여야 하며, 특히 PATH_INFO와 PATH_TRANSLATED, SCRIPT_NAME에 대해 명확하게 이해하고 사용해야 합니다.

if (token == "CONTENT_LENGTH") {
	if (ft::hasKey(request.get_m_headers(), "Content-Length"))
		return (request.get_m_headers().find("Content-Length")->second);
	return (std::string("-1"));
}
else if (token == "CONTENT_TYPE") {
	if (ft::hasKey(request.get_m_headers(), "Content-Type"))
		return (request.get_m_headers().find("Content-Type")->second);
	return (std::string());
}
else if (token == "AUTH_TYPE")
	return (config.get_m_cgi_version());
else if (token == "PATH_INFO")
	return (request.get_m_path_info());
else if (token == "PATH_TRANSLATED")
	return (request.get_m_path_translated());
else if (token == "QUERY_STRING")
	return (request.get_m_query());
else if (token == "REMOTE_ADDR")
	return (request.get_m_connection()->get_m_client_ip());
else if (token == "REQUEST_METHOD")
	return (request.get_m_method_to_string());
else if (token == "REQUEST_URI")
	return (request.get_m_uri());
else if (token == "SCRIPT_NAME")
	return (request.get_m_script_translated());
else if (token == "SERVER_NAME")
	return (server->get_m_server_name());
else if (token == "SERVER_PORT")
	return (ft::to_string(server->get_m_port()));
else if (token == "SERVER_PROTOCOL")
	return ("HTTP/" + config.get_m_http_version());
else if (token == "SERVER_SOFTWARE")
	return (config.get_m_software_name() + "/" + config.get_m_software_version());
else if (token == "GATEWAY_INTERFACE")
	return (config.get_m_cgi_version());
return (NULL);

위와 같은 복잡한 if/else if문은 지저분하고, 지양되어야 합니다. enum이나 macro, 컨테이너를 활용하여 swith나 for문으로 처리하는 게 좋습니다.

CGI 처리 흐름

일반적인 CGI의 처리 흐름은 다음과 같습니다.

  1. CGI 프로그램과 통신할 파이프 만들기

  2. 파이프 fd에 대해 nonblock 설정하기

  3. 불필요한 fd 닫기

  4. CGI 환경변수 세팅하기

  5. fork 하기

  6. 자식 함수에서 execve 함수 실행하기

  7. 부모 함수에서 read_set, write_set 설정하기

42 CGI Tester

42에서 제공하는 cgi tester는 cgi program입니다. 즉, 이름을 바꿔서 여러분의 cgi program이 있어야 할 위치에 리소스로 사용하면 됩니다. 여러분이 cgi를 제대로 처리하는지는 tester 프로그램을 통해 함께 검사될 것이며, cgi tester는 cgi를 test하기 위해 필요한 cgi script일 뿐입니다.

주의사항

CGI의 처리 자체는 어렵지 않으나 주의해야 할 사항들이 많습니다.

입출력이 꼬이지 않기 위해 파이프는 2개를 만드는 것이 좋습니다.

파이프 fd 역시 nonblock 처리가 필수입니다.

select를 통하여 read/write 가능 여부를 확인 후 실행해야 하므로 여기에서 바로 입출력을 해서는 안 됩니다.

Last updated