구현 | 응답 보내기

Response 객체의 응답 메시지화

응답을 보낼 때 가장 먼저 해야 할 작업은 Response 객체의 멤버 변수들을 응답 메시지 문자열로 변환하는 것입니다. 코드는 아래와 같습니다.

std::string
Response::getString() const
{	
	std::string message;
	std::map<std::string, std::string>::const_iterator it = this->m_headers.begin();

	message = m_protocol + " " + ft::to_string(m_status_code) + " " + m_status_description + "\r\n";
	for (; it != this->m_headers.end(); ++it)
		message += it->first + ": " + it->second + "\r\n";
	if (m_connection_type == CLOSE || m_status_code < 200 || m_status_code > 299)
		message += "Connection: close\r\n";
	else
		message += "Connection: Keep-Alive\r\n";
	if (m_transfer_type == CHUNKED) {
		message += "Transfer-Encoding: chunked\r\n\r\n";
		int size = this->m_content.size();
		int count;
		std::string data = m_content;
		int added = 0;
		while (size > 0)
		{
			if (size > BUFFER_SIZE)
				count = BUFFER_SIZE;
			else
				count = size;
			message += ft::itos(ft::to_string(count), 10, 16) + "\r\n";
			message += data.substr(added, count) + "\r\n";
			size -= count;
			added += count;
		}
		data.clear();
		message += "0\r\n\r\n";
	}
	else
	{
		message += "\r\n";
		message += this->m_content;
	}
	return (message);
}

프로토콜과 상태 코드, 사유 구절을 합쳐 시작 줄을 만듭니다. 헤더 맵의 key와 value들을 쌍으로 헤더를 추가합니다. body의 경우 chunked encoding인 경우 BUFFER_SIZE보다 크지 않도록 잘라서 16진수 토큰과 함께 넣습니다. 이런 과정들을 거쳐 메시지를 만들고, 커넥션 객체의 write 버 변수에 저장합니다.

응답 전송하기

응답을 전송하는 과정은 단순합니다. write 버프에 저장된 응답 메시지를 client socket fd를 이용하여 전송하는 것이죠. 다만 보내야 할 메시지의 길이가 큰 경우에는 여러 차례에 걸쳐 나눠서 보내야 합니다. 코드는 아래와 같습니다.

bool
Connection::sendFromWbuf(int fd)
{
	int count = m_wbuf_data_size - m_send_data_size;
	if (count > BUFFER_SIZE)
		count = BUFFER_SIZE;
	count = send(fd, m_wbuf.c_str() + m_send_data_size, count, 0);
	if (count == 0 || count == -1) 
		throw (Server::IOError((("IO error detected to send response message to client ") + ft::to_string(fd)).c_str()));
	m_send_data_size += count;
	return (true);
}

send든 write든 write operation 작업이 0이나 -1을 리턴하는 경우 Connection(Client)을 제거해야 합니다.

Last updated