HTTP POST - вернуть бинарный объект
От: PPA Россия http://flylinkdc.blogspot.com/
Дата: 07.02.13 05:19
Оценка:
Привет.

Подскажите кто хорошо разбирается в стандартах и 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
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.