【问题标题】:Invalid Http response on opening a connection to APNS using its HTTP API使用其 HTTP API 打开与 APNS 的连接时的 Http 响应无效
【发布时间】:2016-02-07 19:23:56
【问题描述】:

我正在编写一个模块,用于使用 APNs 使用其新的 HTTP 提供程序 API 向 IOS 设备发送推送通知。但是我在从响应中读取输出的过程中遇到了某些问题。它抛出了一个无效的 http 响应错误。以下是我写的一段代码:

static SSLSocketFactory getSSLSocketFactory() {
        try {
            String keystoreFilename = "D:/Oracle/IDCS/MFA/APNS/OMA_prereqs/iOS_prod.p12";
            char[] storepass = "welcome1".toCharArray();
            FileInputStream fis = new FileInputStream(
                    new File(keystoreFilename));

            final KeyStore ks = KeyStore.getInstance("PKCS12");
            ks.load(fis, storepass);

            KeyManagerFactory keyManagerFactory = KeyManagerFactory
                    .getInstance("SunX509");
            keyManagerFactory.init(ks, storepass);

            TrustManagerFactory trustManagerFactory = TrustManagerFactory
                    .getInstance("SunX509");
            trustManagerFactory.init((KeyStore) null);
            // trustManagerFactory.init(ks);

            // create ssl context
            SSLContext sslContext = SSLContext.getInstance("TLSv1.2");


            // setup the HTTPS context and parameters
            sslContext.init(keyManagerFactory.getKeyManagers(),
                    trustManagerFactory.getTrustManagers(), null);

            if (keyManagerFactory != null || trustManagerFactory != null) {
                return SSLTunnelSocketFactory.wrap(proxy,
                        sslContext.getSocketFactory());
            }
        } catch (Exception e) {
            System.out.println("Unable to create ssl socket factory");
            e.printStackTrace();
        }
        return HttpsURLConnection.getDefaultSSLSocketFactory();
    }  

    private static void sendSamplePushNotification() {
                System.setProperty("javax.net.debug", "all");
                URL url = null;
                try {
                    HostnameVerifier hv = new HostnameVerifier() {
                        public boolean verify(String urlHostName, SSLSession session) {
                            return true;
                        }
                    };
                    JSONObject payload = new JSONObject();
                    JSONObject msg = new JSONObject();
                    try {
                        msg.put("alert", "Hello APNS");
                        payload.put("aps", msg);
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                    url = new URL(
                            "https://api.development.push.apple.com:443/3/device/00fc13adff785122b4ad28809a3420982341241421348097878e577c991de8f0");
                    HttpsURLConnection conn = (HttpsURLConnection) url
                            .openConnection(proxy);
                    conn.setRequestMethod("POST");
                    conn.setDoOutput(true);
                    conn.setHostnameVerifier(hv);
                    conn.setSSLSocketFactory(getSSLSocketFactory());
                    /*conn.setRequestProperty("content-length", new String(payload
                            .toString().getBytes()));*/
                    conn.setConnectTimeout(3000);
                    conn.connect();
                    OutputStream os = conn.getOutputStream();
                    OutputStreamWriter writer = new OutputStreamWriter(os);
                    BufferedWriter bw = new BufferedWriter(writer);
                    bw.write(payload.toString());
                    bw.flush();
                    //System.out.println("Response code : " + conn.getResponseCode());
                    System.out.println(conn.getResponseMessage());
                    InputStream is = conn.getInputStream();
                    ................
            }

我在执行此操作时遇到以下异常:

.............................
     ...............................
    main, WRITE: TLSv1.2 Alert, length = 26
[Raw write]: length = 31
0000: 15 03 03 00 1A 00 00 00   00 00 00 00 04 75 ED 66  .............u.f
0010: D6 88 EC E2 B4 8F FF A2   7E CC 1C 22 FF A7 EF     ..........."...
main, called closeSocket(true)
null
java.io.IOException: Invalid Http response
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
    at sun.net.www.protocol.http.HttpURLConnection$10.run(HttpURLConnection.java:1889)
    at sun.net.www.protocol.http.HttpURLConnection$10.run(HttpURLConnection.java:1884)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.net.www.protocol.http.HttpURLConnection.getChainedException(HttpURLConnection.java:1883)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1456)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1440)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:254)
    at com.coding.mfa.apns.driver.APNSDriver.sendSamplePushNotification(APNSDriver.java:141)
    at com.coding.mfa.apns.driver.APNSDriver.main(APNSDriver.java:38)
Caused by: java.io.IOException: Invalid Http response
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1554)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1440)
    at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480)
    at java.net.HttpURLConnection.getResponseMessage(HttpURLConnection.java:546)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseMessage(HttpsURLConnectionImpl.java:382)
    at com.coding.mfa.apns.driver.APNSDriver.sendSamplePushNotification(APNSDriver.java:140)
    ... 1 more

有人可以帮帮我吗? SSL握手似乎很好。它在'conn.getInputStream()'行失败

【问题讨论】:

  • 请添加完整的异常文本。此外,如果您要使用调试来查明代码中断的位置,这将有所帮助。
  • @RoyFalk 我已经用完整的异常堆栈跟踪编辑了这个问题。你能帮帮我吗?同样具有讽刺意味的是,从 PostMan 休息客户端,我能够成功发送推送通知请求并在我的设备上接收。
  • 你考虑过 Pushy relayrides.github.io/pushy 吗?或者也许使用源代码作为灵感..

标签: java https apple-push-notifications


【解决方案1】:

来自“APNs Provider API”文档:“此 API 基于 HTTP/2 网络协议”。 Java 目前不支持 HTTP/2。预计 Java 9 会带来对 HTTP/2 的支持。 您需要使用第三方 http 客户端,建议如下:Does Apache or some other CLIENT JAVA implementation support HTTP/2?

【讨论】:

  • 谢谢 Paulo,经过一段时间的谷歌搜索后,我得到了答案。无论如何,在我们的项目中,我们继续使用 APNS 二进制提供程序 API 来发送通知。
【解决方案2】:

首先,我作为新问题的审阅者添加了评论。堆栈跟踪增加了有人发现它的机会。

其次,如果您能查明导致崩溃的行会有所帮助,因为堆栈跟踪没有列出您的代码(也许还有 1 个?)。请注意,与空指针不同,无效的 HTTP 响应不一定是您的代码的问题。这导致我...

第三,我写这篇文章作为答案的原因,对于 Java,它可能是 cookie。试试:

CookieManager cookieManager = new CookieManager();
CookieHandler.setDefault(cookieManager);

第四,如果一切都失败了,你需要弄清楚邮递员和java代码中的任何东西之间的区别。 wireshark 或类似的工具可能会成功。

更新: This SuperUser 上的帖子似乎表明 Java 7 默认禁用 TLS1.2。

我看到您正在发送 TLS1.2。如果您使用的是 Java 7,似乎有一个 bug affecting updates 25 and above

【讨论】:

  • 它在'InputStream is = conn.getInputStream();'这一行失败
  • 这是意料之中的。我的意思是您应该将其添加到问题中,因为在其他情况下,很难判断堆栈跟踪何时不完整。你试过我的建议了吗?
  • 我已经在它末尾的问题中提到了失败的行本身。谈到你建议的选项,我已经尝试了第三个选项,但我仍然遇到了这个问题第 4 个我正在使用 fiddler 调试网络流量。请求和响应在工具输出中似乎很好,但我仍然在 java 代码中遇到相同的错误。
猜你喜欢
  • 2016-05-04
  • 1970-01-01
  • 1970-01-01
  • 2015-04-29
  • 2015-02-13
  • 1970-01-01
  • 2019-03-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多