skip to Main Content

I stumbled over a weird behavior when I try to send a post HTTP/2.0 request to apples push service:

        $http2ch = curl_init();
        curl_setopt($http2ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0);
        curl_setopt($http2ch, CURLOPT_URL, 'https://api.push.apple.com/3/device/megauniquedevicetokendummy');
        curl_setopt($http2ch, CURLOPT_PORT, 443);
        curl_setopt($http2ch, CURLOPT_HTTPHEADER, $httpHeader);
        curl_setopt($http2ch, CURLOPT_POST, true);
        curl_setopt($http2ch, CURLOPT_POSTFIELDS, $body);
        curl_setopt($http2ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($http2ch, CURLOPT_TIMEOUT, 30);
        curl_setopt($http2ch, CURLOPT_HEADER, 1);

       $result = curl_exec($http2ch);
       if ($result === false) {
           throw new Exception("Curl failed: " . curl_error($http2ch) . " | " . curl_getinfo($http2ch, CURLINFO_HTTP_CODE));
       }

The exception is thrown with the Message:
Curl failed: Received HTTP/0.9 when not allowed | 0

I explicitly told curl to use HTTP/2.0 on the second line of the code snipped above.
Does anyone have any idea what that error message means and why curl uses such an old HTTP version?

I am on PHP 7.2 and curl version 7.66.0.

3

Answers


  1. Chosen as BEST ANSWER

    I figured it out. Make sure that curl is compiled with nghttp2.

    If you are unsure, you can check it on your terminal using curl --version

    If you dont find nghttp2/{version} you need to compile curl again with nghttp2.

    curl --version example where nghttp2 is missing:

    curl 7.66.0 (amd64-portbld-freebsd12.0) libcurl/7.66.0 OpenSSL/1.1.1d zlib/1.2.11
    

    curl --version example where nghttp2 is available:

    curl 7.64.1 (x86_64-apple-darwin19.0) libcurl/7.64.1 (SecureTransport) LibreSSL/2.8.3 zlib/1.2.11 nghttp2/1.39.2
    

  2. I do not believe it requires you to have a version of curl compiled differently, but rather set the option to allow http 0.9 as a response from your older server. PHP has some notes on "CURLOPT_HTTP09_ALLOWED" that may have differed when you posted your question via https://www.php.net/manual/en/function.curl-setopt.php

    The option that overcame the error for me was:

    curl_setopt($http2ch, CURLOPT_HTTP09_ALLOWED, true);
    
    Login or Signup to reply.
  3. This can also happen when the server is a grpc server. When curl is run against a grpc server or other non-HTTP server that doesn’t respond with a valid HTTP status line that curl expects, curl will print the "Received HTTP/0.9 when not allowed".

    It might be better if curl printed something like "unknown protocol" rather than assuming it is 0.9 because hitting something like a grpc server these days is going to be far more common than an actual HTTP 0.9 server.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search