Ir para conteúdo

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

Guilherme Luiz

Requisições GET assincronas com cURL

Recommended Posts

Olá pessoal,

 

Vamos abaixo:
 

Meu carma

Possuo uma aplicação que faz requisições a uma API em Rest via cURL.

Durante o consumo desta API eu tenho diversas requisições e variaveis paralelas que fazem validação, inserção e edição de dados no banco de dados.

Durante este processo, mesmo realizando a utilização de PHP + AngularJS a requisição até ser finalizada, deixa a pagina travada até que venha um response final da API requisitada.

 

Possíveis técnicas a serem utilizadas

Estive estudando algumas técnicas de threading sockets, porem o servidor atual que utilizo não possui acesso a biblioteca pthreads para o threading e a utilização via socket não consegui compreender e faze-la funcionar rsrs.

 

O que estou aplicando

Fazendo alguns testes, percebi que ao aplicar o cURL com um timeout de 1 segundo "resolve" o problema porque desta forma realizo o fluxo:

 

  1. Capturo todos os dados que serão enviados a API
  2. Salvo dados capturados no BD (mysqli)
  3. Faço a requisição via cURL com timeout em 1 segundo para um script que fará a leitura destes dados pendentes de envio a API
  4. Com os dados capturados, faço a requisição a API e então salvo o retorno e faço as devidas validações ao meu BD em "segundo plano".

 

De ante mão já reparei um "problema" que é justamente na requisição cURL com timeout em 1 segundo porque, uma vez que faço isso eu não tenho um retorno do meu script se ele foi requisitado ou não porque nem o http_code consigo recuperar para poder fazer qualquer tratativa e além disso também acredito que terei problemas no momento que o navegador do usuário atualizar porque a requisição feita será stopada e os dados serão salvos de forma parcial. Então, além destes problemas, temos algum outro "contra" a utilizar desta forma? Ao meu ver o que estou fazendo é mais uma gambiarra do que um código bem executado.

 

O que eu preciso

Uma orientação de como e qual a melhor técnica, tendo em vista minhas limitações de servidor citada acima (em relação ao pthreads), para poder realizar essa requisição GET de forma assíncrona.

 

cURL "async" que estou utilizando

error_reporting(E_ALL);

$url = "www.meusite.com.br/pending/read.php";

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 0);
curl_setopt($ch, CURLOPT_NOSIGNAL, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_AUTOREFERER, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
$result   = curl_exec($ch);

if($result){
  var_dump(curl_getinfo($ch));
}else{
  var_dump(curl_error($ch));
  var_dump(curl_getinfo($ch));
}
var_dump($result);
curl_close($ch);

 

Compartilhar este post


Link para o post
Compartilhar em outros sites

Pessoal,

 

Consegui realizar via socket o que preciso vejam o exemplo:

error_reporting(E_ALL);

/* Get the port for the WWW service. */
$service_port = getservbyname('www', 'tcp');

/* Get the IP address for the target host. */
$url     = parse_url("https://www.meusite.com.br/read.php");
$address = gethostbyname($url['host']);

/* Create a TCP/IP socket. */
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($socket === false) {
    echo "socket_create() failed: reason: " . socket_strerror(socket_last_error()) . "\n";
} else {
    echo "OK.\n";
}

echo "Attempting to connect to '$address' on port '$service_port'...";
$result = socket_connect($socket, $address, $service_port);
if ($result === false) {
    echo "socket_connect() failed.\nReason: ($result) " . socket_strerror(socket_last_error($socket)) . "\n";
} else {
    echo "OK.\n";
}

$in = "GET {$url['path']} HTTP/1.1\r\n";
$in .= "Host: {$url['host']}\r\n";
$in .= "Connection: Close\r\n\r\n";
$out = '';

echo "Sending HTTP HEAD request...";
socket_write($socket, $in, strlen($in));
echo "OK.\n";

// echo "Reading response:\n\n";
// while ($out = socket_read($socket, 2048)) {
//     echo $out;
// }

echo "Closing socket...";
socket_close($socket);
echo "OK.\n\n";

Peguei este código do proprio manual do PHP.

Neste modelo eu posso optar por não ler o response que o servidor roda em "segundo-plano" a requisição em GET e tenho o resultado esperado mesmo quando o navegador é fechado e o servidor não "trava" a navegação do usuário.

 

De todas as formas, gostaria de comentários de quem entende um pouco mais sobre estes tipos de requisições para poder me ajudar na formação da logica com foco em melhor desempenho.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Lendo a sua descrição de problema, mais me parecia um lock de sessão, que se resolve utilizando session_write_close.

 

Valide seu código anterior, antes de realizar as requisições "pesadas" e após realizar todas as modificações em $_SESSION, adicione a função session_write_close. 

Compartilhar este post


Link para o post
Compartilhar em outros sites

  • Conteúdo Similar

    • Por gustavopinent
      Olá! Esse erro ocorre em um php simples rodando em um servidor compartilhado Locaweb: SSL certificate problem: unable to get local issuer certificate. O php faz uma requisição ao site do Cep Aberto para consulta de endereço informando o CEP (https://www.cepaberto.com/api/v3/cep?cep=95020520)
       
      Olhei o php.ini e não tem nenhuma menção ao arquivo de certificados. Então peguei alguns tutoriais, baixei o arquivo "cacert.pem", coloquei lá e defini o curl no próprio php, ficou assim:
      $ch = curl_init($url); curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Token token="' . $token . '"']); curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); curl_setopt($ch, CURLOPT_CAINFO, $cacert); curl_setopt($ch, CURLOPT_CAPATH, $cacert); $res = curl_exec($ch); if($res===FALSE) { $Res["erro"] = "curl"; $Res["msg"] = "Execução CURL falhou!"; $Res["descr"] = curl_error($ch); } else { $Res["dados"] = json_decode($res); $Res["http"] = curl_getinfo($ch, CURLINFO_HTTP_CODE); $Res["erro"] = ($Res["http"]==200)? "OK" : "http" ; $Res["msg"] = ($Res["http"]==200)? "" : "Erro HTTP ".$Res["http"] ; } Onde $cacert é o endereço do arquivo "cacert.pem", verificado antes por is_file. Mas o erro é o mesmo, como se eu nada tivesse feito. Tem que configura o Apache? Não sei como configurar o Apache, será que posso? Desabilitar o SSL do php é uma opção que não tentei ainda, dizem que não é aconselhável...
       
      O PHP é o 5.6 (pretendo ir pro 7.4 em breve) e o servidor é CENTOS 5.11 compartilhado, hospedagem Locaweb.
       
      Alguma ideia? 
    • Por Wanderson Moreira
      Bom dia,
      alguém pode me ajudar com uma situação?
      estou utilizando um script pra fazer o carregamento assíncrono do site.
      var links = document.querySelectorAll('a'); function handleClick(event) { event.preventDefault(); fetchPage(event.target.href); window.history.pushState(null, null, event.target.href); window.scrollTo(0, 0); } async function fetchPage(url) { document.querySelector('.content'); var pageResponse = await fetch(url); var pageText = await pageResponse.text(); replaceContent(pageText); } function replaceContent(newText) { var newHtml = document.createElement('div'); newHtml.innerHTML = newText; var oldContent = document.querySelector('.content'); var newContent = newHtml.querySelector('.content'); oldContent.innerHTML = newContent.innerHTML; document.title = newHtml.querySelector('title').innerText; } window.addEventListener('popstate', () => { fetchPage(window.location.href); }) links.forEach(link => { link.addEventListener('click', handleClick); }) O problema em questão é que, o conteúdo da pagina que é carregado dentro da div content não funciona corretamente
       
      os scripts em javascript não são executados;
      os links de navegação da pagina não funcionam de maneira assincrona, diferente dos links de navegação do menu
       
       
    • Por Wyrv
      Boa tarde pessoal, 

      Sou meio novo em programação web.
      Estou com o seguinte problema, qualquer ajuda será bem vinda.

      Em PHP, etou montando uma URL pra ser acessada com o comando Curl. 
      Tudo está funcionando, consigo executar e receber o retorno da URL no meu script.

      Porém o retorno parece vir em html, e a resposta que eu quero estar está no meio de tudo.
       
      <form name="IntegracaoForm" method="post" action="/integracao.do;jsessionid=C221B55C9AF93E1A94403FAA52943FB0" enctype="multipart/form-data" id="IntegracaoForm"> <table > <tbody> <tr> <td> 000 </td> </tr> </tbody> </table> </form><br>FIM<br>-> <br /> O código de retorno vem onde está o 000.
      No caso eu preciso validar esse retorno, mas eu não estou conseguindo uma forma de jogar esse valor pra uma variável pra realizar um if.

      Alguém pode me dar alguma ideia?

      Agradeço desde já.
       
    • Por arlindophp
      <?php
       
      function doPut($url, $fields)
      {
          $fields = (is_array($fields)) ? http_build_query($fields) : $fields;
       
          if ($ch = curl_init($url)) {
              curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
              curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
              curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Length: ' . strlen($fields)));
              curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);
              curl_exec($ch);
              //$resp = curl_exec($ch);
       
              $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
       
              curl_close($ch);
       
              return (int) $status;
          } else {
              return false;
          }
      }
       
      session_start();
      $s_chave = $_POST['edtChave'];
      $_SESSION['s_chave'] = $s_chave;
      $edtChave = $_POST['edtChave'];
       
      $edtCultura = $_POST['edtCultura'];
      $edtPraga = $_POST['edtPraga'];
      $edtDose = $_POST['edtDose'];
      $edtEspecificacao = $_POST['edtEspecificacao'];
      $edtAplicaTerrestre = $_POST['edtAplicaTerrestre'];
      $edtAplicarea = $_POST['edtAplicarea'];
      $edtIntseg = $_POST['edtIntseg'];
      $edtIntEntrada = $_POST['edtIntEntrada'];
      $edtDadosGerais = $_POST['edtDadosGerais'];
       
      $url = "www.api.site.com";
      echo 'Url = ' . $url;
      echo '<br>';
       
          $data_array2 = array();
          for ($i = 0; $i < 5; $i++) {
              $montagem_array = array(
                  'cultura' => $_POST['edtCultura'],
                  'praga' => $_POST['edtPraga'],
                  'dose' => $_POST['edtDose'],
                  'especificacao' => $_POST['edtEspecificacao'],
                  'aplicaterrestre' => $_POST['edtAplicaTerrestre'],
                  'aplicaerea' => $_POST['edtAplicarea'],
                  'intseg' => $_POST['edtIntseg'],
                  'intentrada' => $_POST['edtIntEntrada'],
                  'dadosgerais' => $_POST['edtDadosGerais'],
              );
       
              $data_array2[$i] = $montagem_array;
          }
       
          //$json = json_encode($data_array2);
       
      echo '<br>';
      echo 'Array convertido para formato json: ' . json_encode($data_array2);
      echo '<br>';
      //$data = $array_para_string;
      //echo $data.'+cultura=asdf&praga=asdf&dose=dasf&especificacao=sadf&aplicaterrestre=sadf&aplicaerea=asdf&intseg=2&intentrada=1&dadosgerais=sdaf';
       
      $header = array(
          'Authorization: falkdsjçlaskf'
       
      );
       
      //Nova tentativa 07/01/2022
      if (doPut($url, $data_array2) == 200) {
       
          echo 'Passou!';
          echo '<br>';
          echo json_encode($data_array2);
          echo '<br>';
      }
      // do something
      else {
          echo 'Não deu certo';
          echo '<br>';
          echo json_encode($data_array2);
          echo '<br>';
      }
      //Nova tentativa
       
      //header('location:jsonpostprodutobula_teste.php');
    • Por arlindophp
      <?php
       
      function doPut($url, $fields)
      {
          $fields = (is_array($fields)) ? http_build_query($fields) : $fields;
       
          if ($ch = curl_init($url)) {
              curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
              curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
              curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Length: ' . strlen($fields)));
              curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);
              curl_exec($ch);
              //$resp = curl_exec($ch);
       
              $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
       
              curl_close($ch);
       
              return (int) $status;
          } else {
              return false;
          }
      }
       
      session_start();
      $s_chave = $_POST['edtChave'];
      $_SESSION['s_chave'] = $s_chave;
      $edtChave = $_POST['edtChave'];
       
      $edtCultura = $_POST['edtCultura'];
      $edtPraga = $_POST['edtPraga'];
      $edtDose = $_POST['edtDose'];
      $edtEspecificacao = $_POST['edtEspecificacao'];
      $edtAplicaTerrestre = $_POST['edtAplicaTerrestre'];
      $edtAplicarea = $_POST['edtAplicarea'];
      $edtIntseg = $_POST['edtIntseg'];
      $edtIntEntrada = $_POST['edtIntEntrada'];
      $edtDadosGerais = $_POST['edtDadosGerais'];
       
      $url = "www.api.site.com";
      echo 'Url = ' . $url;
      echo '<br>';
       
          $data_array2 = array();
          for ($i = 0; $i < 5; $i++) {
              $montagem_array = array(
                  'cultura' => $_POST['edtCultura'],
                  'praga' => $_POST['edtPraga'],
                  'dose' => $_POST['edtDose'],
                  'especificacao' => $_POST['edtEspecificacao'],
                  'aplicaterrestre' => $_POST['edtAplicaTerrestre'],
                  'aplicaerea' => $_POST['edtAplicarea'],
                  'intseg' => $_POST['edtIntseg'],
                  'intentrada' => $_POST['edtIntEntrada'],
                  'dadosgerais' => $_POST['edtDadosGerais'],
              );
       
              $data_array2[$i] = $montagem_array;
          }
       
          //$json = json_encode($data_array2);
       
      echo '<br>';
      echo 'Array convertido para formato json: ' . json_encode($data_array2);
      echo '<br>';
      //$data = $array_para_string;
      //echo $data.'+cultura=asdf&praga=asdf&dose=dasf&especificacao=sadf&aplicaterrestre=sadf&aplicaerea=asdf&intseg=2&intentrada=1&dadosgerais=sdaf';
       
      $header = array(
          'Authorization: falkdsjçlaskf'
       
      );
       
      //Nova tentativa 07/01/2022
      if (doPut($url, $data_array2) == 200) {
       
          echo 'Passou!';
          echo '<br>';
          echo json_encode($data_array2);
          echo '<br>';
      }
      // do something
      else {
          echo 'Não deu certo';
          echo '<br>';
          echo json_encode($data_array2);
          echo '<br>';
      }
      //Nova tentativa
       
      //header('location:jsonpostprodutobula_teste.php');
×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.