LINUX.ORG.RU

Помогите перенести код HTTP API с Win на Linux curllib


0

0

Привет всем!

Занимаюсь переносом с Win класса, который занимается посылкой запросов HTTP GET/POST на сервер с помощью WinInet HTTP API, на Linux с помощью curllib. Надеюсь, модераторы пожалеют и не удалят сообщение, хотя оно и не очень связано с Linux - просто я уверена, что здесь есть люди, которые занимались этой библиотекой в Linux. Использую easy interface.

1. В HTTP API можно использовать ::GetLastError() для получения ошибки. Можно ли в curllib просто получить код последней ошибки или там такого нет? Видела, что есть опция для curl_easy_setopt CURLOPT_ERRORBUFFER - можно задать буффер для приема сообщения об ошибке. А можно ли просто получить код?

2. Есть ли аналог InternetOpen? Я так понимаю, что инициализация либы - это просто вызов curl_easy_init - Start a libcurl easy session

он же инициализирует сессию?

Просто в HTTP API делается 2 вызова (взято из MSDN): InternetOpen - Initializes an application's use of the WinINet functions.

InternetConnect - Opens an File Transfer Protocol (FTP), Gopher, or HTTP session for a given site.

Кстати, в последнем вызове задается еще и адрес сервера.

Вообщем, правильно ли я понимаю, что в curllib эти 2 вызова сводятся к curl_easy_init, а, куда коннектиться, указывается потом через опции, скажем, CURLOPT_URL?

3. Правильно ли я понимаю, что CURLOPT_PROXYUSERPWD == INTERNET_OPTION_PROXY_USERNAME + INTERNET_OPTION_PROXY_PASSWORD ? (это опции curl_easy_setopt/InternetSetOption)

INTERNET_OPTION_PROXY_USERNAME - Sets or retrieves a string value that contains the user name used to access the proxy.

INTERNET_OPTION_PROXY_PASSWORD - Sets or retrieves a string value that contains the password used to access the proxy.

4. Нужны аналоги опций HTTP API: INTERNET_OPTION_CONNECT_TIMEOUT - Sets or retrieves an unsigned long integer value that contains the time-out value, in milliseconds, to use for Internet connection requests. If a connection request takes longer than this time-out value, the request is canceled. When attempting to connect to multiple IP addresses for a single host (a multihome host), the timeout limit is cumulative for all of the IP addresses.

INTERNET_OPTION_RECEIVE_TIMEOUT - Sets or retrieves an unsigned long integer value that contains the time-out value, in milliseconds, to receive a response to a request. If the response takes longer than this time-out value, the request is canceled.

INTERNET_OPTION_SEND_TIMEOUT - Sets or retrieves an unsigned long integer value that contains the time-out value to send a request. Units are in milliseconds. If the send takes longer than this time-out value, the send is canceled.

Я нашла только эти: CURLOPT_TIMEOUT (CURLOPT_TIMEOUT_MS)

Pass a long as parameter containing the maximum time in seconds that you allow the libcurl transfer operation to take. Normally, name lookups can take a considerable time and limiting operations to less than a few minutes risk aborting perfectly normal operations. This option will cause curl to use the SIGALRM to enable time-outing system calls.

In unix-like systems, this might cause signals to be used unless CURLOPT_NOSIGNAL is set.

CURLOPT_CONNECTTIMEOUT (CURLOPT_CONNECTTIMEOUT_MS)

Pass a long. It should contain the maximum time in seconds that you allow the connection to the server to take. This only limits the connection phase, once it has connected, this option is of no more use. Set to zero to disable connection timeout (it will then only timeout on the system's internal timeouts). See also the CURLOPT_TIMEOUT option.

In unix-like systems, this might cause signals to be used unless CURLOPT_NOSIGNAL is set.

Не очень понятно, чему соответствует CURLOPT_TIMEOUT? Это все время запроса, т. е. отправка + получение?

Вообщем, непонятно, как задать в curllib INTERNET_OPTION_RECEIVE_TIMEOUT + INTERNET_OPTION_SEND_TIMEOUT.

5. Есть ли аналог HttpOpenRequest + HttpSendRequest? Правильно я понимаю, что нужно просто сделать curl_easy_perform с предварительной установкой нужных опций через curl_easy_setopt?

6. Как в curllib разруливаются ситуации, когда хост, с которого посылаются запросы, будет иметь, скажем, 5 ip адресов, например, но нужно будет отправлять запросы с определенного адреса?


Это еще не все вопросы...

7. Есть ли в curl lib аналог вызова HTTP API HttpQueryInfoA(m_hRequest, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, &dwData, &dwDataLength, &dwIndex);? Вызов получает HTTP_QUERY_CONTENT_LENGTH - Retrieves the size of the resource, in bytes.

Использовать curl_easy_getinfo, CURLINFO_CONTENT_LENGTH_DOWNLOAD?

8. Есть ли аналоги вызовов:

HttpQueryInfoA(m_hRequest, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &dwData, &dwDataLength, &dwIndex);

HTTP_QUERY_STATUS_CODE - Receives the status code returned by the server.

Использовать curl_easy_getinfo, CURLINFO_RESPONSE_CODE?

9. Есть ли аналог InternetReadFile (из MSDN)

InternetReadFile

Reads data from a handle opened by the InternetOpenUrl, FtpOpenFile, GopherOpenFile, or HttpOpenRequest function.

BOOL InternetReadFile( HINTERNET hFile, LPVOID lpBuffer, DWORD dwNumberOfBytesToRead, LPDWORD lpdwNumberOfBytesRead );

Parameters

hFile [in] Handle returned from a previous call to InternetOpenUrl, FtpOpenFile, GopherOpenFile, or HttpOpenRequest.

lpBuffer [out] Pointer to a buffer that receives the data.

dwNumberOfBytesToRead [in] Number of bytes to be read.

lpdwNumberOfBytesRead [out] Pointer to a variable that receives the number of bytes read. InternetReadFile sets this value to zero before doing any work or error checking.

Правильно ли я понимаю, что нужно задать std::string buffer; curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writer); // writer - некая функция записи

curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer); А потом сделать curl_easy_perform?

И потом просто возвращать buffer?

Кстати, во всех примерах, которые я видела, используется для буфера std::string, а в HTTP API используется LPVOID lpBuffer? Можно ли действительно использовать std::string для получения содержимого запроса? Насколько это безопасно? Напоминаю - у меня задача простая - просто сделать GET/POST запросы по определенному URL.

bool CHttp::Get(LPCSTR lpszURL) { return SendRequest("GET",lpszURL,NULL); }

bool CHttp::Post(LPCSTR lpszURL,CRLStream* pOptionalData) { return SendRequest("POST",lpszURL,pOptionalData); }

10. Есть ли аналоги следующих параметров: INTERNET_FLAG_NO_CACHE_WRITE - Does not add the returned entity to the cache, т. е. запрос не кэшируется.

INTERNET_FLAG_PRAGMA_NOCACHE - Forces the request to be resolved by the origin server, even if a cached copy exists on the proxy.

INTERNET_FLAG_NO_COOKIES - Does not automatically add cookie headers to requests, and does not automatically add returned cookies to the cookie database.

Может, можно задать опцию CURLOPT_COOKIE с NULL, и тогда не будут писаться куки? Или просто не надо вообще его задавать?

INTERNET_FLAG_SECURE - Uses secure transaction semantics. This translates to using Secure Sockets Layer/Private Communications Technology (SSL/PCT) and is only meaningful in HTTP requests.

Использвать CURLOPT_SSL_VERIFYHOST с параметром 2?

INTERNET_FLAG_IGNORE_CERT_CN_INVALID - Disables checking of SSL/PCT-based certificates that are returned from the server against the host name given in the request. WinINet functions use a simple check against certificates by comparing for matching host names and simple wildcarding rules.

?

Это флаги для HttpOpenRequest

11. Обязательно ли задавать CURLOPT_USERAGENT и что будет, если не задать его при запросах GET/POST?

В примере, который я нашла, задается

curl_easy_setopt(curl, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)");

А у меня в Win Inet нигде нет никаких упоминаний о user agent.

12. Как добавить header к запросу (есть строка, содержащая, скажем, "Content-Type: application/x-www-form-urlencoded\r\n")?

Правильно я понимаю, что надо юзать CURLOPT_WRITEHEADER?

Вообщем, буду признательна за помощь. Могла что-то не найти поиском по справке - сорри, если что...

XJess
() автор топика

Прочитай-таки внимательно доку по curl-у, лень ее пересказывать и лень вникать в виндовый апи на эту же тему. Дока простая, примеры есть (не простой разве что параллельный фетчинг нескольких урлов, который тебе не нужен).

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от XJess

> 11. Обязательно ли задавать CURLOPT_USERAGENT и что будет, если не задать его при запросах GET/POST?

Если не задать -- будет дефолтный. А вообще лучше не только задавать, а ещё и вписывать туда версию программы, платформу и т. д. Так проще будет отслеживать на сервере запросы и заблокировать "неправильные" версии или прикручивать к ним костыли в случае чего.

bvvv
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.