Покинул форум
Сообщений всего: 4574
Дата рег-ции: Июль 2006 Откуда: Israel
Помог: 3 раз(а)
libcurl для обменна данных
libcurl это библиотека функций, которая позволяет взаимодействовать (обмениваться информацией) с различными серверами по различным протоколам. В настоящее время libcurl поддерживает протоколы http, https, ftp, gopher, telnet, dict, file, и ldap. libcurl также умеет работать с сертификатами HTTPS, посылать запросы к HTTP серверам методами POST и PUT, закачивать файлы по протоколам HTTP и FTP (последнее можно сделать также используя модуль FTP), использовать прокси-серверы, cookies и аутентификацию пользователей.
Нас поймут только по протоколу
Любые сервера, в том числе и web, умеют реагировать на присланные им данные т, но только в том случае, если они понимают, что им прислали. Для этого, данные посылаемые им оформляются согласно определенным правилам. Такой набор правил и называется протоколом. Данные по протоколу оформит libcurl сама, мы же лишь рассмотрим далее как их ей передать.
Раз, два, начали.
Функций в библиотеке совсем не много, но одну из них, приводящую шестеренки в действие, вы встретите в любом скрипте с curl. curl_init — Инициализирует сеанс CURL
Другими словами - эта функция запускает механизм curl и возвращает указатель, дескриптор на созданный механизм.
Напомню что такое ресурс (указатель), тем кто забыл.
Дескриптор ( Resource )
Дескриптор представляет из себя указатель, ссылку, на внешний ресурс.
Представим автосервис с большим количеством машин, которым заливают несколько по литров масла в двигатель. Со свистом тормозов из подворотни вылетает феррари и паркуется на очередной сервисной парковке. Хозяин сервиса уже кричит рабочему, залить 5 литров масла и тычет большим пальцем в красную феррари.
Наш рабочий получает в данном случае два типа данных - число (литров масла) и указатель на машину, то-есть определение - какому именно объекту из всех вокруг нужно подлить чего-нибудь.
Подмечу, что рабочий получает от босса вовсе не саму машину, а лишь дескриптор (указатель) машины с которой предстоит работать. В php этим дескриптором является тип данных resource.
Функция curl_init также может сразу принимать url, адрес того сервера с которым будем общаться. Можно его и не указывать, а указать попозже. Инициализировав механизм, можно сразу отправить запрос, ну и наконец освободить память от этого механизма.
Вот что в итоге получится:
результатом этого кода будет прямой вывод содержимого главной страницы php.su. Не всегда нужно вывести результат запроса прямо в браузер и для этого достаточно просто покрутить пару настроек. Сейчас выясним как это сделать.
Конфигурируем общение
curl_setopt — Устанавливает параметр для сеанса CURL
параметры бывают разные, и их много, очень. Какой за что отвечает можно посмотреть, само собой, в справочнике функции curl_setopt. Мы же сейчас рассмотрим парочку основных и выясним как ими манипулировать.
Но прежде я хочу вернуться на момент к обсуждению протокола http. Из чего же состоит набор правил этого протокола. Давай посмотрим как браузер общается с нашим сервером, что он ему посылает, и что тот от него получает. Я для этого использую расширение браузера livehttpheaders. И вот, что происходит при общении браузера с сервером:
Общение браузера с сервером получилось не слишком замысловатое. Смотрим:
GET /index.php HTTP/1.1 Дай страницу index.php. данные пришли правильно оформленные Host: php.su с сайта php.su User-Agent: Mozilla/5.0 А вот такой вот! Accept: text/html И понимаю я только текст и html. Accept-Language: ru,en-us; И говори по русски или я твоя не понимать Accept-Charset: windows-1251,utf-8; Со специями пожалуйста. Connection: keep-alive Жду от тебя ответа Keep-Alive: 300 но терпения у меня мало. Cookie: lastvisit=1243232518; А еще я заходил вчера и заказывал столик. Помнишь меня ? Нет? ну не важно, ты просил напомнить что я заходил во столько то. Теперь вспомнил? Отлично. Где мой столик ?
HTTP/1.1 200 OK Данные принял, состояние 200. Date: Mon, 25 May 2009 06:33:05 GMT Server: Apache Вас обслуживает ООО "Сервер Apache" X-Powered-By: PHP/5.2.6 Старший шеф повар, php 5.2.6 Transfer-Encoding: chunked Это порция первая, вторая ща будет Connection: close А теперь получил?, распишись, больше не жди Content-Type: text/html; charset=cp1251 Ваша пицаа по русски, с грибами
Сразу после заголовков ответа идёт сам ответ, тоесть html страницы. А мы, тем временем, что стали свидетелями общения моего браузера с сервером php.su. А раз браузер может, то и мы с нашей программой можем.
мы увидели в браузере только html код полученный от сервера. Возможно нам захочется также посмотреть на заголовки, который прислал сервер, а то вдруг я все выше написанное выдумал ?
Для этого установим опцию "показывать заголовки" CURLOPT_HEADER : При установке этого параметра в ненулевое значение результат будет включать полученные заголовки.
Разумеется параметры устанавливать нужно до того, как отправим сам запрос серверу. И так, получилось вот такое:
Возможно нам также захочется получит содержимое в переменную, а вовсе не выводить сразу в браузер. Для этого нам придется установить такое значение среди прочих командой: curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
Хотя документация видимо ошибается в плане настроек..
Позволю себе заметить, что в документации написано что названием параметра должна быть строка. Мы же передаем функции setopt вовсе не строку (кавычек то нет). Мы передаем константу. Предопределенную переменную, значение которой изменить нельзя. Эти константы сами определяются библиотекой. интересно другое.. значения этих констант вовсе не строковые, а численные. Поэтому если кто-то узнает почему в документации написано "строка" вместо числа - дайте мне знать.
А мы пока попробуем авторизоваться на форуме. А для того, чтобы имитировать обычный браузер, нам нужно посмотреть что говорит браузер серверу, что тот ему отвечает и что потом.
Строим из себя пользователя
В первую очередь, чтоб все это показалось правдоподобным, посмотрим что происходит когда мой браузер авторизовывается на форуме. Для этого я опять же воспользуюсь расширением для FireFox под названием liveHttpHeaders и вот что я вижу.
Запрос отличается от предыдущего лишь немногим. рассмотрим разницу.
POST /forum/loginout.php HTTP/1.1 На этот раз мы не просто просим дать нам содержимое страницы, но отправляем серверу свои данные. Referer: http://php.su/forum/loginout.php Откуда мы шлем данные (на какой страницы только что был браузер) Content-Type: application/x-www-form-urlencoded тип данных (данные из формы) Content-Length: 71 длинна посылаемых данных. action=login&imembername=valenok&ipassword=ne_skaju&submit=%C2%F5%EE%E4 ну и сами данные.. Заметь что отправляются все данные из формы.
А вот ответ немного отличается от предыдущего. В нем появляются новые заголовки. В первую очередь нас интересуют Set-Cookie и Location. Остальные особой роли не играют и что они означают можно найти в википедии.
Set-Cookie как ты видишь, и их много, возможно тебе уже знаком. Задача данного заголовка это наклеить на тебя наклейку с именем, чтобы потом сервер мог тебя по нему узнать и сказать, ах, да, точно, это ты. Разумеется для этого при каждом следующем обращении к серверу нужно будет приходить с этой наклейкой.
Location: index.php перенаправляет браузер на другую страницу, после авторизации.
Ну что, теперь попробуем сыграть за браузер ?
----- Truly yours, Sasha.
valenok
Отправлено: 26 Мая, 2009 - 19:47:13
Здесь могла бы быть ваша реклама
Покинул форум
Сообщений всего: 4574
Дата рег-ции: Июль 2006 Откуда: Israel
Помог: 3 раз(а)
Я тоже браузер
Будем анализировать на практике. Код получился следующий.
Какой параметр за что отвечает я показал в коде. Если что-то не до конца ясно, всегда можно посмотреть в документации. Тем не менее, двумя словами опишу параметры cookiejar и cookiefile.
Когда сервер выдает нам куки, тоесть наклейку - Ты такой-то, он потом смотрит на эту наклейку и вспоминает тебя. Но нам для этого разумеется нужно обращаться к серверу когда наклейка у нас висит на видном месте. libcurl может за нас сохранять наклейку в файл, если мы его укажем в параметре cookiejar и также посылать куки, тоесть обращаться вместе с наклейкой, если мы укажем файл в котором эту наклейку мы сохранили cookiefile. А так как нужно было для авторизации чтоб сервер запомнил что мы, это мы при следующем обращение, то на самом деле нужно было просто получить при авторизации куки. Поэтому вот как мы это сделаем.
Здесь я сократил несколько этапов. Причиной стало то, что сервер на самом деле не проверяет откуда пришли данные авторизации, поэтомум реферер указывать не имеет смысла. Какой браузер авторизовывается - ему тоже все равно. Уберем.
Заголовки о том, что мы хотим получить в ответ - тоже отправлять не будем. В ответ же мы все равно получим куки и перенаправление. Кроме того почти ни один программист все равно эти заголовки не учитывает. Они как бараны решили что знают как правильно и что нужно пользователю - и все тут.
Также установлен параметр - без тела (nobody) который говорит что весь html нам не нужен, нужны только заголовки. На самом деле его там и нет, но это только в нашем случае. На самом деле скрипт может и проводить авторизацию и ругаться в одном флаконе.
Присвоение результата в переменную я тоже убрал. Зачем нам в памяти результат запроса.. Мы и так знаем что он успешен. Но если не знаем, можно для примера проверять на наличие перенаправления Location:index.php и на основании этого решать, правильно ли авторизовались или нет. Но ничего ли мы не забыли ?
Пара рекомендаций
На самом деле все что бы могло тебе потребоваться - мы уже прошли. Ты умеешь уже авторизоваться где нибудь, отправить форму (пост данные) средствами библиотеки curl при этом выдавать себя за другой браузер. И напоминать серверу кто ты - с прошлого раза при помощи кук.
Я же лишь скажу что иногда тебе вовсе не нужна страница, а лишь её заголовки, как в нашем примере авторизации. Еще не нужно для каждого запроса создавать в памяти экземпляр механизма curl. Один раз его инициализируем, потом просто меняем параметры и адрес url. Думаю этого вполне хватит для успешного обмена данным с другими сайтами по началу, ну а если не хватит, то можно рассмотреть несколько сложных случаев далее.
----- Truly yours, Sasha.
valenok
Отправлено: 26 Мая, 2009 - 23:17:48
Здесь могла бы быть ваша реклама
Покинул форум
Сообщений всего: 4574
Дата рег-ции: Июль 2006 Откуда: Israel
Помог: 3 раз(а)
Несколько параллельных запросов и curl_multi_init
Если бы нам нужно было бы получить допустим содержания трех страниц, то наверное мы бы отправили запрос сначала на одну, получили результат, отправили на вторую и потом только на третью. Но вот чудо - эта библиотека позволяет отправить запрос сразу в 3 источника параллельно, при этом затратить на все это дело столько же времени сколько на один запрос.
Для следующего кода примеры данных $data могут быть следующими:
вроде все просто, как в примере
но результат ..никакой
браузер задумывается секунд на 20 ... и все - ничего не происходит !
а должен был загрузить страницу и отобразить, насколько я понимаю?
Delovoy
Отправлено: 10 Января, 2011 - 15:24:53
Новичок
Покинул форум
Сообщений всего: 63
Дата рег-ции: Нояб. 2010
Помог: 0 раз(а)
А вопросы установки cURL в этой теме рассматриваются ?
может дело не в самом коде ..а установленно неверно, каких-то библиотек не хватает ?
поменял несколько URL для чистоты эксперемента - получил сообщение
Fatal error: Maximum execution time of 30 seconds exceeded ...
Мелкий
Отправлено: 10 Января, 2011 - 18:46:14
Активный участник
Покинул форум
Сообщений всего: 11926
Дата рег-ции: Июль 2009 Откуда: Россия, Санкт-Петербург
Помог: 617 раз(а)
Если бы нехватало библиотек, то был бы вызов неизвестной функции. Или вообще нестарт сервера.
По какому урлу обращаетесь и передаётся ли он вообще с формы?
----- PostgreSQL DBA
Delovoy
Отправлено: 11 Января, 2011 - 09:50:08
Новичок
Покинул форум
Сообщений всего: 63
Дата рег-ции: Нояб. 2010
Помог: 0 раз(а)
спасибо за ответ
вопрос решил уже - пишу как, может кому-то сгодится
у нас стоит прокси сервер! и если через браузер (в котором прокси указан в настройках) мы переходим на внешние сайты без проблем, то для cURL нужно было указывать отдельно!
Novi4ok
Отправлено: 29 Марта, 2011 - 06:48:14
Новичок
Покинул форум
Сообщений всего: 8
Дата рег-ции: Март 2011
Помог: 0 раз(а)
Вопрос перенес сюда http://forum.php.su/topic.php?forum=1&topic=6841&postid=1301408172#1301408172
Покинул форум
Сообщений всего: 32
Дата рег-ции: Апр. 2011
Помог: 0 раз(а)
Подскажите пожалуйста, а вот как проверить, валидные данные или нет? В плане, куда и что возвращает курл в случае неудачной авторизации? Можно ли как то сделать функцию, вида .if eax==верное значение, то делать то
.else (значение неверное) - делать другое. еах тут условно, это место куда функция возвращает значение.
Php знаю очень плохо, поэтому извиняюсь заранее, если вопрос очень глупый. По форуму искал, но ничего толком не нашел.
з.ы. если в курле это невозможно, то подскажите с помощью чего еще можно проверить, можно ли с помощью определенных данных авторизоваться на сайте, или нет.
shpiz
Отправлено: 23 Октября, 2012 - 10:36:52
Новичок
Покинул форум
Сообщений всего: 1
Дата рег-ции: Окт. 2012
Помог: 0 раз(а)
Подскажите пожалуйста, как быть если надо подключиться к soap-сервису при помощи curl по протоколу https используя сертификат? (wsdl описание есть)
Все гости форума могут просматривать этот раздел. Только зарегистрированные пользователи могут создавать новые темы в этом разделе. Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.