2015-07-26 16 views
5

Sto implementando un servlet in un Jetty integrato (9.3.0.v20150612) e vorrei usare HTTP/2.Embedded Jetty HTTP/2 non funziona con Firefox/Chrome ma sembra ok con Safari

Sto abilitando ALPN per la negoziazione del protocollo per selezionare HTTP 1.1 o HTTP2. Quando invio una richiesta HTTP al mio servlet da Safari 8 (supporta solo HTTP1.1) o Safari 9 (supporta HTTP1.1 & HTTP2) Ricevo una risposta dal mio servlet. Quando eseguo la stessa richiesta da Firefox 39, non funziona e ottengo solo NS_ERROR_ABORT. Ho lo stesso problema con Chrome.

Ho due domande:

  1. Perché non ho ricevuto risposta da Chrome & Firefox
  2. Come faccio a sapere se con Safari 9, HTTP/2 è stato usato al posto di HTTP1.1? (Il mio IOS9 App è anche il collegamento senza alcun problema)

Di seguito si riporta il codice per eseguire l'inizializzazione del molo

private void startHTTP2Server() { 
    WebServerProperties webProperties = WebServerProperties.getInstance(); 

    HttpConfiguration config = getHttpConfiguration(); 

    HttpConnectionFactory http1 = new HttpConnectionFactory(config); 
    HTTP2ServerConnectionFactory http2 = new HTTP2ServerConnectionFactory(config); 

    NegotiatingServerConnectionFactory.checkProtocolNegotiationAvailable(); 
    ALPNServerConnectionFactory alpn = new ALPNServerConnectionFactory(); 
    alpn.setDefaultProtocol(http1.getProtocol()); // sets default protocol to HTTP 1.1 

    // SSL Connection Factory 
    SslContextFactory sslContextFactory = new SslContextFactory(); 
    sslContextFactory.setKeyStorePath(webProperties.getKeystore()); 
    sslContextFactory.setKeyStorePassword(webProperties.getKeystorePassword()); 
    //sslContextFactory.setKeyManagerPassword(KEYSTORE_PW); 
    //sslContextFactory.addExcludeCipherSuites(".*RC4.*"); 
    //sslContextFactory.addExcludeCipherSuites("TLS_DHE_RSA.*"); 
    sslContextFactory.setProtocol(webProperties.getTLSVersion()); // SEB 
    SslConnectionFactory ssl = new SslConnectionFactory(sslContextFactory, alpn.getProtocol()); 

    Server server = new Server(); 
    //ServerConnector connector = new ServerConnector(server, ssl, alpn, http2, http1); 
    ServerConnector connector = new ServerConnector(server, ssl, alpn, http2, http1); 
    connector.setPort(webProperties.getPort()); 
    server.addConnector(connector); 

    // --- SEB 
    ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); 
    context.setContextPath(webProperties.getServletContext()); 
    context.setResourceBase(System.getProperty(webProperties.getServletTmpDir())); 
    server.setHandler(context); 

    // Add dump servlet 
    context.addServlet(IMonServer.class, webProperties.getServletPath()); 

    try { 
     server.start(); 
     server.join(); 
    } catch (Exception e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
} 

private static HttpConfiguration getHttpConfiguration() { 
    WebServerProperties webProperties = WebServerProperties.getInstance(); 
    HttpConfiguration config = new HttpConfiguration(); 
    config.setSecureScheme("https"); 
    config.setSecurePort(webProperties.getPort()); 
    config.setSendXPoweredBy(true); 
    config.setSendServerVersion(true); 
    config.addCustomizer(new SecureRequestCustomizer()); 
    return config; 
} 

Quando sto iniziando il server, io do anche la possibilità di Java -Xbootclasspath/p: $ installDirectory/lib/alpn-boot-8.1.3.v20150130.jar

C'è qualcosa di sbagliato o mancante? Grazie per il vostro aiuto,

saluti,

+0

Potete aiutare per favore con: webProperties? quale importazione/jar? –

risposta

6

il codice è corretto, manca solo altre due linee che sono importanti per ottenere HTTP/2 per funzionare correttamente.

Quando si configura il SslContextFactory, aggiungere le righe:

sslContextFactory.setCipherComparator(HTTP2Cipher.COMPARATOR); 
    sslContextFactory.setUseCipherSuitesOrder(true); 

Ciò che questi due linee che fanno è per ordinare i cifrari TLS a preferire i/2 quelli HTTP prima degli altri, e di chiedere a rispettare quell'ordine .

Senza l'ordinamento, il server stava ricadendo su una versione di bozza precedente di HTTP/2 (h2-14) che non impone la forza di cifratura, ma purtroppo è stata respinta da Chrome e Firefox.

Non so esattamente perché funzioni con Safari: un bug di Safari o un'interpretazione più rilassata delle specifiche HTTP/2 per quanto riguarda la potenza di cifratura rispetto ad altri browser.

+0

Grazie mille, funziona davvero bene con Firefox e Chrome con questo cambiamento! Un'altra domanda, come posso controllare sul lato server (con alcuni log in Jetty) se una richiesta è stata elaborata usando http 1.1 o http/2? – sebastien

+0

In generale, 'HttpServletRequest.getProtocol()' restituirà la stringa della versione del protocollo HTTP. Per la registrazione lato server integrata del logger NCSA di Jetty, vedere https://www.eclipse.org/jetty/documentation/current/embedded-examples.html – sbordet

+0

Grazie ancora! Con HttpServletRequest.getProtocol() ho verificato che la mia app IOS 9 utilizza davvero HTTP/2 – sebastien