質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.20%

APNsを送信するためCURLコマンドを打つと"Unexpected HTTP/1.x request"

受付中

回答 1

投稿 編集

  • 評価
  • クリップ 2
  • VIEW 1,626

Namaco705

score 10

iOS端末へのPush通知の送信にどうしても成功できず困っています。
どうもCURLからhttp2での通信が行えていないところまではなんとかわかってきたのですが・・
原因がどうしても特定できないのでなにかご存知のかたいらっしゃいましたらアドバイスいただければ幸いです。

 前提・実現したいこと

サーバーサイドからAPNsのAPIを直接叩いてiOS端末にPush通知を送るためのテストをしたいと考えています。
下記のURLを参考にしてスクリプトを作成して送信テストを行いました。
https://qiita.com/yimajo/items/58565070d39acb4d5e71

 発生している問題・エラーメッセージ

後述するPushのテスト送信用のスクリプトを実際に実行してみると下記のようなレスポンスが返ってきます。

*   Trying 17.188.164.14...
* TCP_NODELAY set
* Connected to api.push.apple.com (17.188.164.14) port 443 (#0)
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Request CERT (13):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Certificate (11):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS handshake, CERT verify (15):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* Server certificate:
*  subject: CN=api.push.apple.com; OU=management:idms.group.533599; O=Apple Inc.; ST=California; C=US
*  start date: Jan  6 00:14:15 2018 GMT
*  expire date: Feb  5 00:14:15 2020 GMT
*  subjectAltName: host "api.push.apple.com" matched cert's "api.push.apple.com"
*  issuer: CN=Apple IST CA 2 - G1; OU=Certification Authority; O=Apple Inc.; C=US
*  SSL certificate verify ok.
> POST /3/device/****************************** HTTP/1.1
> Host: api.push.apple.com
> User-Agent: curl/7.61.1
> Accept: */*
> apns-priority: 10
> apns-expiration: 0
> apns-topic: ******
> Content-Length: 35
> Content-Type: application/x-www-form-urlencoded
> 
* upload completely sent off: 35 out of 35 bytes
* Closing connection 0
* TLSv1.2 (OUT), TLS alert, close notify (256):
Unexpected HTTP/1.x request: POST /3/device/*****

curlのオプションでhttp2を指定しているにもかかわらずHTTP/1.1で送信されていることがわかります。

 該当のソースコード

テスト送信用のスクリプトとして下記をサーバー上で実行しています

#!/bin/sh

pemfile=$1
token=$2
pushData='{"aps": {"alert": "push dev test"}}'

bundleIdentifier="******"

#appleUri="https://api.development.push.apple.com/3/device/"
appleUri="https://api.push.apple.com/3/device/"

curl -v \
-d "$pushData" \
-H "apns-priority: 10" \
-H "apns-expiration: 0" \
-H "apns-topic: ${bundleIdentifier}" \
--cert ${pemfile} \
--http2 \
--output \
- \
${appleUri}${token}

 試したこと

現象の原因がどうしてもわからず、相手サーバー側にある可能性を確認するために、送信先のURLをAPNsではなく、仮にHTTP2のテストサーバーであるという https://nghttp2.org/ に変更して試してみました。
(参考: https://github.com/nghttp2/nghttp2)

すると、こちらのサーバーではhttp2で通信できているように思います。(当然404にはなりますが)

*   Trying 139.162.123.134...
* TCP_NODELAY set
* Connected to nghttp2.org (139.162.123.134) port 443 (#0)
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* NPN, negotiated HTTP2 (h2)
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Next protocol (67):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-ECDSA-AES256-GCM-SHA384
* Server certificate:
*  subject: CN=nghttp2.org
*  start date: Aug 20 00:00:10 2018 GMT
*  expire date: Nov 18 00:00:10 2018 GMT
*  subjectAltName: host "nghttp2.org" matched cert's "nghttp2.org"
*  issuer: C=US; O=Let's Encrypt; CN=Let's Encrypt Authority X3
*  SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x1aab5f0)
> POST /2c0d299877036d25c1015f5318aaeaee0fad1381d043216b61d4bf656016fc12 HTTP/2
> Host: nghttp2.org
> User-Agent: curl/7.61.1
> Accept: */*
> apns-priority: 10
> apns-expiration: 0
> apns-topic: ********
> Content-Length: 35
> Content-Type: application/x-www-form-urlencoded
> 
* Connection state changed (MAX_CONCURRENT_STREAMS == 100)!
* We are completely uploaded and fine
< HTTP/2 404 
< date: Sun, 28 Oct 2018 14:08:41 GMT
< content-type: text/plain; charset=utf-8
< content-length: 9
< x-backend-header-rtt: 0.001965
< strict-transport-security: max-age=31536000
< server: nghttpx
< via: 2 nghttpx
< x-frame-options: SAMEORIGIN
< x-xss-protection: 1; mode=block
< x-content-type-options: nosniff
< 
* Connection #0 to host nghttp2.org left intact

APNsはHTTP/2をベースに通信するとドキュメントにも記載がありますので、
APNsのAPI側が対応していないとは考えづらく、
原因に見当がつかない状態です。

 補足情報(FW/ツールのバージョンなど)

使用している各種ツールのバージョンを記載いたします。
不足などございましたらご指摘いただけえますでしょうか。

root@e6c018ac81eb:/var/www/html# curl --version
curl 7.61.1 (x86_64-pc-linux-gnu) libcurl/7.61.1 OpenSSL/1.0.1t zlib/1.2.8 nghttp2/1.35.0-DEV
Release-Date: 2018-09-05
Protocols: dict file ftp ftps gopher http https imap imaps pop3 pop3s rtsp smb smbs smtp smtps telnet tftp 
Features: AsynchDNS IPv6 Largefile NTLM NTLM_WB SSL libz TLS-SRP HTTP2 UnixSockets HTTPS-proxy 
root@e6c018ac81eb:/var/www/html# openssl version
OpenSSL 1.0.2g  1 Mar 2016
root@e6c018ac81eb:/var/www/html# cat /etc/debian_version
8.10

 追記 2018/10/29

すこしづつわかってきました。
どうもAPNsがHTTP2でもAPLNのみを受け付けており、NPNは受け付けていない様子・・。
そのせいでAPLNに対応していない環境からの通信がHTTP1.1になってしまっている。
とはいえ、OpenSSL1.0.2を入れたので、APLNに対応したCURLが入っているはずなのですが・・
さらに調査中です・・

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

0

利用されていたPHPのバージョンはいくつでしょうか?
The CURL extension for PHP >= 5.5.24 has support for HTTP/2
とあります。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.20%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる