Привет.
Подскажите кто хорошо разбирается в стандартах и http.
я ведь могу вернуть на клиент произвольный бинарный объект даже если он внутри содержит двоичные 0x00?
Ситуация у меня такая
1. Есть маленький сервер на базе mongoose с обработкой логики в callback
2. Сервер по POST запросу возвращает json с размером 10-100К
3. Клиент на wininet нормально принимает этот ответ и парсит.
Хотел сократить расходы трафика и перед отправкой сжимать возвращаемый пакет json через zlib .
Формировать полноценный gzip пока не хочется т.к. там лишний расчет контрольной суммы и добавление заголовков и суффиксов...
Делаю тестовый json пакет размером 12к сжимается до 1403 байта.
отправляю вот таким кодом
const int l_result_mg_printf = mg_printf_dynamic(conn, l_http_len + 200, "HTTP/1.0 200 OK\r\n"
"Content-Length: %u\r\n"
"Content-Type: application/json\r\n"
"\r\n"
"%s",
l_http_len,
l_is_gzip ? "Content-Encoding: zlib\r\n" : ""
);
// Докидываем второй командой данные (TODO - Склеить все в одну)
const int l_result_mg_write = mg_write(conn,l_is_gzip ? reinterpret_cast<const char*>(l_dest_data.data()) : l_res_stat.c_str(), l_http_len);
#ifdef _DEBUG
std::cout << "[DEBUG] l_result_mg_write = " << l_result_mg_write<< " l_http_len = " << l_http_len <<" l_result_mg_printf = " << l_result_mg_printf << std::endl;
#endif
но на клиент под отладкой приходит на 1375 байт и естественно не раскрывается через вызов uncompress
при этом ответ приходит в два шага
1. На первой итерации InternetQueryDataAvailable читает мелкий блок в который попадает строка "Content-Encoding: zlib"
2. На второй уже сам бинарный блок но немного короче
Подскажите в чем ошибка?
код клиента:
CFlyLog l_fly_server_log("[fly-server POST-query]");
std::string l_data;
static char l_hdrs[] = "Content-Type: application/x-www-form-urlencoded";
static LPCSTR l_accept[2] = {"*/*", NULL};
if(HINTERNET hSession = InternetOpenA(l_user_agent.c_str(),INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0))
{
const CServerItem l_Server = CFlyServerConfig::getRandomMirrorServer(p_is_fly_set_query);
if(HINTERNET hConnect = InternetConnectA(hSession, l_Server.first.c_str(),l_Server.second, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 1))
{
if(HINTERNET hRequest = HttpOpenRequestA(hConnect, "POST", p_is_fly_set_query ? "fly-set" : "fly-get", NULL, NULL, l_accept, 0, 1))
{
if(HttpSendRequestA(hRequest, l_hdrs, strlen(l_hdrs), (LPVOID) l_outputConfig.data(), l_outputConfig.length()))
{
DWORD dwBytesAvailable = 0;
std::vector<char> l_zlib_blob;
int l_count_pass = 0;
while (InternetQueryDataAvailable(hRequest, &dwBytesAvailable, 0, 0))
{
if(dwBytesAvailable == 0)
break;
#ifdef _DEBUG
l_fly_server_log.step(" InternetQueryDataAvailable! dwBytesAvailable = " + Util::toString(dwBytesAvailable));
#endif
std::vector<unsigned char> pMessageBody(dwBytesAvailable+1);
DWORD dwBytesRead = 0;
const BOOL bResult = InternetReadFile(hRequest, pMessageBody.data(),dwBytesAvailable, &dwBytesRead);
if (!bResult)
{
l_fly_server_log.step("InternetReadFile error " + Util::translateError(GetLastError()));
break;
}
if (dwBytesRead == 0)
break;
pMessageBody[dwBytesRead] = 0;
if(l_count_pass)
{
const int l_cur_size = l_zlib_blob.size();
l_zlib_blob.resize(l_zlib_blob.size() + dwBytesRead);
memcpy(l_zlib_blob.data() + l_cur_size, pMessageBody.data(), dwBytesRead);
}
++l_count_pass;
}
unsigned long l_decompress_size = l_zlib_blob.size() * 100;
std::vector<unsigned char> l_decompress(l_decompress_size); // TODO расширять динамически
int l_un_compress_result = uncompress(l_decompress.data(), &l_decompress_size, (uint8_t*)l_zlib_blob.data(), l_zlib_blob.size());
if (l_un_compress_result == Z_OK)
{
l_result_query = (const char*) l_decompress.data();
}
#ifdef _DEBUG
l_fly_server_log.step(" InternetReadFile Ok! size = " + Util::toString(l_result_query.size()));
#endif
}
else
l_fly_server_log.step("HttpSendRequest error " + Util::translateError(GetLastError()));
InternetCloseHandle(hRequest);
}
else
l_fly_server_log.step("HttpOpenRequest error " + Util::translateError(GetLastError()));
InternetCloseHandle(hConnect);
}
else
l_fly_server_log.step("InternetConnect error " + Util::translateError(GetLastError()));
InternetCloseHandle(hSession);
}
else
l_fly_server_log.step("InternetOpen error " + Util::translateError(GetLastError()));
// close any valid internet-handles