Страницы

Поиск по вопросам

Показаны сообщения с ярлыком curl. Показать все сообщения
Показаны сообщения с ярлыком curl. Показать все сообщения

понедельник, 24 февраля 2020 г.

Авторизация пользователя vk с помощью cURL (PHP)

#php #вконтакте #curl #авторизация


Добрый день.

Необходимо авторизировать пользователя vk с помощью PHP скрипта и библиотеки cURL. 
Были рассмотрены следующие решения:


https://forum.antichat.ru/threads/426901/
http://sauron.org.ua/post/938


На основе решений были составлены следующие скрипты.

Получение значений lg_h и ip_h (работает, получает):

$url = 'http://vk.com';
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT
6.1)");
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
        'accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
        'content-type: application/x-www-form-urlencoded',
        'origin: http://vk.com',
        'referer: http://vk.com/',
));
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);

$content = curl_exec($ch);

preg_match_all("/name=\"ip_h\" value=\"(.*?)\" \\//s", $content, $ip_h);
preg_match_all("/name=\"lg_h\" value=\"(.*?)\" \\//s", $content, $lg_h);


Отправка запроса авторизации вида:

http://login.vk.com/?
act=login&
role=al_frame&
_origin=http://vk.com&
ip_h=$ip_h&
lg_h=$lg_h&
email=&
pass=


Сам скрипт:

$url = 'http://login.vk.com/?act=login';
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:42.0)
Gecko/20100101 Firefox/42.0");
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
//curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_POST, true);

$data = array(
    'act' => 'login',
    'role' => 'al_frame',
    '_origin' => 'http://vk.com',
    'ip_h' => $ip_h[0][1][0],
    'lg_h' => $lg_h[0][1][0],
    'email' => '',
    'pass' => ''
);

curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));

curl_setopt($ch, CURLOPT_HTTPHEADER, array(
    'accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
    'content-type: application/x-www-form-urlencoded',
    'origin: http://vk.com',
    'referer: http://vk.com/',
));

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);

curl_setopt($ch, CURLOPT_COOKIEJAR, '/home//Development/vk/cookie.txt');
curl_setopt($ch, CURLOPT_COOKIEFILE, '/home//Development/vk/cookie.txt');

echo curl_exec($ch);


На выходе получаю следующее содержимое страницы:




В свою очередь куки принимают следующие значения:

Set-Cookie: remixmid=DELETED; expires=Thu, 01 Jan 1970 00:00:01 GMT; path=/; domain=.vk.com
Set-Cookie: remixsid=DELETED; expires=Thu, 01 Jan 1970 00:00:01 GMT; path=/; domain=.vk.com
Set-Cookie: remixsid6=DELETED; expires=Thu, 01 Jan 1970 00:00:01 GMT; path=/; domain=.vk.com
Set-Cookie: remixgid=DELETED; expires=Thu, 01 Jan 1970 00:00:01 GMT; path=/; domain=.vk.com
Set-Cookie: remixemail=DELETED; expires=Thu, 01 Jan 1970 00:00:01 GMT; path=/; domain=.vk.com
Set-Cookie: remixpass=DELETED; expires=Thu, 01 Jan 1970 00:00:01 GMT; path=/; domain=.vk.com
Set-Cookie: remixapi_sid=DELETED; expires=Thu, 01 Jan 1970 00:00:01 GMT; path=/;
domain=.vk.com
Set-Cookie: remixpermit=DELETED; expires=Thu, 01 Jan 1970 00:00:01 GMT; path=/; domain=.vk.com
Set-Cookie: remixsslsid=DELETED; expires=Thu, 01 Jan 1970 00:00:01 GMT; path=/; domain=.vk.com


Смею предположить, что не удается передать значение email, т.к. в коде JS именно
на это и ошибка. При ручном составлении URL и перехода по нему — успешное возвращение
хэша и содержимое страницы следующее:




Авторизация проходит успешно. После доступен профиль пользователя.
    


Ответы

Ответ 1



Только что написал рабочий код авторизации во ВКонтакте — http://pastebin.com/5YecKuUs Только учтите, каптча не поддерживается, поэтому сами уже её добавьте. Тест успешно пройден на моём тестовом аккаунте ;)

Ответ 2



Есть рабочая библиотека для PHP, которая получает куку remixsid.

Ответ 3



По состоянию на июль 2018 это рабочий код. Авторизация через мобильную страницу т.к. проще. $email = "{ТЕЛЕФОН}"; $pass = "{ПАРОЛЬ}"; $auth_url = "https://m.vk.com"; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $auth_url); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); //файл для сохранения кукис - cookie.txt curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookie.txt'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //получаем содержимое формы авторизации (URL атрибута action) $login_page = curl_exec($ch); curl_close($ch); //парсим страницу... $html = str_get_html($login_page); //..и узнаем урл авторизации (использовал библиотеку Simple PHP DOM Parser) $login_url = $html->find("form",0)->action; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $login_url); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); //отправляем ПОСТ запрос curl_setopt($ch, CURLOPT_POST, 1); //следуем за редиректом curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); //данные запроса curl_setopt($ch, CURLOPT_POSTFIELDS, ["email"=>$email, "pass"=>$pass]); //СНАЧАЛА ЧИТАЕМ КУКИ полученные в первом запросе curl_setopt($ch, CURLOPT_COOKIEFILE, 'cookie.txt'); //потом ДОБАВЛЯЕМ НОВЫЕ curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookie.txt'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_exec($ch); curl_close($ch); //пользователь авторизован //далее тестируем $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, "https://vk.com/groups?act=catalog"); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); //только читаем куки curl_setopt($ch, CURLOPT_COOKIEFILE, 'cookie.txt'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $page = curl_exec($ch); curl_close($ch); //если ваш сервер работает на UTF-8, в отличие от VK (windows-1251) echo iconv('windows-1251','utf-8',$page);

Ответ 4



Попробуйте закодировать функцией urlencode

четверг, 13 февраля 2020 г.

Передача файла на сервер CURL

#php #curl #файлы


Пытаюсь передать файл на сервер, использую CURL

Запрос формируется так:

$postdata = array(
            'FileToLoad' => "@".$this->file."; filename=\"$this->filename\";",
            'fileId' => $this->fileId);


$this->file содержит полный путь до файла на сервере /var/www/site/data/www/site.ru/tmp/file.pdf

Отправляю так:

if( $curl = curl_init() ) {
            curl_setopt($curl, CURLOPT_URL, $url);
            curl_setopt($curl, CURLOPT_RETURNTRANSFER,true);
            curl_setopt($curl, CURLOPT_POST, true);
            curl_setopt($curl, CURLOPT_POSTFIELDS, $postdata);
            curl_setopt($curl,CURLOPT_ENCODING, '');
            curl_setopt($curl, CURLOPT_COOKIE, ".ASPXAUTH=$this->token;");
            $out = curl_exec($curl);
            curl_close($curl);
        }


Запрос проходит успешно, но данные попадают в $_POST, а я их очень хочу увидеть в
$_FILES. Где я ошибаюсь?
    


Ответы

Ответ 1



Как выяснили в комментариях, речь о PHP 5.6. Начиная с этой версии загрузка файлов синтаксисом через @ отключена по-умолчанию. Теперь файлы нужно загружать через класс CURLFile, как-то так: $postdata = array( 'FileToLoad' => new CURLFile($this->file, null /*или mime-type*/, $this->filename), 'fileId' => $this->fileId, ); Код самого запроса остаётся тем же самым. Как видно, исправляется несложно. Но для полноты ответа добавлю, что для старого кода включить обратно передачу файлов через синтаксис @ пока возможно опцией CURLOPT_SAFE_UPLOAD

Ответ 2



Для поддержки старых версий PHP if (!function_exists('curl_file_create')) { function curl_file_create($filename, $mimetype = '', $postname = '') { if(file_exists($filename)) return "@$filename;filename=" . ($postname ?: basename($filename)) . ($mimetype ? ";type=$mimetype" : ''); else exit('Error! File '.$filename.' not found!'); } } И вызывать: curl_file_create($file)

среда, 12 февраля 2020 г.

libcurl - как парсить HTTP заголовок?

#cpp #http #curl #парсер #веб_сервер


Учусь писать HTTP веб-сервер. Сам сервер есть. Запускаю сервак, посылаю HTTP-запрос
curl -D dumpbin 127.0.0.1:2000. На сервере сохраняю запрос в строковую переменную.
Теперь (и я не знаю, как это сделать) мне надо распарсить весь полученный запрос, составить
ответ и отправить обратно. С отправкой я справлюсь, а вот с парсингом и с составлением
ответа возникли проблемы. 
Сказали, что следует использовать libcurl, но я не понимаю, как им можно парсить
готовые строки и можно ли.
Помогите, пожалуйста, примером такого использования этой либы, если он возможен.
Посоветуйте, какие можно использовать библиотеки еще, чтобы решить эту задачу.

//Вид запроса (это то, что вернул мой эхо-сервер при использовании утилиты curl): 

    request = "GET /index.html HTTP/1.1\r\n"
              "Host: 127.0.0.1:5991\r\n"
              "User-Agent: curl/7.47.0\r\n"
              "Accept: */*\r\n"
              "\r\n";

    //Вид ответа (это я прочитал в комментах к заданию на степике):
    answer = "HTTP/1.0 200 OK\r\n"
             "Content-length: %d\r\n"
             "Connection: close\r\n"
             "Content-Type: text/html\r\n"
             "\r\n"
             "%s";


Суть в том, что есть данные, которые разделены \r\n и заканчиваются двойным переводом
каретки и строки \r\n\r\n
    


Ответы

Ответ 1



tl;dr см. конец ответа для реализации парсера заголовков licurl используют, как правило, для написания клиентов, смотрите FAQ: 5.17 Can I write a server with libcurl? No. libcurl offers no functions or building blocks to build any kind of internet protocol server. libcurl is only a client-side library. For server libraries, you need to continue your search elsewhere but there exist many good open source ones out there for most protocols you could possibly want a server for. And there are really good stand-alone ones that have been tested and proven for many years. There's no need for you to reinvent them! В вольном переводе: 5.17 Могу ли я использовать libcurl для написания сервера? Нет. libcurl не предлагает функций или других строительных блоков для создания какого либо IP сервера. libcurl это только клиентская библиотека. Вам нужно продолжить ваши поиски библиотеки для построения сервера. Существует большое количество таких библиотек с открытым исходным кодом для большинства протоколов. Также существует большое кол-во проверенных годами stand-alone приложений. Вам не стоит изобретать их заново. Хотя для построения клиента libcurl действительно очень удобная вещь, как упомянул в своем ответе @Pink Tux. В том числе заголовки вы получаете уже разбитые по одному. Для построения сервера, как один из вариантов, можно использовать mongoose (на c, в виде пары .c/.h, добавляемой к вашему проекту, либо одну из многочисленных c++ оберток). Пример минимального сервера достаточно громоздкий, поэтому приводить здесь не буду. Можно посмотреть здесь. Еще один вариант - библиотека cpp-netlib которая изначально планировалась как часть boost (но потом планы разработчиков поменялись). В простейшем виде http сервер выглядит так: namespace http = boost::network::http; struct handler; typedef http::server http_server; struct handler { void operator() (http_server::request const &request, http_server::response &response) { response = http_server::response::stock_reply( http_server::response::ok, "Hello, world!"); } void log(http_server::string_type const &info) { std::cerr << "ERROR: " << info << '\n'; } }; int main(int arg, char * argv[]) { handler handler_; http_server::options options(handler_); http_server server_( options.address("0.0.0.0") .port("8000")); server_.run(); } Если вам нужно что-то еще более высокоуровневое (с поддержкой шаблонов, json, middlewares), можно взять crow, которая подключается к вашему проекту одним заголовочным файлом. По духу это напоминает Python Flask. Пример сервера: #include "crow_all.h" int main() { crow::SimpleApp app; CROW_ROUTE(app, "/")([](){ return "Hello world"; }); app.port(18080).multithreaded().run(); } Если все-таки интересно самому разобрать заголовки, то можно например таким кодом: std::istringstream rawstream(raw); std::map headers; std::string header; while (std::getline(rawstream, header) && header != "\r") { std::string::size_type index = header.find(':'); if (index != std::string::npos) { headers.insert(std::make_pair( boost::algorithm::trim_copy(header.substr(0, index)), boost::algorithm::trim_copy(header.substr(index + 1)) )); } } В raw типа std::string помещаете строку с вашими заголовками (либо даже целиком запрос клиента), в headers получаете map из имен/значений заголовков. Используете к примеру так: std::cout << headers["Content-Type"] << std::endl; Обратите внимание, что по стандарту имя заголовка может иметь любой регистр. Поэтому CONTENT-TYPE, content-type и Content-Type это все один заголовок, и для удобства можно перед добавлением в map привести имя заголовка в нижний регистр: headers.insert(std::make_pair( boost::algorithm::to_lower_copy(boost::algorithm::trim_copy(header.substr(0, index))), boost::algorithm::trim_copy(header.substr(index + 1)) )); Действующий пример на Ideone.com. P.S. Для тестирования вместо curl можно использовать postman в котором можно задавать заголовки, тело страниц (в том числе json), сохранять наборы запросов и т.д.

Ответ 2



libcurl предоставляет возможность задавать обработчик для разных данных. Например, чтобы "поймать" заголовки ответа, можно воспользоваться следующим подходом: static size_t header_callback(char *buffer, size_t size, size_t nitems, void *userdata) { /* * Эта функция будет вызываться на каждый возвращаемый заголовок. */ return nitems * size; } int main() { CURL *curl = curl_easy_init(); if(curl) { curl_easy_setopt(curl, CURLOPT_URL, "http://yahoo.com/"); curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, header_callback); curl_easy_perform(curl); } return 0; } Подробней - см. в документации по libcurl. Кроме того, для C++ есть обёртки, например, curlcpp.

среда, 29 января 2020 г.

cURL не работает

#php #curl #парсер


Пытаюсь сделать парсер, но не хочет работать, пишет


  Object Moved This object may be found here.


Гуглил, но решения не удалось найти. Что за метод защиты стоит, что запрещает парсить
данные с данного сайта ?

$url = 'http://elibrary.ru/titles.asp';

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/535.6
(KHTML, like Gecko) Chrome/16.0.897.0 Safari/535.6'); 
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0);
curl_setopt($ch, CURLOPT_REFERER, $url);
$content = curl_exec($ch);
curl_close($ch);
echo $content;

    


Ответы

Ответ 1



Суть проблемы в следующем: целевой сайт выставляет cookie для идентификации пользователя и отдает код 302 Moved Temporarily + заголовок Location. Это что-то вроде защиты от простеньких парсеров, не способных работать с cookie. Если говорить о вашем коде, то опция CURLOPT_FOLLOWLOCATION выставленная в false (или 0), запрещает переходы по ссылкам из Location. Поэтому вы видите в ответе: Object moved Выставление CURLOPT_FOLLOWLOCATION в true (или 1) не помогает в вашем случае потому, что curl по умолчанию все еще не работает с cookie. А чтобы работал, достаточно указать: curl_setopt($ch, CURLOPT_COOKIEFILE, ''); Пустая строка в качестве значения, указывает curl, что cookie должны быть использованы, однако без сохранения в файловую систему (см. http://php.net/manual/ru/function.curl-setopt.php). Таким образом, работающий код может выглядеть так: $url = 'http://elibrary.ru/titles.asp'; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/535.6 (KHTML, like Gecko) Chrome/16.0.897.0 Safari/535.6');. curl_setopt($ch, CURLOPT_HEADER, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); curl_setopt($ch, CURLOPT_REFERER, $url); curl_setopt($ch, CURLOPT_COOKIEFILE, ''); $content = curl_exec($ch); curl_close($ch); echo($content);

Ответ 2



Хорошее решение, долго не мог решить эту проблему. Для некоторых сайтов обязательно не только cookie, но и строка user-agent: curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/535.6 (KHTML, like Gecko) Chrome/16.0.897.0 Safari/535.6'); после чего все заработало.

пятница, 24 января 2020 г.

Не получается установить вебхук(viber)

#python #post #curl #viber


Следовал инструкции с офф.сайта

Вот views.py файлик

@csrf_exempt
def botviber(request):
    bot_configuration = BotConfiguration(
        name='zxcasdqwezxcasdqwe',
        avatar='http://viber.com/avatar.jpg',
        auth_token='************************'
    )

    viber = Api(bot_configuration)
    viber.set_webhook('https://sitename.ninja/botviber/')

    viber_request = viber.parse_request(request.get_data())
    print(viber_request)


После этого при попытке перейти на сайт - получаю вот такую ошибку:

Exception at /botviber/
failed with status: 1, message: Result[HttpRequest[POST /botviber/ HTTP/1.1]@533b70c
> HttpResponse[null 0 null]@28581fb9] java.util.concurrent.TimeoutException: Total
timeout elapsed


Забил на это, решил через curl сделать вебхук

Вот команда curl -# -i -g -H "X-Viber-Auth-Token:*****" -d @vibe.json -X POST https://chatapi.viber.com/pa/set_webhook -v

Cам vibe.json файл

{
  "url": "https://sitename.ninja"
}


Тоже ошибка - 

Note: Unnecessary use of -X or --request, POST is already inferred.
*   Trying 52.4.209.25...
* Connected to chatapi.viber.com (52.4.209.25) port 443 (#0)
* found 148 certificates in /etc/ssl/certs/ca-certificates.crt
* found 594 certificates in /etc/ssl/certs
* ALPN, offering http/1.1
* SSL connection using TLS1.2 / ECDHE_RSA_AES_128_GCM_SHA256
*    server certificate verification OK
*    server certificate status verification SKIPPED
*    common name: *.viber.com (matched)
*    server certificate expiration date OK
*    server certificate activation date OK
*    certificate public key: RSA
*    certificate version: #3
*    subject: C=LU,ST=Luxembourg,L=Luxembourg,O=Viber Media Sarl,OU=IT,CN=*.viber.com
*    start date: Sun, 26 Jun 2016 00:00:00 GMT
*    expire date: Tue, 26 Jun 2018 23:59:59 GMT
*    issuer: C=US,O=thawte\, Inc.,CN=thawte SSL CA - G2
*    compression: NULL
* ALPN, server did not agree to a protocol
> POST /pa/set_webhook HTTP/1.1
> Host: chatapi.viber.com
> User-Agent: curl/7.47.0
> Accept: */*
> X-Viber-Auth-Token:security
> Content-Length: 39
> Content-Type: application/x-www-form-urlencoded
> 
* upload completely sent off: 39 out of 39 bytes
< HTTP/1.1 200 OK
HTTP/1.1 200 OK
< cache-control: no-cache no-store
cache-control: no-cache no-store
< content-type: application/json
content-type: application/json
< date: Sat Feb 10 21:03:46 2018
date: Sat Feb 10 21:03:46 2018
< Content-Length: 158
Content-Length: 158
< Connection: keep-alive
Connection: keep-alive

< 
* Connection #0 to host chatapi.viber.com left intact
{"status":1,"status_message":"Result[HttpRequest[POST / HTTP/1.1]@40da913d > HttpResponse[null
0 null]@c0d645f] java.nio.channels.UnresolvedAddressEx


Помогите пожалуйста, в чем здесь вообще ошибка и как быть
    


Ответы

Ответ 1



Ошибка решилась. В json файле с адресом оказалась 1 русская буква.

Не работает curl -s “https://get.sdkman.io” | bash

#linux #bash #curl #elementary_os


Хочу установить sdkman на elementary OS Loki.
Пытаюсь делать всё по инструкции с сайта, ввожу в консоли curl -s "https://get.sdkman.io"
| bash и ничего не происходит. Разработчики sdkman сказали, что возможно это из-за
блокировок серверов, но у меня стоит vpn и я могу пинговать get.sdkman.io, а также
если я ввожу этот адрес в браузер то у меня открывается их страница, отсюда я сделал
вывод, что дело не в блокировке, в чём тогда может быть проблема?

UPD:
попробовал изменить запрос вот результат

curl -sv "https://get.sdkman.io/" | bash
Rebuilt URL to: https://get.sdkman.io/
Trying 159.89.187.78...
Connected to get.sdkman.io (159.89.187.78) port 443 (#0)
found 148 certificates in /etc/ssl/certs/ca-certificates.crt
found 597 certificates in /etc/ssl/certs
ALPN, offering http/1.1
gnutls_handshake() failed: Error in the push function.
Closing connection 0


UPD2:

ls -l $(which bash)
-rwxr-xr-x 1 root root 1037528 ноя 27  2017 /bin/bash

bash --version
GNU bash, версия 4.3.48(1)-release (x86_64-pc-linux-gnu)


UPD3:

$ wget 'https://get.sdkman.io'
--2018-09-27 16:25:07--  https://get.sdkman.io/
Распознаётся get.sdkman.io (get.sdkman.io)... 159.89.187.78
Подключение к get.sdkman.io (get.sdkman.io)|159.89.187.78|:443... 
соединение установлено.
Не удаётся установить SSL-соединение.


UPD4:
Я использую VPN, на сайт get.sdkman.io через браузер я зайти могу.

    


Ответы

Ответ 1



согласно информации с сайта https://zapret.info/index.php?url=get.sdkman.io: Сожалеем, ресурс get.sdkman.io (159.89.187.78) находится в списке заблокированных ресурсов на территории Российской Федерации! если у вас имеется ssh-доступ к серверу, на котором сайт get.sdkman.io (и api.sdkman.io, к которому происходят обращения уже внутри скрипта, который вы хотите получить и выполнить) не заблокирован, то можете воспользоваться советом из другого моего ответа: Как проксировать http[s] через ssh-туннель? (точнее, первым пунктом из ответа). в отдельном эмуляторе терминала запускаете проксирующий процесс: $ ssh -D 1122 user@server в другом эмуляторе терминала, где собираетесь запускать программу curl, объявляете переменную окружения HTTPS_PROXY, значение которой использует программа: $ export HTTPS_PROXY=socks5://localhost:1122 (номер порта — тот же самый, что вы указывали и при запуске ssh) теперь в этом эмуляторе терминала команда $ curl https://get.sdkman.io | ... благополучно отработает. если вы, как и я, не доверяете всяким левым сайтам и устанавливаете программы с них исключительно в docker-контейнерах, то контейнер надо запускать (хотя бы на стадии запуска скриптов с sdkman.io), например, с опцией --network=host. первый пункт выполняете на хост-машине, второй и третий — внутри контейнера.

Ответ 2



Просто используй curl -s "http://get.sdkman.io" | bash

четверг, 23 января 2020 г.

CURL выводит ответ но не возвращает его в переменную

#php #curl


Ниже код:

$url = "http://site.ru/my_exchange_2.php?type=sale&mode=checkauth";  
$ch = curl_init();  
curl_setopt($ch, CURLOPT_URL,$url); // set url to post to  
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_USERPWD, "user:password");
$result = curl_exec($ch); 
curl_close($ch);   
echo $result;


Код выполняется, выдает ответ:

success PHPSESSID aooom9tmurdnrdukfgkk631421 sessid=e519c36f6765ec9f8eaf30ecd10d9f4d


Но в переменной $result нет ответа, а только bool(true) если смотреть через var_dump.

Как получить то, что выводит curl на экран? Меня интересует sessid.
    


Ответы

Ответ 1



Добавьте эту опцию: curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

Ошибка 404 в ответе cURL

#php #curl


Здравствуйте! У меня такой вопрос. Я отправляю post данные с помощью cURL на другой
сайт. Мне нужно проверить если в курле введен не существующий url сайта, то в итоге
возвращается стр. 404. Как сделать проверку что возвращена именно страница 404? Поиском
подстроки 404 в принятом html или есть какой-то другой способ?
    


Ответы

Ответ 1



Это очень индивидуально для каждого сайта. "Правильная" 404 страница отдаёт http_code 404, но к сожалению не все сайты правильные. Многие отдают 200 ОК на 404 ошибку. Кроме того, каждый сайт может сделать свою кастомную 404 страничку с уникальным дизайном. Там может вообще не встретиться 404 (легко: сделано картиной) Поэтому нужно смотреть на конкретный сайт и анализировать конкретно его особенности. Кроме того, принятый алгоритм может вдруг перестать работать после редизайна сайта. Искать в теле только 404 чревато изредка ложными срабатываниями -- особенно если на сайте много разных цифр и таблиц -- может найтись и такая, на которой 404 встречается. Увы, серебряной пули нет. Подбирайте под конкретный сайт свой собственный алгоритм. PS Классический ответ 404 в http_code реализуется так: $handle = curl_init($url); curl_setopt($handle, CURLOPT_RETURNTRANSFER, TRUE); /* Get the HTML or whatever is linked in $url. */ $response = curl_exec($handle); /* Check for 404 (file not found). */ $httpCode = curl_getinfo($handle, CURLINFO_HTTP_CODE); if($httpCode == 404) { /* Handle 404 here. */ } curl_close($handle); Пример отсюда: https://stackoverflow.com/questions/408405/easy-way-to-test-a-url-for-404-in-php Также см. в документации: http://php.net/manual/ru/function.curl-getinfo.php

среда, 22 января 2020 г.

Парсинг. На запрос от сайта отдает ответ, а через cURL нет

#php #curl


Сильно увлекаюсь темой парсингом динамических сайтов. Наткнулся на интересный ресурс.
Решил его пропарсить. В Chrome на вкладке Network посмотрел куда идет запрос, там оказывается
он идет через GET. Я скопировал ссылку запроса - перешел на нее - в итоге ответ 403
- мне данные не выдает.

Тогда я скопировал этот запрос: Copy -> Copy as cURL (bash) с куками и тд (все как
в браузере)
И импортировал этот запрос в Postman, попытался выполнить - но в ответ получаю все
ту же 403.

Стало еще интереснее. Хотелось бы разгадать этот ребус. Возможно там создается какая-то
метка... или еще что-то.

Буду благодарен за любую помощь!
Очень бы хотелось получить больше опыта в парсинге подобных ресурсов.

Ссылка на динамическую страницу которую пытаюсь парсить: ссылка

Ссылка куда идет запрос с Network: ссылка
    


Ответы

Ответ 1



Я провел експеримент и определил минимальный набор данных чтоб запрос проходил: Cookie Referer User-agent Вот этот код работает у меня.

вторник, 7 января 2020 г.

Как уменьшить расход памяти? php, cURL, array

#массивы #память #php #оптимизация #curl


Собираю два массива А и Б по ~миллиону целых чисел из веб сервиса, чтобы затем сосчитать
их пересечение. Сервис отдаёт за один запрос 1000 чисел, поэтому в цикле около 1000
раз для каждого приходится делать запрос через cURL. Коннекшн один, используется снова
и снова: подставляются новые значения в CURLOPT_POSTFIELDS, и снова curl_exec().

Полученный json разбирается, и очередной массив с 1000 целых чисел merge'ится в А или Б.

Пока это всё работает в виде пруф-оф-концепт на shared хостинге руЦентра, где памяти
выделено всего ничего. С партиями меньше миллиона скрипт справляется. Больше - вылетает
с фатальной ошибкой об исчерпанной памяти. Иногда на этапе получения второго миллиона
из сервиса, иногда уже после, на этапе сравнения.

Вместо ф-ий array_merge() и array_intersect() уже использую свои, менее ресурсоёмкие:
мне не нужно сортировать и получать само пересечение, достаточно сосчитать кол-во общих.

Не может только массив целых с 2 млн. значений занимать десятки мегов памяти же!
Как понять, раздувается ли это cURL при каждом новом обращении? Или, может, массивы
хранят значения не как целые по 4 байта, а как строки например?

Сориентируйте, пожалуйста, с оптимизацией по памяти - куда копать?
    


Ответы

Ответ 1



Имхо при ужатой памяти вам проще на БД переложить этот процесс. Работать будет дольше, но памяти есть меньше. Может быть, можно будет даже часть алгоритмов на базу переложить. Далее, в php с памятью такая анархия, что лучше даже не интересоваться. Достаточно сказать, что размер массива всегда степень двойки (в большую сторону), состоит он из указателей(4-8 байт) на int, а int - это структура(имя, тип, размер etc). И далее, если можно обрабатывать все в процессе - do it. Т.е. получили тысячу, обработали, выкинули, погнали дальше. Если нет - БД. Теоретически можно попробовать с временными файлами поколдовать, но вряд ли этот способ сильно выиграет у БД по удобству/скорости.

понедельник, 6 января 2020 г.

Получение всех HTTP заголовков страницы

#php #http #curl #http_заголовки


Всем привет. Допустим, есть сайт site.ru. С помощью данного скрипта я могу получить
лишь сам адрес страницы:

if( $curl = curl_init() ) {
curl_setopt($curl,CURLOPT_URL,'http://site.ru');
curl_setopt($curl,CURLOPT_RETURNTRANSFER,true);
curl_setopt($curl,CURLOPT_NOBODY,true);
curl_setopt($curl,CURLOPT_HEADER,true);
$out = curl_exec($curl);
echo $out;
curl_close($curl);
}


В браузере вижу следующее:

HTTP/1.1 301 Moved Permanently
Date: Sun, 14 May 2017 09:54:15 GMT
Server: Apache/2.4.7 (Ubuntu)
Location: http://site.ru/
Content-Type: text/html; charset=iso-8859-1


Как получить все заголовки, получаемые в инструментах разработчика (F12->Network)?
(Кто знает расширение для хрома Creative Tester - Live HTTP Headers(логотип круга салатового
цвета) - результат нужен примерно такой же, вернее, нужны только ссылки)

    


Ответы

Ответ 1



Возможно, get_headers():

Ответ 2



$raw_headers = ''; curl_setopt($curl, CURLOPT_HEADERFUNCTION, '__write_header'); public function __write_header($curl, $bytes) { $GLOBALS['raw_headers'] .= $bytes; return strlen($bytes); } CURLOPT_HEADERFUNCTION Callback-функция принимает два параметра. Первым параметром является дескриптор cURL, вторым параметром является строка с записываемыми заголовками. Заголовки должны быть записаны с помощью данной callback-функции. Должна возвратить количество записанных байт. описание взято отсюда

вторник, 31 декабря 2019 г.

Преобразование Curl в Java эквивалент?

#java #curl


Здравствуйте! Может ли кто-нибудь подсказать либо о существовании интерпретатора
Curl в Java, либо какой (хотя бы приблизительно) аналог кода на Java будет из этого
запроса:

 curl -i -X POST --data-urlencode "oauth_consumer_key=ЗНАЧЕНИЕ" --
 data-urlencode "oauth_nonce=значение"  --data-urlencode "oauth_signature_method=HMAC-SHA1"
--data-urlencode "oauth_timestamp=значение"  --data-urlencode "oauth_version=1.0" --data-
 urlencode "oauth_token=значение"  --data-urlencode "auth_signature=значение" --data
"category=3" --data-urlencode "title=Новое название" --data-urlencode "description=Краткое
описание" --data-urlencode "message=Полное описание" --data 
"end2br_desc=1&includehtml_desc=no" http://yoursite.ucoz.ru/uapi/news


Благодарю за ответ!
    


Ответы

Ответ 1



Вам нужно думать не об обертке над Curl, а об HTTP-клиенте в принципе. Для Java существует масса реализаций HTTP-клиентов. Один из самых известных - Apache HttpComponents / HttpClient HttpClient httpClient = HttpClients.createDefault(); HttpUriRequest request = RequestBuilder.post("http://yoursite.ucoz.ru/uapi/news") .addParameter("oauth_consumer_key", "ЗНАЧЕНИЕ") .addParameter("oauth_nonce", "значение") .addParameter("oauth_signature_method", "HMAC-SHA1") .addParameter("oauth_timestamp", "значение") .addParameter("oauth_version", "1.0") .addParameter("oauth_token", "значение") .addParameter("auth_signature", "значение") .addParameter("title", "Новое название") .addParameter("description", "Краткое описание") .addParameter("message", "Полное описание") .setEntity(new UrlEncodedFormEntity(Arrays.asList( new BasicNameValuePair("end2br_desc", "1"), new BasicNameValuePair("includehtml_desc", "no") ))).build(); HttpResponse response = httpClient.execute(request);

пятница, 27 декабря 2019 г.

OAuth2.0 vk.com используя curl и bash

#vkontakte_api #bash #вконтакте #curl #oauth2


Я хочу написать баш скрипт, который будет взаимодействовать с контактом через апи.

Для начала необходимо запрограммировать OAuth2.0 авторизацию. Все казалось бы просто,
но проблема в том, что я не могу использовать браузер, так как хочу чтобы мой скрипт
работал на юниксовой машине без иксов и без вмешательства пользователя, то есть меня.

Исходя из документация сайта вконтакте сначала я должен выполнить GET запрос:

https://oauth.vk.com/authorize?client_id=&redirect_uri=https://oauth.vk.com/blank.html&display=mobile&scope=video,audio&response_type=token&v=5.44&revoke=1


Этот запрос выполняется нормально и я получаю страницу для отображения пользователю
с формами ввода. На данной странице меня интересует только следующий код:

Phone or email:
Password:
Not registered yet?
Исходя из документации и этого кода делаю вывод что должен реализовать следующее, то есть отправить пост запрос: https://login.vk.com/?act=login&soft=1&utf8=1 и в качестве параметров передать следующие поля: _origin, ip_h, lg_h, to, email, pass Но этот запрос у меня не работает. Возвращается пустая строка при попытке выполнить через curl и страница с ошибкой, мол неправильный пароль если отправляю запрос через какой-нибудь REST клиент. Была мысль что проблема может быть в том, что я не использую куки, но с их добавлением тоже ничего не изменилось, хотя возможно я что-то сделал не так. Скрипт, который я пытаюсь заставить работать: #!/bin/bash username=$1 password=$2 response=$(curl --cookie-jar vk.txt "https://oauth.vk.com/authorize" --data "client_id=&redirect_uri=https://oauth.vk.com/blank.html&display=mobile&scope=video,audio&response_type=token&v=5.44&revoke=1") echo "response is $response" echo "=================================================================" response=$(curl --request POST --cookie vk.txt "https://login.vk.com/?act=login&soft=1&utf8=1" --data-urlencode "_origin=https://oauth.vk.com&ip_h=&lg_h=&to=&email=&pass=") echo "response is $response" echo "=================================================================" exit 0 Я пробовал играться с параметрами curl, например, кодировать, раскодировать передаваемые данные запроса. Но в результате получаю одно и то же. Может быть я должен проводить какое-то дополнительное кодирование или шифрование прежде чем выполнять запрос? Если да, то почему curl не выполняет это по умолчанию? Я нашел на просторах статью, где эта задача решалась на питоне и у чувака все работает. Я воспользовался его питоновским кодом, переделав его под третий питон, но он также не работает. Возвращает пустую страницу после ввода логина и пароля, хотя должен возвращать страницу с разрешениями для приложения. Мне кажется, что механизм авторизации претерпел некоторые изменения, в связи с чем код перестал работать. Вот ссылка на ту статью: https://habrahabr.ru/post/143972/ Вообщем вопрос в следующем: как сделать так чтобы всё заработало или что я делаю не так?


Ответы

Ответ 1



А redirect_uri у вас соответствует тому, что вы указали при регистрации приложения? Если нет, то проблема в этом.

VK API: загрузка фото на стену возвращает пустое photo

#java #curl #http #vkontakte_api #вконтакте


Пытаюсь прикрепить фото к посту, но upload-сервер возвращает

{"server":619324,"photo":"[]","hash":"235eb464133565b70d01ee4b174b2697"}

Шаги

Получаю uload_url через photos.getWallUploadServer(group_id)
Делаю POST-запрос на uload_url, где параметр формы photo содержит jpg-файл.

Дамп POST-запроса
Это дамп запроса, которые я получаю с Java-версии
POST /upload.php?act=do_add&mid=231464696&aid=-14&gid=74806856&hash=2b2c4e818d938b4202e736bccb6de22e&rhash=d22a5b85bf5bd8298f193b4318c8d54d&swfupload=1&api=1&wallphoto=1
 HTTP/1.1
Content-Length: 233477
Content-Type: multipart/form-data; boundary=0g6_BF339gILdnLw48ZE7ZTnTHz-pcIMiQG7Y
Host: cs619324.vk.com
Connection: Keep-Alive
Cookie: remixlang=0
Cookie2: $Version=1

--0g6_BF339gILdnLw48ZE7ZTnTHz-pcIMiQG7Y
Content-Disposition: form-data; name="photo"; filename="photo.jpg"
Content-Type: image/jpeg

(Бинарное содержимое файла)
...

Как я делаю запрос через curl
$ curl -F photo=@photo.jpg $uload_url

Как я делаю запрос на Java
Используется Apache HTTP-client 4. Результат аналогичен curl.
HttpPost post = new HttpPost(server.toURI());
HttpEntity entity = MultipartEntityBuilder.create()
        .setLaxMode()
        .addBinaryBody(fileName, image, ContentType.create("image/jpeg"), fileName
+ ".jpeg")
        .build();
post.setEntity(entity);
getNewHttpClient().execute(post);

HttpClient getNewHttpClient() {
        KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
    trustStore.load(null, null);
    SSLSocketFactory sf = new EmptySSLSocketFactory(trustStore);
    sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

    HttpParams params = new BasicHttpParams();
    HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
    HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);
    HttpConnectionParams.setConnectionTimeout(params, 3 * 60 * 1000);

    SchemeRegistry registry = new SchemeRegistry();
    registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
    registry.register(new Scheme("https", sf, 443));

    ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);

    return new DefaultHttpClient(ccm, params);
}



Аналогичные действия для заливки фото в альбом (photos.getUploadServer) работают
корректно.
Находил похожие сообщения об ошибках, но не помогло.
    


Ответы

Ответ 1



Используй Fiddler и проксируй все запросы через него - это поможет быстрее понять в чём ошибка. Для начала попробуй в браузере на старнице метода выполнить загрузку файла и в Fiddler посмотреть как формируется запрос, затем проверь как работает твой код. Ошибка будет видна практически сразу. В моём случае PHP не отправляло содержимое файла.

суббота, 21 декабря 2019 г.

Как отключить сообщения cURL?

#php #curl #ftp


Добрый день. Есть код на PHP который получает список файлов с FTP сервера. Код работает
через прокси, который поддерживает режим FTP over HTTP. Вот
сам код

$proxy_host = "1.1.1.1";  
$proxy_port = 8080;  
$curl = curl_init();  
$ftp_url = 'ftp://login:password@ftp:21/dir'; 
curl_setopt($curl,CURLOPT_TIMEOUT,10); 
curl_setopt($curl,CURLOPT_RETURNTRANSFER,1);
curl_setopt($curl,CURLOPT_FTPLISTONLY,1);
curl_setopt($curl,CURLOPT_PROXYTYPE,CURLPROXY_HTTP);
curl_setopt($curl,CURLOPT_PROXY,$proxy_host);
curl_setopt($curl,CURLOPT_PROXYPORT,$proxy_port);
curl_setopt($curl,CURLOPT_PROXYUSERPWD,'login_proxy:password_proxy');
curl_setopt($curl,CURLOPT_URL,$ftp_url); 
curl_setopt($curl,CURLOPT_VERBOSE,FALSE);
curl_setopt($curl,CURLOPT_HEADER,0);  
$content=curl_exec($curl);
echo $content;


Код работает прекрасно, однако вывод списка файлов всегда предваряет сообщение
curl 230 OK. Current restricted directory is /. Это сообщение присутствует даже тогда
когда я пытаюсь скачать файлы. То есть содержимое всех скачанных файлов содержит это
диагностическое сообщение. Как отключить вывод этого сообщения?

Дополнение
Параметр CURLOPT_VERBOSE (true,false,отсутствует) никак не влияет на сообщение. Есть
подозрение что он включен по умолчанию и не отключается.

Еще дополнения
пробовал на версиях PHP 5.3.13 и 5.6.30
версия curl (из phpinfo) 7.24.0
Важно то, что без proxy сервера все работает отлично.  
    


Ответы

Ответ 1



curl 230 OK. Current restricted directory is / Это сообщение выводится не из php, а из прокси-программы через которую вы отправляете запрос. Я не знаю что за софт там стоит может быть это 'Pure-FTPd' или что-то в этом роде. Но похоже что это он делает STDOUT перед показом того что вы запросили.. и соответственно ваш курл уже все это и подтягивает. Нужно уже смотреть в сторону как это заглушить, отправить в > /dev/null, смотреть конфиги и т.д.

Ответ 2



Попробуйте опции CURLOPT_HEADER или CURLINFO_HEADER_OUT (а, вероятно, и обе вместе) поставить в false. Тут описаны дополнительные опции, пошарьтесь в них если не помогло.

Ответ 3



Если внимательно прочитать CURLOPT_VERBOSE : TRUE для вывода подробной информации. Записывает вывод в STDERR или файл, указанный с помощью CURLOPT_STDERR. По скольку CURLOPT_VERBOSE - FALSE ничего не сказано, и притом в вашем случае он не соответствует логическому продолжению,то думаю что с использованием опции CURLOPT_STDERR поможет решить вашу проблему. Замените: ..... curl_setopt($curl,CURLOPT_VERBOSE,FALSE); ..... На: Заранее создайте файл curl.txt ..... $stderr = fopen("curl.txt", "w"); curl_setopt($curl, CURLOPT_VERBOSE, TRUE); curl_setopt($curl, CURLOPT_STDERR, $stderr); .....

понедельник, 16 декабря 2019 г.

Как спарсить инфо с сайта с recaptcha?

#php #curl #recaptcha


Есть 2 сайта с формами поиска информации, мой и чужой, на чужом стоит recaptcha в
форме поиска (аякс запрос на скрипт). Требуется с чужого спарсить информацию, пользуясь
формой поиска моего сайта.

Мои действия.

1 вариант. Загружаю на своем сайте рекапчу с публичным ключом для своего домена и
отправляю разгаданный ключ g-recaptcha-response на чужой сайт. В ответ - ошибка 403.
Вероятно несоответсвие моего публичного ключа и приватного того домена.

2 вариант. Пытаюсь загрузить у себя в песочнице рекапчу с публичным ключом чужого
сайта - в ответ ошибка (на скриншоте). 



Вопрос - как мне спарсить инфо с такого сайта? Капчу не требуется взламывать, её
будет разгадываать человек, это не проблема.

Напоминаю, данное осуществимо, сервис Rucaptcha предоставляет услуги разгадывания
капч, в том числе и гугловскую рекапчу http://rucaptcha.com/api-rucaptcha#solving_recaptchav2_new

Дополнено 04.10.2017: Для пробы парсинга можете использовать форму с рекапчей на
моем тестовом стенде http://dev.drupalworld.ru/recaptcha/ - имитация чужого сайта.
    


Ответы

Ответ 1



Это можно сделать простым скриптом при достаточном везении. Если при создании ключей автор сайта не указал домен, на котором капча должна ра­ботать, то скрипт рекаптчи будет работать на любом домене. Конкретно это поле нужно было оставить пустым: Если это было так, то вы сможете попросить разгадать ту же самую капчу у вас на сервере с тем же самым sitekey:
Google не сможет проверить с того сайт разгадывается капча, или с другого. У упомянутой вами РуКапча используется самодельный браузер, в котором разрешена подмена window.location.href без перезагрузки страницы. Очевидно, это не вариант для обычных гостей сайта. Динамически этот ключ можно получить, но лучше будет кешировать его где-то чтобы не дёргать тот сайт каждый раз при открытии страницы. $contents = file_get_contents('http://dev.drupalworld.ru/recaptcha/'); preg_match('#data-sitekey="([-_A-Za-z0-9]+)"#', $contents, $match); $sitekey = $match[1]; Это было первое условие. Оно может быть выполнено если разработчик был ленив, и не стал получать ещё один ключ для локальной разработки, или не стал добавлять имя локального се­рвера к разрешенным в существующем ключе. Или не пользовался специальным ключом для разработчика. При создании ключа у вас в примере вы указали домен, значит такой трюк на вашем примере уже не получится провернуть. Второе условие: необходимо чтобы на целевом сайте использовалась самодельная функция для отправки результатов на сервер Google, которая не указывает IP разгадавшего капчу в па­раметре remoteip. Этот параметр пока ещё не является обязательным. Если такого параметра нет, то Google не сможет проверить что человек, разгадавший капчу, и человек, зашедший на сайт, тот же самый. Таким образом, если вам повезло по двум пунктам, то вы сможете разгадывать ту же самую капчу у вас на сайте. Если хотя бы по одному из пунктов вам не повезло, то пиши пропало. Простым скриптом такую капчу не обойти.

вторник, 10 декабря 2019 г.

Как передать в cURL дату в формате Java Date?

#php #java #android #curl #parsecom


Есть Android-приложение, оно отправляет на сервер через Parse.com один из параметров
в формате Date:

HashMap p = new HashMap();
p.put("created", Calendar.getInstance().getTime());
ParseCloud.callFunctionInBackground(f, p, v);


Как передать этот параметр в таком же формате, но только через cURL в PHP? Пробовал
передавать в массиве строковое значение или Date в виде массива, сервер не принимает
такие запросы:

array('created'=>'Sun Nov 12 2017 02:58:09 GMT+0300')
array('__type'=>'Date','iso'=>'2017-11-11T12:35:39.273Z')


Как понимаю, надо передать параметр в виде самого объекта Date, но вопрос как он
будет точно выглядеть в сыром текстовом виде?

Это сам код для выполнения cURL-запроса:

    // post fields
    $post_fields = array('created'=>'здесь должно быть значение для created');
    // options
    $options = array(
        CURLOPT_URL => $target_url,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HEADER => true,
        CURLOPT_HTTPHEADER => $headers,
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => http_build_query($post_fields),
        CURLOPT_CONNECTTIMEOUT => 20,
        CURLOPT_SSL_VERIFYPEER => false,
        CURLOPT_TIMEOUT => 20,
        CURLOPT_USERAGENT => $user_agent
    );
    // curl
    $curl = curl_init();
    curl_setopt_array($curl, $options);
    $data = curl_exec($curl);
    curl_close($curl);

    


Ответы

Ответ 1



В PHP не силен, но если нужна строка вида yyyy-MM-dd'T'HH:mm:ss.SSS'Z' то по-моему, тут надо просто привести спецсимволы, а именно: двоеточие, одиночную кавычку, дефис и точку, - к формату URL, то есть (":") заменить на ("%3a") ("'") заменить на ("%27") ("-") заменить на ("%2d") (".") заменить на ("%2e") тогда строка из вашего cURL-запроса примет вид: $post_fields = array('created'=>'2017%2d11%2d17%27T%2708%3a54%3a27%2e727%27Z%27'); P.S. По рекомендации пользователя eugeneek, может быть, имеет смысл заменить 'created' на 'createdAt'

Ответ 2



Судя по исходникам SDK для Android: Все даты передаются в формате yyyy-MM-dd'T'HH:mm:ss.SSS'Z'. Нужный вам параметр называется createdAt. Получается вам нужно что-то типа: $post_fields = array('createdAt'=>'2017-11-17T08:54:27.727Z');

вторник, 16 июля 2019 г.

CURL POST params PHP

Нужно передать POST-ом некоторые параметры на определённый url. Для тестирование, я отправляю на свой action. Вот такой код:
$url = 'https://mysite/payboutique/paymentResult'; $xml_data = 'some data'; $data = array('xml' => urlencode($xml_data));
$headers = array( 'Content-type: text/xml', 'Content-length: '.strlen($xml_data), );
$ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_exec($ch);
В соответственном action я написал такой код:
$xml = Arr::get($_POST, 'xml', ''); Log::instance()->add(Log::NOTICE, 'Post:'.$xml); $xml = Arr::get($_GET, 'xml', ''); Log::instance()->add(Log::NOTICE, 'Get:'.$xml); Log::instance()->add(Log::NOTICE, implode("|",$_POST));
Посмотрел по логам, а ничего не пришло? Как вы поняли, мне нужно передать постом параметр с именем "xml". Что я не так сделал?
В логах:
2015-07-22 10:26:29 --- NOTICE: Post: in /.../system/classes/Kohana/Controller.php:84 2015-07-22 10:26:29 --- NOTICE: Get: in /.../system/classes/Kohana/Controller.php:84 2015-07-22 10:26:29 --- NOTICE: in /.../system/classes/Kohana/Controller.php:84


Ответ

Если вы хотите отправить с запросом POST параметры, вам нужен не Content-type: text/xml, а Content-type: application/x-www-form-urlencoded. Этот заголовок устанавливается самим CURL'ом автом-ки, если вы передадите в CURLOPT_POSTFIELDS url-encoded строку (для этого нужно вызвать функцию http_build_query). Так что вам не нужно вручную передавать HTTP заголовки, оставьте это CURL'у.
И читайте мануалы, в конце концов.

пятница, 12 июля 2019 г.

Изменить возврат от сервиса sms.ru при отправке sms ( команда curl )

Сервис sms.ru . При выполнении команды
curl -d "msg=TEXT" https://sms.ru/sms/send\?api_id=MY_ID\&to=PHONE
( где TEXT- текст sms, который отправляется на телефон, MY_ID- ID клиента в сервисе, PHONE - номер телефона, на который отправляется sms ) сервис возвращает при каждой отправке sms в терминал служебную информацию о статусе отправки, балансе клиента и т.п. - каждый раз три строки без перевода последней строки, (вот что получается например после двух смс):
100 201830-1000001 balance=8.13100 201830-1000001 balance=8.13
у меня на удаленном сервере включен бесконечный скрипт, который отслеживает текущее состояние и при наступлении определенных обстоятельств завершает каждый цикл выполнением вышеуказанной команды и я получаю sms с нужным кодом. Меня не устраивает, что ответы копятся, собственно они мне вообще не нужны там. Как сделать так, чтобы команда выполнялась, но мне в терминал ничего не возвращалось, ну или чтобы возврат был подавлен или как-то невидим?


Ответ

Вечер добрый
if [[ ваше условие ]]; then # если нужно сделать невидимым по условию curl -d "msg=TEXT" https://sms.ru/sms/send\?api_id=MY_ID\&to=PHONE &> /dev/null fi
Если речь идет о *nix и bash оболочке (не указано) stderr и stdout будут перенаправлены в "черную дыру" и не будут захламлять терминал.
Небольшое замечание, вы ничего не "захламляете" если пишите в stdout, вот если пишите в файл то да - используете какое то физическое-виртуальное пространство вашего удаленного сервера
Встречный вопросы:
скрипт написан на чем? bash/perl/python... знакомы ли вы с: /dev/null, >, <, 2 > /dev/null, & > /dev/null

четверг, 6 июня 2019 г.

Как уменьшить расход памяти? php, cURL, array

Собираю два массива А и Б по ~миллиону целых чисел из веб сервиса, чтобы затем сосчитать их пересечение. Сервис отдаёт за один запрос 1000 чисел, поэтому в цикле около 1000 раз для каждого приходится делать запрос через cURL. Коннекшн один, используется снова и снова: подставляются новые значения в CURLOPT_POSTFIELDS, и снова curl_exec()
Полученный json разбирается, и очередной массив с 1000 целых чисел merge'ится в А или Б.
Пока это всё работает в виде пруф-оф-концепт на shared хостинге руЦентра, где памяти выделено всего ничего. С партиями меньше миллиона скрипт справляется. Больше - вылетает с фатальной ошибкой об исчерпанной памяти. Иногда на этапе получения второго миллиона из сервиса, иногда уже после, на этапе сравнения.
Вместо ф-ий array_merge() и array_intersect() уже использую свои, менее ресурсоёмкие: мне не нужно сортировать и получать само пересечение, достаточно сосчитать кол-во общих.
Не может только массив целых с 2 млн. значений занимать десятки мегов памяти же! Как понять, раздувается ли это cURL при каждом новом обращении? Или, может, массивы хранят значения не как целые по 4 байта, а как строки например?
Сориентируйте, пожалуйста, с оптимизацией по памяти - куда копать?


Ответ

Имхо при ужатой памяти вам проще на БД переложить этот процесс. Работать будет дольше, но памяти есть меньше. Может быть, можно будет даже часть алгоритмов на базу переложить. Далее, в php с памятью такая анархия, что лучше даже не интересоваться. Достаточно сказать, что размер массива всегда степень двойки (в большую сторону), состоит он из указателей(4-8 байт) на int, а int - это структура(имя, тип, размер etc). И далее, если можно обрабатывать все в процессе - do it. Т.е. получили тысячу, обработали, выкинули, погнали дальше. Если нет - БД. Теоретически можно попробовать с временными файлами поколдовать, но вряд ли этот способ сильно выиграет у БД по удобству/скорости.