title: Sending HTTP/2 request to Apple Push Notification Service using HttpClient, Client Certificate and WinHttpHandler raises HttpRequestException
body: <p>I am trying to write some code to send a push notification to an iPhone using C# .NET and HttpClient over HTTP with client certificate authentication.</p>
  <p>Code compiles but always yields a:</p>
  <p>HttpRequestException with Message &quot;Error while copying content to a stream.&quot;</p>
  <p>InnerException IOException Message &quot;The write operation failed, see inner exception.&quot;</p>
  <p>InnerException WinHttpException Message &quot;{&quot;Error 12152 calling WinHttpWriteData, 'The server returned an invalid or unrecognized response'.&quot;}&quot;</p>
  <p>I am looking for why the code is failing?</p>
  <p>Is it possible to debu/troubleshoot this in some way?</p>
  <p>Here is my code</p>
  <pre><code>class Program {
      private const string cert = &quot;MIINKwI....&lt;hidden&gt;&quot;;
      private const string certpw = &quot;password&quot;;
      private const string devicetoken = &quot;921c95b6494828f973512f2327478b0&lt;hidden&gt;&quot;;
      private const string bundleid = &quot;se.jensolsson.testapp&quot;;
  
      private static HttpClient client = null;
      static async Task Main(string[] args) {
          try {
  
              byte[] certificateData = Convert.FromBase64String(cert);
              X509Certificate2 certificate = new X509Certificate2(certificateData, certpw, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet);
  
              string url = &quot;https://api.push.apple.com:443/3/device/&quot;;
  
              string payload = @&quot;{&quot;&quot;aps&quot;&quot;:{&quot;&quot;alert&quot;&quot;:&quot;&quot;Test&quot;&quot;}}&quot;;
  
              var handler = new WinHttpHandler();
              handler.ClientCertificates.Add(certificate);
  
              if (client == null)
                  client = new HttpClient(handler);
  
              using (var request = new HttpRequestMessage(HttpMethod.Post, url + devicetoken)) {
                  var messageGuid = Guid.NewGuid().ToString();
                  request.Version = new Version(&quot;2.0&quot;);
                  request.Content = new StringContent(payload);
                  request.Headers.Add(&quot;apns-id&quot;, messageGuid);
                  request.Headers.Add(&quot;apns-push-type&quot;, &quot;alert&quot;);
                  request.Headers.Add(&quot;apns-priority&quot;, &quot;10&quot;);
                  request.Headers.Add(&quot;apns-topic&quot;, bundleid);
  
  
                  using (var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead)) {
                      HttpStatusCode statusCode = response.StatusCode;
                      string reasonPhrase = response.ReasonPhrase;
                      bool success = response.IsSuccessStatusCode;
                  }
              }
  
          }
          catch (ArgumentNullException anu) { }
          catch (InvalidOperationException ioe) { }
          catch (HttpRequestException hre) { }
          catch (TaskCanceledException tce) { }
          catch (Exception e) { }        
      }
  }
  </code></pre>
  <p><strong>EDIT</strong> @jdweng actually tried Wireshark but since it is over SSL and encrypted I would expect it to be unreadable from Wireshark? What I can see is that the connection is reset from our client, must be done by the underlying framework.</p>
  <p><a href="https://i.stack.imgur.com/Mit9O.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/Mit9O.png" alt="Wireshark" /></a></p>
  <p><strong>EDIT 2:</strong>
  Investigating further. Tried to connect to an open HTTP2 capable web server. I used <a href="https://nghttp2.org/" rel="nofollow noreferrer">https://nghttp2.org/</a> as an example.</p>
  <ol>
  <li>Replaced url line to <code>string url = &quot;https://nghttp2.org/&quot;;</code></li>
  <li>replaced request line to <code>using (var request = new HttpRequestMessage(HttpMethod.Get, url)) {</code>.</li>
  </ol>
  <p>A very interesting finding is that even though i send a HTTP/2 request and it seem to give a reply, looking at the response object, <strong>Version is set to 1.1</strong>.</p>
  <p>If I also remove the <code>handler.ClientCertificates.Add(certificate);</code> line and retry, looking at the response object, <strong>Version is correctly set to 2.0</strong>.</p>
  <p>So it seem like WinHttpHandler drops HTTP/2 support as soon as a client certificate is added to the handler.</p>
  <p><strong>EDIT 3:</strong>
  I now assume this is a bug in the framework and I have posted a bug report here: <a href="https://github.com/dotnet/runtime/issues/40794" rel="nofollow noreferrer">https://github.com/dotnet/runtime/issues/40794</a></p>