응답을 보낼 때 가장 먼저 해야 할 작업은 Response 객체의 멤버 변수들을 응답 메시지 문자열로 변환하는 것입니다. 코드는 아래와 같습니다.
Copy 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를 이용하여 전송하는 것이죠. 다만 보내야 할 메시지의 길이가 큰 경우에는 여러 차례에 걸쳐 나눠서 보내야 합니다. 코드는 아래와 같습니다.
Copy 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 );
}