Классы для работы с HTTP(S) на C++

Написал кроссплатформенную библиотеку (набор классов) для работы с HTTP(S) на C++, используя последние концепции программирования. Пока что это, пожалуй, beta, так как тестировал я ее совсем мало.

Для сборки библиотеки потребуется собранный Boost (желательно версии 1.48 или выше). Если планируется включение функционала для работы с SSL (HTTPS), то потребуется еще собранная библиотека OpenSSL. Также в обязательном порядке требуется поддержка компилятором C++11. Сами заголовочные файлы библиотеки не включают ни заголовочные файлы boost, ни OpenSSL.

Для тех, кто захочет использовать библиотеку для написания чего-то жестоко многопоточного (конечно, спамеров, а что же еще подобное пишут с дохера потоками), учтите, что каждый запрос создает 1 дополнительный фоновый поток, т.е. количество потоков, используемых приложением, увеличивается вдвое. Такая особенность работы связана с тем, что в своем ядре библиотека использует boost::asio::io_service для контроля времени выполнения запроса (словом, внутри библиотеки всё происходит асинхронно).

Краткое описание возможностей класса:
[+] GET/POST/прочие запросы с использованием HTTP/1.0
[+] Поддержка HTTPS
[+] Поддержка multipart-POST запросов с возможностью загрузки произвольного количества файлов любого размера
[+] Автоматический менеджмент Cookies
[+] Автоматические переходы по Location-редиректам
[+] Поддержка скачивания больших файлов
[+] Поддержка HTTP/HTTPS/SOCKS5-прокси с авторизацией и без
[+] Возможность добавлять собственные HTTP-заголовки в запрос
[+] Поддержка автоматической обработки параметров (urlencode)
[+] Возможность задать таймаут на любой запрос
[+] Множество вспомогательных функций (urlencode, base64 и т.п.)

Классы потоконебезопасны, организация синхронизации должна производиться на вашей стороне в случае использования одного и того же экземпляра какого-либо класса в нескольких потоках сразу.

Далее я по пунктам приведу краткое описание возможностей библиотеки с примерами.

1. Простой пример HTTP GET-запроса.

Пара строк кода, чтобы совершить GET-запрос. Что может быть проще? Дальнейшие примеры не будут уступать этому по простоте.

На заметку. Метод simple_http::http_endpoint::from_string создает экземпляр класса http_endpoint, который разделяет переданную ему строку URL на следующие независимые элементы:
- HTTP/HTTPS
- HOST/IP address
- порт (если есть)
- URI (если есть)
- параметры запроса (если есть)

Если передать объект класса http_endpoint в метод get, то параметры будут переданы методом GET, а если в post, то, соответственно, методом POST.

2. Запросы с автоматическим менеджментом Cookies.
Для автоматического менеджмента Cookies существует класс cookie_manager.

Далее могут следовать любые HTTP(S)-запросы, кукисы для них будут автоматически сохраняться менеджером и подставляться, когда это необходимо. Класс менеджера Cookies позволяет получить действительные Cookies для заданного домена, пути и т.д. Также можно добавлять собственные Cookies, они будут использоваться при HTTP(S)-запросах.

Для отключения автоматического менеджмента Cookies используется функция remove_auto_cookie_manager.

Класс cookie_manager имеет множество методов, позволяющих получить определенные Cookies, добавить новые, удалить какие-то определенные или все сразу и т.д. Описание я приводить не буду, так как они имеют достаточно очевидные названия и прототипы.

3. Установка таймаута на запрос.
Для того, чтобы установить максимальное время, которое может выполняться запрос, используется функция set_query_timeout, которая принимает как аргумент максимальное значение времени в секундах. По умолчанию на каждый запрос отводится 60 секунд. Если при запросе используются прокси, то время их отклика включается в этот таймаут.

4. Использование http proxy/socks5 с авторизацией или без для запросов.
Для установки proxy для запросов используются следующие методы класса http_sync_connection:

address - строка адреса прокси (IP-адрес или имя хоста).
port - порт прокси
ptype - тип прокси: proxy_none - убрать прокси, proxy_http - HTTP-прокси, proxy_socks5 - SOCKS5-прокси.
login, password - логин и пароль прокси-сервера.

Позволяет очистить текущий прокси-сервер.

5. Использование автоматических переходов по редиректам.

Включает/отключает автоматические переходы по редиректам (Location). По умолчанию выключено.

Включает/отключает переходы по Location на другие домены (например, если встретится редирект с mail.ru на yandex.ru, то при выключенной опции он не будет произведен автоматически). По умолчанию включено.

Устанавливает максимальное количество автоматических переходов по редиректам. По умолчанию 10.

Данные функции позволяют получить информацию о последнем произведенном редиректе: домен, URI, строку адреса редиректа и порт соответственно.

Позволяет получить количество сделанных авторедиректов во время последнего HTTP(S)-запроса.

Если библиотека собрана без поддержки SSL, и в каком-либо ответе от сервера встречается редирект с HTTP на HTTPS, он произведен не будет, даже если включена опция автоматического перехода по редиректам.

6. Дополнительные заголовки запроса.
Для добавления/удаления дополнительных заголовков в запрос используются следующие функции:

Первая добавляет дополнительный заголовок с именем name и значением value.
Вторая удаляет дополнительный заголовок с именем name.
Третья удаляет все дополнительные заголовки.

7. User-agent.
Для установки заголовка User-agent есть удобная функция

Если ей передана пустая строка, заголовок User-agent отсылаться не будет.

8. Отправка запросов без использования http_endpoint.
Иногда может потребоваться отправка запросов без использования данного упрощающего класса (например, если требуется передать HTTP Referer или часть параметров методом GET, а другую часть - методом POST).

Класс http_sync_connection имеет следующие функции:

Первые две отправляют на сервер, соответственно, GET и POST запрос. Третья позволяет явно задать тип запроса (например, "GET", "POST", "HEAD").
uri - Service-URI
parameters - параметры, которые необходимо передать на сервер. Функция get передаст их методом GET, а post - методом POST.
cookies - cookie, которые необходимо добавить в запрос. Если включен автоматический менеджмент Cookies, эти кукисы будут добавлены к тем, которые отсылаются менеджером cookies.
referer - HTTP-Referer.

Три последние функции отличаются от первых трех только тем, что позволяют задать домен, порт, URI и параметры запроса с помощью класса http_endpoint.

9. Отправка файлов на сервер (Multipart POST-запросы).
Класс http_sync_connection поддерживает загрузку файлов на сервер с помощью multipart-запросов. Имеется три функции:

Их параметры аналогичны вышеописанным get, post, query. Первый вариант функции ничем не отличается от функции post за исключением того, что данные будут отсылаться multipart-запросом.

Второй вариант имеет дополнительные параметры:
multipart_file_parameter_name - имя прикрепляемого к запросу файла
file - сам файл (объект класса multipart_file).

Третий вариант позволяет прикрепить сразу несколько файлов к запросу. Для этого используется параметр files - список файлов с именами.

Три последние функции отличаются от первых трех только тем, что позволяют задать домен, порт, URI и параметры запроса с помощью класса http_endpoint.

Класс multipart_file объявлен в заголовочном файле multipart_file.h и позволяет задать файл либо по его пути (физический файл операционной системы), либо как буфер данных.

Пример загрузки файла на сервер:

10. Кеширование DNS-запросов.

Эта функция позволяет включить или отключить кеширование DNS-запросов. По умолчанию кеширование включено. Если вы делаете много запросов подряд на один и тот же сервер, и данная функция включена, определение IP-адреса хоста будет производиться только один раз при первом запросе.

11. Автоматическая обработка параметров запроса (urlencode).
По умолчанию данная возможность выключена. Для ее включения/отключения используется функция

Если данная функция включена, будет производиться автоматическая обработка (urlencode) параметров запросов HTTP(S).

12. Callback при загрузке контента.
Если вы скачиваете большой файл или общаетесь с очень медленным сервером, возможно, есть смысл настроить callback, который будет вызываться при загрузке содержимого страницы.

Данная функция позволяет установить коллбек, который будет вызываться в процессе загрузки контента с сервера.

Данная функция отключает callback на чтение данных.

Данная функция устанавливает, должно ли очищаться возвращаемое значение функций get, post, query, multipart_post при использовании коллбека. По умолчанию включено.

Данная функция позволяет установить минимальное количество байтов, которое должно быть принято с сервера до вызова коллбека. По умолчанию 1.

Данная функция позволяет настроить поведение коллбека. По умолчанию это get_everything, т.е. из сокета читается весь контент. Доступны также значения get_headers_only (будут считаны только заголовки) и get_body_only (будет считано только тело).

Сам коллбек должен представлять из себя функтор, возвращающий bool. Чтение данных из сокета будет продолжаться до тех пор, пока коллбек возвращает true.

Пример использования коллбека для скачивания большого файла (при этом оперативной памяти будет расходоваться совсем немного):

13. Вспомогательные функции.
Файл utils.h содержит объявления различных вспомогательных функций для перекодирования base64, urlencode и т.д.
Файл functions.h содержит объявления вспомогательных функций для работы с ответами HTTP.

14. Исключения
Файл http_error.h содержит объявление класса, используемого для возбуждения исключений, возникающих при работе классов simple_http. Все примеры приведены без обработки исключений, чтобы сосредоточиться на их сути. Вообще, все вызовы функций и методов классов неймспейса simple_http должны оборачиваться в обработчик исключений. Класс http_error позволяет получить как текст сообщения об ошибке, так и его код (они перечислены внутри класса).

15. Сборка с поддержкой SSL.
Для того, чтобы собрать библиотеку с поддержкой SSL (чтобы работали HTTPS-запросы), необходимо задать директиву препроцессора SSL_SUPPORT. Если поддержка SSL отключена, класс http_sync_connection будет бросать исключение при попытке произвести HTTPS-запрос.

Наконец, последний пример - авторизуемся на Форуме АНТИЧАТ и получаем количество новых приватных сообщений и общее их количество.

Вот и всё! Приведенной информации вполне достаточно, чтобы полноценно работать с библиотекой.

Выкладываю исходники библиотеки и последнего примера: simple_http.zip. В комплекте - файл солюшена и проектов Visual Studio 2010. Не забудьте прописать свои пути к boost'у и OpenSSL (если вам потребуется поддержка HTTPS).

UPD 06.05.2013 - поправлен недочет при парсинге cookies.

Классы для работы с HTTP(S) на C++: 93 комментария

  1. Спасибо за код, выглядит интересно. Но почему большинство функций статические? simple_http::http_endpoint::from_string и тд. И почему в примерах не юзаете неймспейсы? Повторяющегося кода было бы меньше.

    1. Статические функции в коде олько те, которые могут работать вне класса. Зачем добавлять функциональность внутрь класса, если она, по сути, не зависимая? Об этом еще Скотт Мейерс писал, кажется, да или посмотри на буст: boost::asio::ip::tcp::endpoint::from_string и подобные вызовы.

      В примерах на 5 строк юзать неймспейсы? Да и что подразумевается под использованием неймспейсов, написать строку "using namespace simple_http"? Я не сторонник разыменовывания всего подряд, тем более, что это может породить конфликты имен. Если много писать, лучше сделать укороченный алиас неймспейсу.

  2. А никто не может рассказать как включать его в свои проекты? Положил в include в VS, при компиляции выдает "error LNK2028: ссылка на неразрешенную лексему (0A000089) "public: class std::basic_string<char,struct std::char_traits..."

    1. Я же писал, что либа требует boost собранного, и сама тоже требует сборки.
      Если требуется поддержка ssl, то необходима еще и OpenSSL собранная.
      Пример включения в проект лежит в архиве.

  3. [+] Поддержка multipart-POST запросов с возможностью загрузки произвольного количества файлов любого размера

    Он вроде как загружает файлы в ОП перед отправкой, поэтому зависит от количества свободной ОП.

    Трудно читать код на C++ после Delphi, очень непривычно, что можете посоветовать?

  4. Где можно прочитать про стандарты C/C++, желательно на русском и какую IDE можете посоветовать кроме MS Visual Studio.

    1. Стандарт C++ - это обычный документ, который можно брать и читать. IDE - смотря под какую ОС. Visual Studio последних версий, имхо, одна из самых удобных.

  5. При попытки компиляции примера:

    error LNK2019: ссылка на неразрешенный внешний символ "public: __thiscall simple_http::http_sync_connection::http_sync_connection(void)" (??0http_sync_connection@simple_http@@QAE@XZ) в функции _main C:\Users\Denis\Downloads\Архивы\simple_http\examples\main.obj examples

    Пути к бусту указаны

  6. странно , буст скомпилил и собрал , да и примеры бустовые идут на ура , вот только почемуто при компиле отправки потс запроса (1 ый ваш пример) , выдаёт типа от что :
    1>c:\program files\microsoft visual studio 9.0\vc\include\simple_http\simple_http.h(110) : error C2039: function: не является членом "std"
    1>c:\program files\microsoft visual studio 9.0\vc\include\simple_http\simple_http.h(110) : error C2143: синтаксическая ошибка: отсутствие ";" перед "c:\program files\microsoft visual studio 9.0\vc\include\simple_http\simple_http.h(110) : error C4430: отсутствует спецификатор типа - предполагается int. Примечание. C++ не поддерживает int по умолчанию
    1>c:\program files\microsoft visual studio 9.0\vc\include\simple_http\simple_http.h(110) : error C2238: непредвиденные лексемы перед ";"
    В сём мб трабла ? Буст собран , SSL не нужен :)

    1. Можно закомментировать этот момент (если коллбеки не нужны), он компилируется только в студии 2010 и выше и в последних gcc. Это C++11.
      Ну или поставить новую студию)

  7. simple_http::http_sync_connection conn -На это он выдает:

    msvcprtd.lib(MSVCP100D.dll) : error LNK2005: "public: __thiscall std::_Lockit::~_Lockit(void)" (??1_Lockit@std@@QAE@XZ) already defined in libcpmtd.lib(xlock.obj)
    1>msvcprtd.lib(MSVCP100D.dll) : error LNK2005: "public: __thiscall std::_Lockit::_Lockit(int)" (??0_Lockit@std@@QAE@H@Z) already defined in libcpmtd.lib(xlock.obj)
    1>msvcprtd.lib(MSVCP100D.dll) : error LNK2005: "void __cdecl std::_Debug_message(wchar_t const *,wchar_t const *,unsigned int)" (?_Debug_message@std@@YAXPB_W0I@Z) already defined in libcpmtd.lib(stdthrow.obj)
    1>msvcprtd.lib(MSVCP100D.dll) : error LNK2005: "void __cdecl std::_Xout_of_range(char const *)" (?_Xout_of_range@std@@YAXPBD@Z) already defined in libcpmtd.lib(xthrow.obj)
    1>msvcprtd.lib(MSVCP100D.dll) : error LNK2005: "public: __thiscall std::_Container_base12::~_Container_base12(void)" (??1_Container_base12@std@@QAE@XZ) already defined in main.obj
    1>msvcprtd.lib(MSVCP100D.dll) : error LNK2005: "public: __thiscall std::_Container_base12::_Container_base12(void)" (??0_Container_base12@std@@QAE@XZ) already defined in main.obj
    1>msvcprtd.lib(MSVCP100D.dll) : error LNK2005: "public: void __thiscall std::_Container_base12::_Orphan_all(void)" (?_Orphan_all@_Container_base12@std@@QAEXXZ) already defined in main.obj
    1>msvcprtd.lib(MSVCP100D.dll) : error LNK2005: "void __cdecl std::_Xlength_error(char const *)" (?_Xlength_error@std@@YAXPBD@Z) already defined in libcpmtd.lib(xthrow.obj)
    1>msvcprtd.lib(MSVCP100D.dll) : error LNK2005: "public: struct std::_Iterator_base12 * * __thiscall std::_Container_base12::_Getpfirst(void)const " (?_Getpfirst@_Container_base12@std@@QBEPAPAU_Iterator_base12@2@XZ) already defined in simple_http.lib(simple_http.obj)
    1>msvcprtd.lib(MSVCP100D.dll) : error LNK2005: "public: static int __cdecl std::numeric_limits::max(void)" (?max@?$numeric_limits@H@std@@SAHXZ) already defined in simple_http.lib(simple_http_impl.obj)
    1>msvcprtd.lib(MSVCP100D.dll) : error LNK2005: "public: void __thiscall std::_Container_base12::_Swap_all(struct std::_Container_base12 &)" (?_Swap_all@_Container_base12@std@@QAEXAAU12@@Z) already defined in simple_http.lib(utils.obj)
    1>msvcprtd.lib(MSVCP100D.dll) : error LNK2005: "public: static unsigned int __cdecl std::numeric_limits::max(void)" (?max@?$numeric_limits@I@std@@SAIXZ) already defined in simple_http.lib(simple_http.obj)
    1>MSVCRTD.lib(MSVCR100D.dll) : error LNK2005: "public: __thiscall std::exception::exception(char const * const &)" (??0exception@std@@QAE@ABQBD@Z) already defined in LIBCMTD.lib(stdexcpt.obj)
    1>MSVCRTD.lib(MSVCR100D.dll) : error LNK2005: "public: virtual __thiscall std::exception::~exception(void)" (??1exception@std@@UAE@XZ) already defined in LIBCMTD.lib(stdexcpt.obj)
    1>MSVCRTD.lib(MSVCR100D.dll) : error LNK2005: "public: __thiscall std::exception::exception(class std::exception const &)" (??0exception@std@@QAE@ABV01@@Z) already defined in LIBCMTD.lib(stdexcpt.obj)
    1>MSVCRTD.lib(MSVCR100D.dll) : error LNK2005: __wassert already defined in LIBCMTD.lib(wassert.obj)
    1>MSVCRTD.lib(MSVCR100D.dll) : error LNK2005: _memmove already defined in LIBCMTD.lib(memmove.obj)
    1>MSVCRTD.lib(MSVCR100D.dll) : error LNK2005: _wcslen already defined in LIBCMTD.lib(wcslen.obj)
    1>MSVCRTD.lib(MSVCR100D.dll) : error LNK2005: __invalid_parameter already defined in LIBCMTD.lib(invarg.obj)
    1>MSVCRTD.lib(MSVCR100D.dll) : error LNK2005: __CrtDbgReportW already defined in LIBCMTD.lib(dbgrptw.obj)
    1>MSVCRTD.lib(MSVCR100D.dll) : error LNK2005: "public: bool __thiscall type_info::operator==(class type_info const &)const " (??8type_info@@QBE_NABV0@@Z) already defined in LIBCMTD.lib(typinfo.obj)
    1>MSVCRTD.lib(MSVCR100D.dll) : error LNK2005: _tolower already defined in LIBCMTD.lib(tolower.obj)
    1>MSVCRTD.lib(MSVCR100D.dll) : error LNK2005: _towlower already defined in LIBCMTD.lib(towlower.obj)
    1>MSVCRTD.lib(ti_inst.obj) : error LNK2005: "private: __thiscall type_info::type_info(class type_info const &)" (??0type_info@@AAE@ABV0@@Z) already defined in LIBCMTD.lib(typinfo.obj)
    1>MSVCRTD.lib(ti_inst.obj) : error LNK2005: "private: class type_info & __thiscall type_info::operator=(class type_info const &)" (??4type_info@@AAEAAV0@ABV0@@Z) already defined in LIBCMTD.lib(typinfo.obj)
    1>MSVCRTD.lib(MSVCR100D.dll) : error LNK2005: _strerror already defined in LIBCMTD.lib(strerror.obj)
    1>LINK : warning LNK4098: defaultlib 'MSVCRTD' conflicts with use of other libs; use /NODEFAULTLIB:library
    1>D:\example\simple_http (1)\Debug\examples.exe : fatal error LNK1169: one or more multiply defined symbols found

  8. И еще в примерах вызывается либа "libboost_regex-vc100-mt-sgd-1_48.lib" (например), а boost (v.1.48) собрал "libboost_regex-vc100-mt-gd-1_48.lib" может в этом дело?

    1. Собрать всё с одинаковыми рантаймами (например, статические отладочные или статические релизные), и все без проблем слинкуется.
      Примеры вообще никак не собраны и никакие либы там не вызываются. Надо ставить просто везде одинаковый параметр Code Generation в студии и собирать буст с теми же самыми настройками.

  9. СтраHHо , устаHовил 10 студию , буст поставвил (всe примэры бустовскиe компилятся Hа ура !!), одHако пи выполHeHии вышe описаHHого кода , вылазиeт :
    1>crea.obj : error LNK2019: ссылка на неразрешенный внешний символ "public: __thiscall simple_http::http_sync_connection::~http_sync_connection(void)" (??1http_sync_connection@simple_http@@QAE@XZ) в функции _main
    1>crea.obj : error LNK2019: ссылка на неразрешенный внешний символ "class std::basic_string<char,struct std::char_traits,class std::allocator > __cdecl simple_http::get_body(class std::basic_string<char,struct std::char_traits,class std::allocator > const &)" (?get_body@simple_http@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@ABV23@@Z) в функции _main
    1>crea.obj : error LNK2019: ссылка на неразрешенный внешний символ "public: class std::basic_string<char,struct std::char_traits,class std::allocator > __thiscall simple_http::http_sync_connection::get(class simple_http::http_endpoint const &,class std::basic_string<char,struct std::char_traits,class std::allocator > const &,class std::basic_string<char,struct std::char_traits,class std::allocator > const &)" (?get@http_sync_connection@simple_http@@QAE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@ABVhttp_endpoint@2@ABV34@1@Z) в функции _main
    1>crea.obj : error LNK2019: ссылка на неразрешенный внешний символ "public: static class simple_http::http_endpoint __cdecl simple_http::http_endpoint::from_string(class std::basic_string<char,struct std::char_traits,class std::allocator > const &)" (?from_string@http_endpoint@simple_http@@SA?AV12@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) в функции _main
    1>crea.obj : error LNK2019: ссылка на неразрешенный внешний символ "public: __thiscall simple_http::http_sync_connection::http_sync_connection(void)" (??0http_sync_connection@simple_http@@QAE@XZ) в функции _main
    В чём мб трабла ??

  10. П.с , КАими писал мол , Путь к lib-файлу либы то тоже надо указать.. Это как , и про какую лтбу ??Файлы из папки SТage буста , я указал ..

    1. Если ты собираешь пример работы с либой, то перед этим как бы надо и саму либу собрать, а потом в примере указать путь к ее lib-файлу.

  11. В отдельности в проекте работает и boost и openssl, но стоит добавить хотя бы "simple_http::http_sync_connection conn;" линкер выдает две ошибки!

    1>asd.obj : error LNK2019: unresolved external symbol "public: __thiscall simple_http::http_sync_connection::~http_sync_connection(void)" (??1http_sync_connection@simple_http@@QAE@XZ) referenced in function _main
    1>asd.obj : error LNK2019: unresolved external symbol "public: __thiscall simple_http::http_sync_connection::http_sync_connection(void)" (??0http_sync_connection@simple_http@@QAE@XZ) referenced in function _main

    если же пишем #pragma comment (lib, "simple_http.lib") то вообще беда...
    dx, выручайте))

    1. Именно #pragma comment (lib, "simple_http.lib") и надо написать, учтя, чтобы буст и либа были собраны с одинаковыми параметрами Code generation (рантаймы студии).

  12. Дык а как иё собрать ??Я так поHИмаю рeчь идёт о сборкe вашэй либы , а He бустовской ??Бустовая уж собраHа , я каHуч извиHяюсь за тупизHу , просто curl He качаицо ЫЫ

  13. А как узнать/ посмотреть с какими рантаймами был создан boost?
    собирал так:
    1.bootstrap.bat
    2.bjam.exe --toolset=msvc-10.0 --build-type=complete
    Его boost из студии надо собрать? или в проекте Вашей библиотеке рантаймы поменять проще будет и пере собрать?

    1. Советую собрать буст в двух вариантах:

      bjam variant=debug link=static threading=multi runtime-link=static
      bjam variant=release link=static threading=multi runtime-link=static

      (ну и тулсет указать, если их несколько, да)

      После этого ставить в проектах, в которых буст используется, параметр Code generation = MT для релизных сборок и MTd для отладочных.
      Библиотеку, соответственно, в студии с такими флагами и собирать.

  14. Собрал, флаги выставил. Все равно!
    1>asd.obj : error LNK2019: unresolved external symbol "public: __thiscall simple_http::http_sync_connection::~http_sync_connection(void)" (??1http_sync_connection@simple_http@@QAE@XZ) referenced in function _main
    1>asd.obj : error LNK2019: unresolved external symbol "public: __thiscall simple_http::http_sync_connection::http_sync_connection(void)" (??0http_sync_connection@simple_http@@QAE@XZ) referenced in function _main
    1>C:\Users\Администратор\Downloads\simple_http\Debug\asd.exe : fatal error LNK1120: 2 unresolved externals

  15. Собираю дебаг, тест тоже
    command line в simple_http:

    /I"C:\OpenSSL-Win32\include\openssl" /I"C:\OpenSSL-Win32\include" /ZI /nologo /W3 /WX- /Od /Oy- /D "SSL_SUPPORT" /D "_WIN32_WINNT=0x0501" /D "WIN32" /D "_DEBUG" /D "_LIB" /D "_UNICODE" /D "UNICODE" /Gm /EHsc /RTC1 /MTd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Fp"Debug\simple_http.pch" /Fa"Debug\" /Fo"Debug\" /Fd"Debug\vc100.pdb" /Gd /analyze- /errorReport:queue

    1. Это командная строка компилятора. Ошибки, которые ты написал, выводятся линкером. Покажи командную строку линкера.

  16. Подменю линкера в simple_http нет, есть подменю Librarian!Там командная строка
    /OUT:"C:\Users\Администратор\Downloads\simple_http\Debug\simple_http.lib" /NOLOGO

    1. Я говорю о сборке не либы, а твоего проекта, который либу использует блин. Туда надо подключить собранную мою либу.

      1. А я вот либу собрать не могу, выдает:
        boost_1_47_0\boost\asio\impl\read_until.hpp(881): error C2783: 'boost::asio::detail::read_until_expr_op boost::asio::detail::make_read_until_expr_op(AsyncReadStream &,boost::asio::basic_streambuf &,const boost::regex &,ReadHandler)' : could not deduce template argument for 'RegEx'

        \boost_1_47_0\boost\asio\impl\read_until.hpp(862) : see declaration of 'boost::asio::detail::make_read_until_expr_op'
        1> \desktop\simple_http\simple_http\simple_http_socket_worker.h(96) : see reference to function template instantiation 'void boost::asio::async_read_until,boost::_bi::bind_t>(AsyncReadStream &,boost::asio::basic_streambuf<> &,const boost::regex &,const ReadHandler &)' being compiled...

        ШОДЕЛАТЬ?!

  17. Кхм... извиняюсь конечно, но до сих пор не могу собрать все в кучу! Вот строка линкера проекта, где хочу использовать либу!
    /OUT:"D:\example\boost+openssl\Debug\boost+openssl.exe" /INCREMENTAL /NOLOGO "kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib" /MANIFEST /ManifestFile:"Debug\boost+openssl.exe.intermediate.manifest" /ALLOWISOLATION /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /PDB:"D:\example\boost+openssl\Debug\boost+openssl.pdb" /SUBSYSTEM:CONSOLE /PGD:"D:\example\boost+openssl\Debug\boost+openssl.pgd" /TLBID:1 /DYNAMICBASE /NXCOMPAT /MACHINE:X86 /ERRORREPORT:QUEUE
    Как правильно настроить линкер?

    1. Я тут не вижу линкования с simple_http.lib, собсна. Либо явно указать либу надо, либо прописать в исходнике проекта #pragma comment(lib, "simple_http")

    1. За это время можно было бы уже 100 раз разобраться. Если нет умения работать с бустом и вообще со студией - лучше за это дело даже не браться, прежде чем научишься что-то делать.

  18. Да я просто не понимаю почему не получается... simple_http::http_sync_connection conn именно с этим проблема!
    Менеджер куков свободно создается, буст работает! Может быть из за SSL? Хочу разобраться и понять, с Вашей помощью...

    1. Попробуй собрать из буста пример, работающий с SSL. Там есть вроде бы, в примерах для boost::asio.
      Да и ты же говоришь, у тебя там 80 ошибок появляется, если слинковаться с моей либой... Значит, не только в конструкторе проблема, еще что-то не так?

  19. Ошибки:
    MSVCRTD.lib(ti_inst.obj) \\ на эти либы линковщик ругается
    msvcprtd.lib(MSVCP100D.dll) \\ ошибкой errorLNK2005

    после чего выдает error LNK1169: one or more multiply defined symbols found

    Предупреждение:
    warning LNK4098: defaultlib 'MSVCRTD' conflicts with use of other libs; use /NODEFAULTLIB:library
    убирал эту либу- вообще беда)

    simple_http::http_sync_connection conn; -это не работает
    simple_http::cookie_manager manager;- это работает

    либу и проект собирал с SSL_SUPPORT

    1. Уже сто раз писал, что ты буст/мою библиотеку/проект примера собираешь с разными настройками рантаймов студии. Повторяю это в очередной раз.

  20. либкурл не требует никакого буста, уже собран, с минимальными затратами поддерживает потоки (правда когда его юзал последний раз там был глюк в библиотеке, связанный с указателями, сейчас ), создаёт всего один лишний поток, на всё (количество потоков = ваши потоки +1), есть неблокирующийся режим и тд.
    зачем изобретать велосипед?

    1. Дело в том, что если бы все имели такое мнение, как у тебя, то мы бы сейчас были лишены большого количества замечательных продуктов, а у тебя не было бы выбора, какие программы ставить на компьютер. Зачем было делать винамп, аимп и прочие плейеры, если есть виндовс медиа плеер, который тоже все играет? Ну и т.д.
      Немного по теме: либкурл - это сишная библиотека, и плюсовые биндинги надо, во-первых, еще найти/выбрать, а потом еще и собрать, так как они собранными точно не будут поставляться - плюсовое abi в каждом компиляторе сильно отличается, поэтому каждый собирает для себя.
      Не спорю, возможностей там больше, но это не значит, что не нужно делать никаких аналогов, свет клином на курле не сошелся.

  21. Здравствуйте, пытаюсь отправить фаил (точно так же как написано в примере) *.jpeg ругается:
    1>SendDATA_test_console.obj : error LNK2019: ссылка на неразрешенный внешний символ "public: __thiscall simple_http::http_sync_connection::~http_sync_connection(void)" (??1http_sync_connection@simple_http@@QAE@XZ) в функции _main
    1>SendDATA_test_console.obj : error LNK2019: ссылка на неразрешенный внешний символ "public: __thiscall simple_http::multipart_file::~multipart_file(void)" (??1multipart_file@simple_http@@QAE@XZ) в функции _main
    1>SendDATA_test_console.obj : error LNK2019: ссылка на неразрешенный внешний символ "public: class std::basic_string<char,struct std::char_traits,class std::allocator > __thiscall simple_http::http_sync_connection::multipart_post(class simple_http::http_endpoint const &,class std::basic_string<char,struct std::char_traits,class std::allocator > const &,class simple_http::multipart_file &,class std::basic_string<char,struct std::char_traits,class std::allocator > const &,class std::basic_string<char,struct std::char_traits,class std::allocator > const &)" (?multipart_post@http_sync_connection@simple_http@@QAE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@ABVhttp_endpoint@2@ABV34@AAVmultipart_file@2@11@Z) в функции _main
    1>SendDATA_test_console.obj : error LNK2019: ссылка на неразрешенный внешний символ "public: static class simple_http::http_endpoint __cdecl simple_http::http_endpoint::from_string(class std::basic_string<char,struct std::char_traits,class std::allocator > const &)" (?from_string@http_endpoint@simple_http@@SA?AV12@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) в функции _main
    1>SendDATA_test_console.obj : error LNK2019: ссылка на неразрешенный внешний символ "public: __thiscall simple_http::multipart_file::multipart_file(class std::basic_string<char,struct std::char_traits,class std::allocator > const &,class std::basic_string<char,struct std::char_traits,class std::allocator > const &)" (??0multipart_file@simple_http@@QAE@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@0@Z) в функции _main
    1>SendDATA_test_console.obj : error LNK2019: ссылка на неразрешенный внешний символ "public: __thiscall simple_http::http_sync_connection::http_sync_connection(void)" (??0http_sync_connection@simple_http@@QAE@XZ) в функции _main
    о чём это он? (VS10 C++)

    1. Не указали в списке библиотек для линковки саму либу для работы с HTTP, поэтому компилятор функции оттуда не может найти.

  22. где взять simple_http.lib ?
    та же ситуация с libeay32.lib и ssleay32.lib
    если их нужно как то собирать то подскажите как?
    simple_http.lib нужна для примера с передачей файла.

    1. simple_http.lib - это та библиотека, которая собирается из моих исходников, выложенных в этом посте. Ее просто нужно собрать в студии и потом линковаться с ней.
      libelay и ssleay нужны только в том случае, если необходима поддержка HTTPS, я писал об этом в посте. Их можно либо найти уже собранные где-нибудь в интернете, либо собрать самому из исходников OpenSSL.
      Если все это звучит слишком сложно, то, вероятно, есть смысл использовать CURL, он есть в уже собранных исполнениях наверняка.

      1. ок, вроде как разобрался (http://msdn.microsoft.com/ru-ru/library/ms235627%28v=vs.90%29.aspx была мне в помощь)
        я так понимаю, для примера с передачей файлов в состак библиотеки (создаваемой simple_http.lib) можно включать не весь проект.
        попробовал собрать с заголовочными simple_http.h, http_endpoint.h, multipart_file.h ну и их исходниками (*.cpp имею введу) и того 6 файлов. Библиотека собралась. подключил так: #pragma comment(lib, "simple_http.lib"). попытался скомпилировать ошибка не исчезла..
        Можете сказать какие конкретно файлы должны входить в состав библиотеки.
        Спасибо, за ранее.

        1. или подскажите, хотя бы какие файлы можно исключить дабы избежать подключения openssl. Ну или может что то в коде поправить..

        2. Нужно взять и собрать всю либу, в проекте уже есть все необходимые файлы же. Потом просто слинковаться, как Вы и пробовали. Если что-то не выходит, нужен текст ошибок из студии. Если OpenSSL не нужен, то собирайте мою библиотеку без директивы препроцессора SSL_SUPPORT. В посте есть такой текст, скопирую сюда, если не дочитали:

          15. Сборка с поддержкой SSL.
          Для того, чтобы собрать библиотеку с поддержкой SSL (чтобы работали HTTPS-запросы), необходимо задать директиву препроцессора SSL_SUPPORT. Если поддержка SSL отключена, класс http_sync_connection будет бросать исключение при попытке произвести HTTPS-запрос.

  23. Если использовать сокс5, то при задании адреса через std::string (а не simple_http::http_endpoint) дял get/post - в прокси доходит ":80" т.е. вместо хоста имеем пустую строку.

  24. Большое спасибо, очень удобная библиотека. Вот только не получается отправить post запрос на авторизацию к mail.ru (SSL handshake error). Отладчик показал, что не парсятся куки... В чём может быть проблема? Заранее благодарен. (Брал код из примера, с античатом всё работает)

    1. Не исключено, что баги в библиотеке есть. Хотелось бы небольшой пример кода увидеть, который не работает. Вообще, ssl handshake error говорит о том, что не удалось связаться с сервером по каким-то причинам, связанным с SSL сертификатом (т.е. не удалось получить ключи для шифрования, или что-то в этом роде).

      1. Спасибо за оперативный ответ. SSL заработал. Это был мой косяк, надо было сразу отправлять пост на https, чтобы включилась поддержка SSL.(Приношу свои извинения за преждевременную панику =D) Но вот с куками по прежнему беда, куки парсятся, но не все. Прикладываю скриншот http://saveimg.ru/show-image.php?id=b05e9eeaa5ae86702ff62e5d081e06c3

        1. Думаю, что проблема возникает при парсинге параметра expires в куках. Из-за невозможности распарсить этот параметр куки не добавляются в менеджер.

        2. Дошли руки до правки багов. Действительно, регулярное выражение для парсинга даты кукисов не совсем корректное было, поправил. По идее, теперь должно сработать, можно перекачать архив с исходниками.

  25. Здравствуйте! А как решить проблему с многопоточностью? Хочу написать многопоточный брутфорс, не подскажите как решить мою задачу?

  26. Здравствуйте, какая-то ошибка в куки менеджере, при запросе отправляется только первая кука

    1. Библиотекой почти никто не пользуется, так что не исключено, что там есть ошибки. Постараюсь посмотреть в ближайшие дни, как появится время.

  27. Здравствуйте, ошибки не было, просто оказалось что сайт часть куков передаёт для домена с http://www., а часть без него, это я поправил в куки мэнеджере храня все куки без www. Но я немного не понял как отправлять post запрос, когда имеются и GET параметры, они автоматом в POST уходят, хотя это не требуется

    1. Не уверен, что cookies для сайта с www могут быть валидны для сайта без www и наоборот (скорее всего нет). Нужно смотреть.

      Отправить POST с дополнительными GET-параметрами можно так:
      std::cout << conn.query("POST", "http://localhost/simple.php?c=3&d=4", "a=1&b=2"); //"c" и "d" уйдут в GET, "a" и "b" - в POST

  28. Всё-таки есть ошибка с куками есть, но не в менеджере, например, при авторизации на яндексе из 7 кук, в куки менеджер поступает только 5, хотя формат оставшихся 2-ух такой же.

  29. И еще ошибку нашёл: при запросе по ssl, если включен авторедирект, то при редиректе он почему-то делает запрос на 80-ый порт

    1. Эта ошибка вроде бы действительно есть, поправлю. С кукисами еще посмотрю. Неплохо бы пример кода, который работает не так, как должен.

  30. И еще если можно, то добавить вывод последнего запроса (как респонс выводится, так же и реквест перед нем)

Добавить комментарий для Bo0oM Отменить ответ

Ваш адрес email не будет опубликован. Обязательные поля помечены *