NetMessage API

Oasis 네트워크 메세지는 NetMessage API 통하여 처리됩니다.

NetMessage는 네트워크 컴포넌트 인터페이스의 매개변수로 전달되고, 응답이나 요청을 위해 사용됩니다.

헤더 파일

OasisNet.h

함수

NetMessageRef netMessageCreate ( const NetMessageRef & msg , bool is_request )
OasisNet.h
NetMessage 객체를 생성합니다.
매개변수
msg  참조 NetMessage 객체입니다. 응답 NetMessage를 생성할 경우, 이 응답 메세지에 대한 요청 메세지입니다.
is_request  true 이면 요청 메세지를 생성하고, false이면 응답 메세지를 생성합니다.
리턴값
성공하면 NetMessage 객체를 리턴하고, 실패하면, nullptr을 리턴합니다.
int32_t netMessageLocalAddressString ( const NetMessageRef & msg , std::string & local_address_string , std::string & local_port_string )
OasisNet.h
로컬 서버의 주소를 문자열로 리턴합니다.
매개변수
msg  NetMessage 객체입니다.
local_address_string  OUT 로컬 서버의 IPv4 주소입니다.
local_port_string  OUT 로컬 서버의 포트 번호입니다.
리턴값
  • 0: 성공
  • -1: 실패
int32_t netMessageRemoteAddressString ( const NetMessageRef & msg , std::string & remote_address_string , std::string & remote_port_string )
OasisNet.h
로컬 서버에 연결된 원격 클라이언트의 주소를 문자열로 리턴합니다.
매개변수
msg  NetMessage 객체입니다.
remote_address_string  원격 클라이언트의 IPv4 주소입니다.
remote_port_string  원격 클라이언트의 포트 번호입니다.
리턴값
  • 0: 성공
  • -1: 실패
int32_t netMessageGetSocket ( const NetMessageRef & msg )
OasisNet.h
NetMessage 객체에 연결된 소켓 핸들번호입니다.
매개변수
msg  NetMessage 객체입니다.
리턴값
소켓 번호를 리턴합니다. 실패하거나 연결되어 있지 않은 경우, -1을 리턴합니다.
int32_t netMessageAbortConnection ( const NetMessageRef & msg )
OasisNet.h
NetMessage 객체의 서버와 클라이언트 연결 끊습니다.
매개변수
msg  NetMessage 객체입니다.
리턴값
  • 0: 성공
  • -1: 실패
int32_t netMessageGetStatusCodeAndReasonString ( const NetMessageRef & msg , std::string & reason_string )
OasisNet.h
NetMessage에서 HTTP나 기타 텍스트 기반 프로토콜의 응답 상태 코드와 이유 문자열을 리턴합니다.
매개변수
msg  NetMessage 객체입니다.
reason_string  OUT 이유 문자열을 리턴합니다.
리턴값
상태 코드를 리턴합니다.
int32_t netMessageUriGetPath ( const NetMessageRef & msg , std::string & uri_path )
OasisNet.h
NetMessage의 URI 경로를 얻습니다.
매개변수
msg  NetMessage 객체입니다.
uri_path  OUT URI 경로를 리턴합니다.
리턴값
  • 0: 성공
  • -1: 실패
bool netMessageUriHasQueryParameter ( const NetMessageRef & msg , const char * key )
OasisNet.h
매개변수
msg  NetMessage 객체입니다.
key  확인할 키 문자열입니다.
리턴값
  • true: Query 집합에 키가 존재합니다.
  • false: Query 집합에 키가 존재하지 않습니다.
int32_t netMessageUriGetQueryParameterValue ( const NetMessageRef & msg , const char * key , std::string & value )
OasisNet.h
Query 키 값을 얻습니다.
매개변수
msg  NetMessage 객체입니다.
key  Query 키 문자열입니다.
value  OUT 키 값을 리턴합니다.
리턴값
  • 0: 성공
  • -1: 실패
int32_t netMessageUriGetQueryParameters ( const NetMessageRef & msg , key_value_map_t & dictionary )
OasisNet.h
Query 집합을 key-value map으로 얻습니다.
매개변수
msg  NetMessage 객체입니다.
dictionary  OUT Query key-value map을 리턴합니다.
리턴값
  • 0: 성공
  • -1: 실패
int32_t netMessageUriSetQueryParameterValue ( const NetMessageRef & msg , const char * key , const char * value )
OasisNet.h
Query 키에 값을 설정합니다.
매개변수
msg  NetMessage 객체입니다.
key  Query 키 문자열입니다.
value  키 값입니다.
리턴값
  • 0: 성공
  • -1: 실패
bool netMessageIsRequest ( const NetMessageRef & msg )
OasisNet.h
요청 메세지인지 확인합니다.
매개변수
msg  NetMessage 객체입니다.
리턴값
  • true: 요청 메세지입니다.
  • false: 응답 메세지입니다.
int32_t netMessageSetStatusCodeAndReasonString ( const NetMessageRef & msg , int32_t status_code , const char * reason_string )
OasisNet.h
메세지에 응답코드와 이유를 설정합니다.
매개변수
msg  NetMessage 객체입니다.
status_code  응답 코드입니다.
reason_string  응답 코드에 대한 이유(설명) 문자열입니다.
리턴값
  • 0: 성공
  • -1: 실패
int32_t netMessageSetContent ( const NetMessageRef & msg , const char * content_type_string , const void * content_data , size_t content_length )
OasisNet.h
메세지에 컨텐츠 데이터를 저장합니다.
매개변수
msg  NetMessage 객체입니다.
content_type_string  메세지의 Content-Type 입니다.
content_data  메세지의 컨텐츠 데이터 포인터 입니다.
content_length  컨텐츠 데이터 길이입니다. 바이트 단위입니다.
리턴값
  • 0: 성공
  • -1: 실패
ssize_t netMessageGetContentLength ( const NetMessageRef & msg )
OasisNet.h
메세지의 컨텐츠 길이를 얻습니다. 바이트 단위입니다.
매개변수
msg  NetMessage 객체입니다.
리턴값
컨텐츠 길이를 리턴합니다. 실패하면 -1을 리턴합니다. 컨텐츠가 비어 있으면 0을 리턴합니다.
int32_t netMessageGetContentType ( const NetMessageRef & msg , std::string & content_type )
OasisNet.h
메세지의 Content-Type을 얻습니다.
매개변수
msg  NetMessage 객체입니다.
content_type  OUT Content-Type을 리턴합니다.
리턴값
  • 0: 성공
  • -1: 실패
ssize_t netMessageGetContent ( const NetMessageRef & msg , std::vector<char> & content )
OasisNet.h
메세지 컨텐츠 데이터를 얻습니다.
매개변수
msg  NetMessage 객체입니다.
content  OUT 컨텐츠 데이터를 리턴할 벡터입니다.
리턴값
성공하면 컨테츠 길이 (바이트 단위)를 리턴합니다. 실패하면 -1을 리턴합니다.
bool netMessageIsChunkedContent ( const NetMessageRef & msg )
OasisNet.h
메세지 컨텐츠가 chunked 형태인지 확인합니다. 큰 컨텐츠의 메세지는 쪼개서 여러개 메세지로 전송됩니다. 완전히 다 받을 때까지 컨텐츠 길이는 0입니다.
매개변수
msg  NetMessage 객체입니다.
리턴값
  • true: chunked 메세지입니다.
  • false: 단일 메세지입니다.
ssize_t netMessageGetCurrentContentLength ( const NetMessageRef & msg )
OasisNet.h
메세지의 현재 컨텐츠 길이를 얻습니다. 바이트 단위입니다. 메세지 컨텐츠가 커서 분할되어 받아질 때 현재 컨텐츠 길이를 얻습니다.
매개변수
msg  NetMessage 객체입니다.
리턴값
성공하면 현재 컨텐츠 길이를 리턴합니다. 실패하면 -1을 리턴합니다.
bool netMessageIsContentReady ( const NetMessageRef & msg )
OasisNet.h
메세지 컨텐츠가 모두 다 받아서 준비된 상태인지 확인합니다. 대용량의 파일을 서버로 부터 받을 때 유용합니다. 아래 예제 참조합니다.
매개변수
msg  NetMessage 객체입니다.
리턴값
  • true: 준비된 상태입니다.
  • false: 아직 다운받는 중입니다.
int32_t netMessageGetContentFilePath ( const NetMessageRef & msg , std::string & filepath )
OasisNet.h
메세지의 컨텐츠를 파일에 저장할 경우, 컨텐츠 경로입니다. 파일에 저장하는 경우는 cache가 허용된 Content-Type에 대해 적용됩니다.
매개변수
msg  NetMessage 객체입니다.
filepath  OUT 컨텐츠가 저장된 파일 경로입니다.
리턴값
  • 0: 성공
  • -1: 실패
bool netMessageIsConnected ( const NetMessageRef & msg )
OasisNet.h
연결된 상태인지 확인합니다.
매개변수
msg  NetMessage 객체입니다.
리턴값
  • true: 연결된 상태입니다.
  • false: 연결되지 않은 상태입니다.
int32_t netMessageAddFieldToMultipartFormData ( const NetMessageRef & msg , const char * field_name , const char * field_value )
OasisNet.h
POST 메세지의 경우 사용자가 폼 데이터를 입력하였을 때, 필드 이름과 값을 메세지에 추가합니다. 실제 폼 필드가 아니어도 임의의 필드 이름과 값을 추가할 수 있습니다.
매개변수
msg  NetMessage 객체입니다.
field_name  필드 이름입니다.
field_value  필드 값입니다.
리턴값
  • 0: 성공
  • -1: 실패
int32_t netMessageAddContentToMultipartFormData ( const NetMessageRef & msg , const char * field_name , const char * content , size_t content_length , const char * content_type )
OasisNet.h
Multipart 메세지에 컨텐츠 데이터를 추가합니다.
매개변수
msg  NetMessage 객체입니다.
field_name  컨텐츠 필드 이름입니다.
content  컨텐츠 데이터 입니다.
content_length  컨텐츠 데이터 길이입니다. 바이트 단위입니다.
content_type  Content-Type 입니다.
리턴값
  • 0: 성공
  • -1: 실패
int32_t netMessageAddFileToMultipartFormData ( const NetMessageRef & msg , const char * field_name , const char * file_name , const char * content , size_t content_length , const char * content_type )
OasisNet.h
Multipart 메세지에 파일을 추가합니다. 서버 단으로 파일 전송할 때 유용합니다.
매개변수
msg  NetMessage 객체입니다.
field_name  필드 이름입니다.
file_name  파일명입니다.
content  파일 데이터입니다.
content_length  파일 데이터 길이입니다. 바이트 단위입니다.
content_type  Content-Type 입니다.
리턴값
  • 0: 성공
  • -1: 실패
int32_t netMessageAddFileToMultipartFormData ( const NetMessageRef & msg , const char * field_name , const char * file_name , const char * file_path , const char * content_type )
OasisNet.h
Multipart 메세지에 파일을 추가합니다. 파일 크기가 클 경우, 이 API를 이용합니다. 서버 단으로 파일 전송할 때 유용합니다.
매개변수
msg  NetMessage 객체입니다.
field_name  필드 이름입니다.
file_name  파일명입니다.
file_path  전송할 파일의 경로입니다.
content_type  Content-Type입니다.
리턴값
  • 0: 성공
  • -1: 실패
int32_t netMessageSetHeaderField ( const NetMessageRef & msg , const char * name_string , const char * value_string )
OasisNet.h
메세지에 헤더 필드를 추가합니다.
매개변수
msg  NetMessage 객체입니다.
name_string  헤더 필드 이름입니다.
value_string  헤더 필드 값입니다.
리턴값
  • 0: 성공
  • -1: 실패
int32_t netMessageSetCorsHeaderFields ( const NetMessageRef & msg , const NetMessageRef & req_msg , const char * origin = nullptr , const char * methods = nullptr , const char * headers = nullptr , bool allow_credentials = true , bool allow_private_network_access = true , int32_t max_age = 86400 )
OasisNet.h
메세지에 CORS(Cross-Origin Resource Sharing, 교차 출처 리소스 공유) 관련 헤더 필드를 추가합니다.
매개변수
msg  NetMessage 객체입니다.
req_msg  요청 NetMessage 객체입니다.
origin  Access-Control-Allow-Origin 헤더 필드를 추가합니다. nullptr일 경우, "✱" 값이 할당됩니다. msg가 응답 메세지이고, Access-Control-Allow-Origin 헤더 필드 값이 "✱"인 경우에, 요청 메세지(req_msg)의 Origin 헤더 필드가 있으면, 요청 메세지의 Origin 헤더 필드 값으로 대체될 수 있습니다. allow_credentialsallow_private_network_access 설명 참고합니다.
methods  Access-Control-Allow-Methods 헤더 필드를 추가합니다. nullptr일 경우, "OPTIONS,GET" 값이 할당됩니다.
headers  Access-Control-Allow-Headers 헤더 필드를 추가합니다. nullptr일 경우, "✱" 값이 할당됩니다.
allow_credentials  이 매개변수는 msg가 응답 메세지이고, 요청 메세지(req_msg)에 Access-Control-Request-Credentials 헤더 필드가 있는 경우에 적용됩니다. 요청 메시지가 유효하지 않을 경우 적용되지 않습니다. 응답 메세지의 Access-Control-Allow-Credentials 헤더 필드 값을 allow_credentials 에 따라 "true" 또는 "false" 값으로 설정합니다. 요청 메세지의 Access-Control-Request-Credentials 헤더 필드 값이 "true" 이고, origin 값이 nullptr이나 "✱" 인 경우, 응답 메세지의 Access-Control-Allow-Origin 헤더 필드 값을 요청 메세지의 Orgin 헤더 필드 값으로 대체됩니다.
allow_private_network_access  이 매개변수는 msg가 응답 메세지이고, 요청 메세지(req_msg)에 Access-Control-Request-Private-Network 헤더 필드가 있는 경우에 적용됩니다. 요청 메시지가 유효하지 않을 경우 적용되지 않습니다. 응답 메세지의 Access-Control-Allow-Private-Network 헤더 필드 값을 allow_private_network_access 에 따라 "true" 또는 "false" 값으로 설정합니다. 요청 메세지의 Access-Control-Request-Private-Network 헤더 필드 값이 "true"이고, origin 값이 nullptr이나 "✱" 인 경우, 응답 메세지의 Access-Control-Allow-Origin 헤더 필드 값을 요청 메세지의 Orgin 헤더 필드 값으로 대체됩니다.
max_age  Access-Control-Max-Age 헤더 필드 값을 추가합니다. 0 일경우, 86400 초로 설정합니다.
리턴값
  • 0: 성공
  • -1: 실패
int32_t netMessageGetHeaderFieldValue ( const NetMessageRef & msg , const char * name_string , std::string & value_string )
OasisNet.h
메세지의 헤더 필드 값을 얻습니다.
매개변수
msg  NetMessage 객체입니다.
name_string  헤더 필드 이름입니다.
value_string  OUT 필드 값을 리턴합니다.
리턴값
성공할 경우, 헤더 필드 값의 길이를 리턴합니다. 실패할 경우, -1을 리턴합니다.
int32_t netMessageGetHeaderFields ( const NetMessageRef & msg , key_value_map_t & dictionary )
OasisNet.h
메세지의 헤더 필드들을 key-value map 형태로 얻습니다.
매개변수
msg  NetMessage 객체입니다.
dictionary  OUT 헤더 필드 사전용 key-value map 을 리턴합니다.
리턴값
  • 0: 성공
  • -1: 실패
int32_t netMessageGetFormDataFieldValue ( const NetMessageRef & msg , const char * field_name , std::string & field_value )
OasisNet.h
메세지에서 폼 데이터 필드의 값을 얻습니다.
매개변수
msg  NetMessage 객체입니다.
field_name  필드 이름입니다.
field_value  OUT 필드 값을 리턴합니다.
리턴값
성공할 경우, 필드 값의 길이를 리턴합니다. 실패할 경우, -1을 리턴합니다.
ssize_t netMessageGetFormDataFileData ( const NetMessageRef & msg , const char * field_name , std::string & content_type , std::string & file_name , char ** file_data_ptr )
OasisNet.h
메세지에서 폼 데이터 파일 필드의 데이터를 얻습니다. 리턴된 데이터 길이 값이 유효하지만, *file_data_ptr 값이 nullptr일 수 있으며, 파일 데이터가 메모리가 아닌 캐쉬 파일로 저장되어 있음을 의미합니다. 이 경우, 아래의 netMessageGetFormDataFileData API를 이용하여, 직접 std::vector<char> &file_data 인수를 전달해서 데이터를 읽어와야 합니다. 단순 파일 데이터 타입, 파일이름과 파일 데이터 길이 확인 용으로 file_data_ptr 값을 nullptr로 지정하여 이 함수를 호출할 수 있습니다.
매개변수
msg  NetMessage 객체입니다.
field_name  필드 이름입니다.
content_type  OUT Content-Type을 리턴합니다.
file_name  OUT 파일명을 리턴합니다.
file_data_ptr  OUT nullptr이 아닌 경우, 내부에서 보관하고 있는 데이터의 포인터를 리턴합니다. 데이터를 복사하지 않습니다. 메모리가 아닌 캐쉬 파일에 저장된 경우, *file_data_ptr 값은 nullptr을 리턴합니다.
리턴값
성공할 경우, 데이터 길이를 리턴합니다. 실패할 경우, -1을 리턴합니다.
ssize_t netMessageGetFormDataFileData ( const NetMessageRef & msg , const char * field_name , std::string & content_type , std::string & file_name , std::vector<char> & file_data )
OasisNet.h
메세지에서 폼 데이터 파일 필드의 데이터를 전달한 버퍼에 저장합니다.
매개변수
msg  NetMessage 객체입니다.
field_name  필드 이름입니다.
content_type  OUT Content-Type을 리턴합니다.
file_name  OUT 파일명을 리턴합니다.
file_data  OUT 파일 데이터가 저장될 벡터입니다. 캐쉬에 저장된 경우, 캐쉬 파일 내용을 읽어서 저장됩니다.
리턴값
성공할 경우, 데이터 길이를 리턴합니다. 실패할 경우, -1을 리턴합니다.
ssize_t netMessageSaveFormDataFileDataAs ( const NetMessageRef & msg , const char * field_name , const char * file_path )
OasisNet.h
메세지에서 폼 데이터 파일 필드의 데이터를 전달한 파일 경로에 저장합니다.
매개변수
msg  NetMessage 객체입니다.
field_name  필드 이름입니다.
file_path  저장할 파일 경로입니다.
리턴값
성공할 경우, 저장한 파일 데이터 길이를 리턴합니다. 실패할 경우, -1을 리턴합니다.
int32_t netMessageSetMethod ( const NetMessageRef & msg , const char * method_string )
OasisNet.h
메세지의 Method를 설정합니다.
매개변수
msg  NetMessage 객체입니다.
method_string  Method 이름입니다.
리턴값
  • 0: 성공
  • -1: 실패
int32_t netMessageGetMethod ( const NetMessageRef & msg , std::string & method_string )
OasisNet.h
Method 이름을 얻습니다.
매개변수
msg  NetMessage 객체입니다.
method_string  OUT Method 이름을 리턴합니다.
리턴값
  • 0: 성공
  • -1: 실패
ssize_t netMessageSendFile ( const NetMessageRef & msg , const char * file_path , const char * mime_type_string = nullptr )
OasisNet.h
로컬 서버에서 파일 전송 요청에 대한 응답으로 파일을 원격 클라이언트에 백그라운드로 파일 데이터를 전송합니다. 파일 전송에 오류가 발생할 경우, 클라이언트에 오류 응답 코드를 전송합니다.
매개변수
msg  NetMessage 객체입니다.
file_path  파일 경로입니다.
mime_type_string  Content-Type 입니다.
리턴값
성공할 경우 0을 리턴하고, 실패할 경우 -1을 리턴합니다.

아래는 웹 서버에서 클라이언트로 부터 파일 전송 요청을 받았을 때 처리하는 예입니다. 오류 상황은 고려하지 않았습니다.

void MyHttpUpStreamDelegate::onRequest(const NetMessageRef &msg) 
{
  std::string url;
  netMessageUriGetPath(msg, url);

  NetMessageRef res = netMessageCreate(msg, false);

  std::string path = http_root_dir_path + url;
  if(access(path.c_str(), F_OK) == 0) {
    //get mime type based on extension
    const char *mime_type = get_file_mime_type(path.c_str());   
    if(mime_type == nullptr) {
      //not supported
      netMessageSetStatusCodeAndReasonString(res, 403, "Forbidden");
      netMessagePost(res);  
    } else {
      //파일을 전송합니다.
      netMessageSendFile(res, path.c_str(), mime_type);
    }
  } else {
    netMessageSetStatusCodeAndReasonString(res, 400, "Bad Request");
    netMessagePost(res);    
  }
}
int32_t netMessagePost ( const NetMessageRef & msg )
OasisNet.h
메세지를 전송합니다. 전송 마칠 때까지 기다리지 않고 바로 리턴을 하며, 오류가 발생할 경우, 인터페이스를 통하여 오류 이벤트가 전달됩니다.
매개변수
msg  NetMessage 객체입니다.
리턴값
  • 0: 성공
  • -1: 실패

예제

Oasis의 각 네트워크 컴포넌트 문서에 메세지 API를 이용한 예제들이 있습니다.

아래는 웹 클라이언트가 웹 서버로 부터 대용량 파일을 전송 받는 예, 웹 서버에 폼 데이터를 전송하는 예, 웹 서버에서 웹 클라이언트가 전송한 폼 데이터 파일을 저장하는 예 입니다.

웹 서버로 부터 대용량 파일 받기

웹 서버에 연결합니다.

const int32_t timeout = 60000; 
HttpConnectionRef conn = httpOpenConnection(
                           "https://example.com/data/firmware.img", 
                           timeout, 
                           "/tmp" /* 캐쉬 디렉토리 */
                           );

연결 객체로 부터 요청 메세지를 얻어와서 Method를 GET으로 설정 후 서버에 요청 메세지를 전송합니다.

NetMessageRef msg = httpConnectionGetRequestMessage(conn);
netMessageSetMethod(msg, "GET");
netMessagePost(msg);

서버로 부터 응답 헤더를 수신합니다. 일정 시간내에 응답이 없으면 실패한 것으로 간주합니다.

NetMessageRef res_msg;
wait_count = 0;
do {
  res_msg = httpConnectionGetResponseHeaderMessage(conn, 1000);
  wait_count++;
} while(res_msg == nullptr && continuing_ && wait_count*1000 < timeout);

if(res_msg == nullptr || !continuing_) {
  return -1;
}

응답 코드를 확인합니다. 200이 아닌 경우, 오류 응답으로 간주합니다.

std::string reason_string;
int32_t status_code = netMessageGetStatusCodeAndReasonString(res_msg, reason_string);
if(status_code != 200) {
  return -1;
}

응답 컨텐츠 길이를 확인합니다. 파일 길이가 유효하지 않으면 오류로 간주합니다.

ssize_t content_length = netMessageGetContentLength(res_msg);
if(content_length < 0) {
  return -1;
}

아래 루프를 통해서 완전히 파일 데이터를 수신 마칠 때 까지 확인합니다. 수신 도중 연결이 끊기거나 사용자가 중단할 경우, 오류로 간주합니다.

do {
  ssize_t current_length = netMessageGetCurrentContentLength(res_msg);
  if(current_length >= 0) {
    //현재 까지 수신된 데이터 길이를 확인할 수 있습니다.
  }
  usleep(1000000);
} while(netMessageIsConnected(res_msg) && netMessageIsContentReady(res_msg) == false && continuing_);

if(!netMessageIsContentReady(res_msg) || !continuing_) {
  return -1;
}

캐쉬 디렉토리(/tmp)에 저장된 파일 경로를 얻습니다.

std::string filepath;
netMessageGetContentFilePath(res_msg, filepath);

사용 후 파일을 삭제합니다.

unlink(filepath.c_str());

웹 서버에 폼 데이터 보내기

웹 서버에 연결합니다.

const int32_t timeout = 60000; 
HttpConnectionRef conn = httpOpenConnection(
                           "https://example.com/api/status/update", 
                           timeout;

연결 객체로 부터 요청 메세지를 얻어와서 Method를 POST으로 설정합니다.

NetMessageRef msg = httpConnectionGetRequestMessage(conn);
netMessageSetMethod(msg, "POST");

폼 필드 데이터를 설정하고, 전송합니다.

netMessageAddFieldToMultipartFormData(msg, "state", "idle");
// 파일 경로를 지정하여, 전송이 파일 데이터도 함께 보냅니다.
netMessageAddFileToMultipartFormData(msg, "image", file_name.c_str(), file_path_.c_str(), get_file_mime_type(file_path_.c_str()));
netMessagePost(msg);

서버로 부터 응답 헤더를 수신합니다. 일정 시간내에 응답이 없으면 실패한 것으로 간주합니다.

NetMessageRef res_msg;
wait_count = 0;
do {
  res_msg = httpConnectionGetResponseHeaderMessage(conn, 1000);
  wait_count++;
} while(res_msg == nullptr && continuing_ && wait_count*1000 < timeout);

if(res_msg == nullptr || !continuing_) {
  return -1;
}

응답 코드를 확인합니다. 200이 아닌 경우, 오류 응답으로 간주합니다.

std::string reason_string;
int32_t status_code = netMessageGetStatusCodeAndReasonString(res_msg, reason_string);
if(status_code != 200) {
  return -1;
}

응답 컨텐츠 길이를 확인하고, 응답 컨텐츠를 얻습니다. 보통 서버는 JSON 양식의 응답 데이터를 전송합니다. 메세지의 파일 길이가 유효하지 않으면 오류로 간주합니다.

ssize_t content_length = netMessageGetContentLength(res_msg);
if(content_length < 0) {
  return -1;
}
std::vector<char> res_content;
netMessageGetContent(res_msg, res_content);

응답 메세지를 처리합니다.

웹 서버에서 폼 데이터 파일 저장하기

웹 서버를 생성하고 시작합니다. 캐쉬 디렉토리를 지정하고, 캐쉬할 컨텐츠 타입에 multipart/form-data를 지정합니다.

예제에서 오류 상황은 고려하지 않았습니다.

parameters["port"] = std::to_string(http_port);
parameters["root-dir"] = "/var/www/htdocs";
parameters["content-length-max"] = std::to_string(200*1024*1024);
parameters["cache-dir"] = "/tmp";
parameters["cached-content-types"] = "multipart/form-data,multipart/mixed";

std::shared_ptr<MyHttpUpStreamDelegate> http_delegate = std::make_shared<MyHttpUpStreamDelegate>();

HttpServerRef http_server = oasis::createHttpServer(parameters, http_delegate);
oasis::startHttpServer(http_server);

웹 클라이언트가 폼 데이터의 "image" 파일 입력 필드에 지정한 파일을 웹 서버로 전송하면, 웹 서버는 캐쉬 폴더에 이 응답 메세지를 저장합니다.

웹 서버는 MyHttpUpStreamDelegate::onRequest 콜백 함수에서 웹 클라이언트가 업로드한 파일을 저장하고, JSON으로 응답 코드를 보냅니다.

virtual void MyHttpUpStreamDelegate::onRequest(const NetMessageRef &msg) {
  std::string url;
  netMessageUriGetPath(msg, url);

  if(url == "/api/status/update") {
    std::string content_type, filename;
    ssize_t size = netMessageGetFormDataFileData(msg, "image", content_type, filename, nullptr);
    if(size > 0) {
      char path[PATH_MAX];
      sprintf(path, "/tmp/%s", filename.c_str());
      ssize_t saved_size = netMessageSaveFormDataFileDataAs(msg, "image", path);
    }

    NetMessageRef res = netMessageCreate(msg, false);
    netMessageSetStatusCodeAndReasonString(res, 200, "OK");
    netMessageSetHeaderField(res, "Connection", "close");
    std::string json_string = R"({ "result":"OK" })";
    netMessageSetContent(res, "application/json", json_string.c_str(), json_string.length());
    netMessagePost(res);
  }
}