z3nth10n
z3nth10n

Reputation: 2441

CURLOPT_STDERR is always executed?

Well, I'm having troubles making requests to the Discord API, I'm not understanding how curl is working.

This is my code:

function make_request($mixed, $token, $get_json = true) {
    $url = is_string($mixed) ? $mixed : getApiUrl($mixed);
    // TODO: Check for valid url!

    $log_file = __DIR__.'/../logs/request.txt';
    if(!is_readable($log_file)) printError("File '$log_file' is not readable!");
    if(!is_writable($log_file)) printError("File '$log_file' is not writable!");

    $ch = curl_init();
    $f = fopen($log_file, 'w+');

    if($f === false) printError("There was an error opening '$log_file'!");
    ftruncate($f, 0);

    curl_setopt_array($ch, array(
        CURLOPT_URL            => $url, 
        CURLOPT_HTTPHEADER     => array('Authorization: Bot ' . $token), 
        CURLOPT_RETURNTRANSFER => 1,
        CURLOPT_FOLLOWLOCATION => 1,
        CURLOPT_VERBOSE        => 1,
        CURLOPT_SSL_VERIFYPEER => 0,
        CURLOPT_STDERR         => $f,
    ));

    $response = curl_exec($ch);
    fclose($f);
    curl_close($ch);

    $contents = file_get_contents($log_file);
    if($contents != '') 
    {
        // Censor bot key!
        $contents = preg_replace("/^Authorization: Bot.+?$/", "Authorization: Bot xxx", $contents);
        printError($contents);
    }

    if($get_json) {
        $pretty = isset($_GET["pretty"]);

        if($pretty) {
            $json = json_decode($response);
            return json_encode($json, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
        }

        return $response;
    }

    return json_decode($response, true);
}

And this is my output:

[OuterException] System.Exception: * Hostname in DNS cache was stale, zapped
*   Trying 162.159.135.233...
* TCP_NODELAY set
* Connected to discordapp.com (162.159.135.233) port 443 (#0)
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: /etc/ssl/certs
* SSL connection using TLSv1.2 / ECDHE-ECDSA-AES128-GCM-SHA256
* ALPN, server accepted to use http/1.1
* Server certificate:
*  subject: CN=ssl711320.cloudflaressl.com
*  start date: Feb 13 00:00:00 2020 GMT
*  expire date: Aug 21 23:59:59 2020 GMT
*  subjectAltName: host "discordapp.com" matched cert's "discordapp.com"
*  issuer: C=GB; ST=Greater Manchester; L=Salford; O=COMODO CA Limited; CN=COMODO ECC Domain Validation Secure Server CA 2
*  SSL certificate verify ok.
> GET /api/guilds/479096180601782274 HTTP/1.1
Host: discordapp.com
Accept: */*
Authorization: Bot ...

< HTTP/1.1 200 OK
< Date: Thu, 20 Feb 2020 17:49:15 GMT
< Content-Type: application/json
< Transfer-Encoding: chunked
< Connection: keep-alive
< Set-Cookie: __cfduid=ddfc25d7448507e06474f24ff3e8352381582220955; expires=Sat, 21-Mar-20 17:49:15 GMT; path=/; domain=.discordapp.com; HttpOnly; SameSite=Lax
< Strict-Transport-Security: max-age=31536000; includeSubDomains
< Via: 1.1 google
< Alt-Svc: clear
< CF-Cache-Status: DYNAMIC
< Set-Cookie: __cfruid=66721d8d16cd42e4884dc62afe94705cbf1e21df-1582220955; path=/; domain=.discordapp.com; HttpOnly; Secure; SameSite=None
< Expect-CT: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
< Server: cloudflare
< CF-RAY: 568250ea9fe2a861-CDG
<
* Curl_http_done: called premature == 0
* Connection #0 to host discordapp.com left intact

   en DiscordIdCrawler.Lib.Core.ApiWorker.CheckForErrors(Object response) en E:\PHP\discord-flooder-bot\client\DiscordIdCrawler\DiscordIdCrawler.Lib\Core\ApiWorker.cs:línea 152
   en DiscordIdCrawler.Lib.Core.ApiWorker.GetServerName(Int64 serverId) en E:\PHP\discord-flooder-bot\client\DiscordIdCrawler\DiscordIdCrawler.Lib\Core\ApiWorker.cs:línea 312
   en DiscordIdCrawler.Lib.Core.DriverWorker.GoToServer(IWebDriver web, Int32 serverNum, Boolean storeOnDB) en E:\PHP\discord-flooder-bot\client\DiscordIdCrawler\DiscordIdCrawler.Lib\Core\DriverWorker.cs:línea 141

My question is that maybe I'm printing an error when curl is just showing a verbosed log, but I'm not sure if the CURLOPT_STDERR is used to print errors or the entire log.

On the docs: https://www.php.net/manual/en/function.curl-setopt.php

An alternative location to output errors to instead of STDERR.

Maybe is because CURLOPT_VERBOSE is enabled.

TRUE to output verbose information. Writes output to STDERR, or the file specified using CURLOPT_STDERR.

On that case, I need to know when an error happens. Any tip here?

Upvotes: 1

Views: 1070

Answers (1)

bishop
bishop

Reputation: 39354

You're on the right track. If you want the diagnostic output, you have to arrange to capture it before you make your request. The usual way to do this is by storing it in RAM, checking for curl error, and handling appropriately.

That code looks like:

$ch = curl_init();
curl_setopt_array($ch, [
    // ... other options here
    CURLOPT_RETURNTRANSFER => 1,
    CURLOPT_VERBOSE => 1,
    CURLOPT_STDERR => ($log = fopen('php://temp', 'w')),
]);
$response = curl_exec($ch);
if (false === $response) {
    $errno = curl_error($ch);
    $errmsg = curl_strerror($errno);
    $logtext = stream_get_contents($log, -1, 0);
    // ... log the info above, take action, etc.
} else {
    // ... $response is your HTTP response
}
curl_close($ch);

Upvotes: 1

Related Questions