├── .editorconfig ├── .eslintrc ├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── THANKS.md ├── index.js ├── index.spec.js ├── package.json ├── util.js └── util.spec.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # For all files in this project: 2 | # - 2-space soft tabs 3 | # - All files end with a line-break 4 | # - Trim trailing whitespace 5 | [*] 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parserOptions": { 3 | "sourceType": "module" 4 | }, 5 | "rules": { 6 | "indent": [ 7 | 2, 8 | 2 9 | ], 10 | "quotes": [ 11 | 2, 12 | "single" 13 | ], 14 | "linebreak-style": [ 15 | 2, 16 | "unix" 17 | ], 18 | "semi": [ 19 | 2, 20 | "always" 21 | ], 22 | "no-multi-spaces": 0, 23 | "no-underscore-dangle": 0, 24 | "no-use-before-define": 0, 25 | "key-spacing": [ 26 | 2, 27 | { 28 | "align": "colon", 29 | "beforeColon": true, 30 | "afterColon": true 31 | } 32 | ], 33 | "object-curly-spacing": [2, "always"], 34 | "array-bracket-spacing": [2, "always"], 35 | "computed-property-spacing": [2, "always"], 36 | "space-in-parens": [2, "always" ], 37 | "no-unused-vars": [2, { "args": "all" }] 38 | }, 39 | "env": { 40 | "es6": true, 41 | "node": true 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | .nyc_output 16 | .coveralls.yml 17 | 18 | # node-waf configuration 19 | .lock-wscript 20 | 21 | # Compiled binary addons (http://nodejs.org/api/addons.html) 22 | build/Release 23 | 24 | # Dependency directory 25 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 26 | node_modules 27 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "4" 4 | - "5" 5 | - "6" 6 | 7 | branches: 8 | only: 9 | - master 10 | 11 | after_success: npm run coveralls 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Stefan Judis 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](http://img.shields.io/travis/stefanjudis/is-http2.svg?style=flat)](https://travis-ci.org/stefanjudis/is-http2) [![npm version](http://img.shields.io/npm/v/is-http2.svg?style=flat)](https://www.npmjs.org/package/is-http2) [![npm downloads](http://img.shields.io/npm/dm/is-http2.svg?style=flat)](https://www.npmjs.org/package/is-http2) [![Coverage Status](http://img.shields.io/coveralls/stefanjudis/is-http2.svg?style=flat)](https://coveralls.io/r/stefanjudis/is-http2?branch=master) [![Uses greenkeeper.io](https://img.shields.io/badge/Uses-greenkeeper.io-green.svg)](http://greenkeeper.io/) 2 | 3 | # is-http2 4 | 5 | Simple module to check if certain servers out there support HTTP/2. 6 | 7 | ## install 8 | 9 | ``` 10 | $ npm install --save is-http2 11 | ``` 12 | 13 | ## Pre-requisites 14 | 15 | To make `is-http2` work, you need to have [openssl](http://openssl.org/) in a version greater than 1.0.0 installed and available in your `$path`. 16 | 17 | ## Basic usage 18 | 19 | ### isHttp2( url, options ) 20 | 21 | **Description** : Check if server behind given url supports HTTP/2 22 | 23 | **url** : Url to check HTTP/2 support for 24 | 25 | #### Options 26 | * **includeSpdy** : optional: should SPDY be considered HTTP/2 27 | * **openssl** : optional: specify custom openssl command (i.e. '/usr/local/Cellar/openssl/1.0.2k/bin/openssl') 28 | 29 | 30 | `isHttp2` returns a Promise which will be resolved with an Object containing `isHttp2` and `supportedProtocols`. 31 | 32 | ```javascript 33 | const isHttp2 = require( 'is-http2' ); 34 | 35 | isHttp2( 'twitter.com', { includeSpdy : true } ) 36 | .then( function( result ) { 37 | if ( result.isHttp2 ) { 38 | console.log( `${ chalk.green( '✓' ) } HTTP/2 supported by ${ host }` ); 39 | } else { 40 | console.log( `${ chalk.red( '×' ) } HTTP/2 not supported by ${ host }` ); 41 | } 42 | 43 | if ( result.supportedProtocols ) { 44 | console.log( 45 | `Supported protocols: ${ result.supportedProtocols.join( ' ' ) }` 46 | ); 47 | } 48 | } ) 49 | .catch( function( error ) { 50 | console.error( chalk.red( error ) ); 51 | 52 | process.exit( 1 ); 53 | } ); 54 | ``` 55 | 56 | -------------------------------------------------------- 57 | 58 | #### I want to thank all these [people](./THANKS.md) for their great work!!! 59 | -------------------------------------------------------------------------------- /THANKS.md: -------------------------------------------------------------------------------- 1 | # Credits for is-http2 2 | ## is-http2 relies on the work of 182 people: 3 | 4 | - **Sindre Sorhus** *sindresorhus@gmail.com* (109 packages) 5 | - **John-David Dalton** *john.david.dalton@gmail.com* (30 packages) 6 | - **Mathias Bynens** *mathias@qiwi.be* (28 packages) 7 | - **Blaine Bublitz** *blaine@iceddev.com* (25 packages) 8 | - **Benjamin Tan** *demoneaux@gmail.com* (25 packages) 9 | - **Kit Cambridge** *github@kitcambridge.be* (25 packages) 10 | - **Isaac Z. Schlueter** *isaacs@npmjs.com* (25 packages) 11 | - **Sebastian McKenzie** *sebmck@gmail.com* (19 packages) 12 | - **James Halliday** *mail@substack.net* (18 packages) 13 | - **Takuto Wada** *takuto.wada@gmail.com* (12 packages) 14 | - **Jon Schlinkert** *github@sellside.com* (12 packages) 15 | - **Olov Lassus** *olov.lassus@gmail.com* (9 packages) 16 | - **Joshua Appelman** *jappelman@xebia.com* (8 packages) 17 | - **Mariusz Nowak** *medyk@medikoo.com* (8 packages) 18 | - **Forrest L Norvell** *forrest@npmjs.com* (8 packages) 19 | - **Vsevolod Strukchinsky** *floatdrop@gmail.com* (8 packages) 20 | - **nzakas** *nicholas@nczconsulting.com* (6 packages) 21 | - **Benjamin Coe** *ben@npmjs.com* (6 packages) 22 | - **Mikeal Rogers** *mikeal.rogers@gmail.com* (6 packages) 23 | - **Eran Hammer** *eran@hammer.io* (6 packages) 24 | - **Yusuke SUZUKI** *utatane.tea@gmail.com* (6 packages) 25 | - **Simon Boudrias** *admin@simonboudrias.com* (5 packages) 26 | - **Mathias Buus** *mathiasbuus@gmail.com* (5 packages) 27 | - **Shinnosuke Watanabe** *snnskwtnb@gmail.com* (5 packages) 28 | - **Michael Ficarra** *github.public.email@michael.ficarra.me* (5 packages) 29 | - **Ben Newman** *bn@cs.stanford.edu* (5 packages) 30 | - **Rebecca Turner** *me@re-becca.org* (5 packages) 31 | - **Kyle E. Mitchell** *kyle@kemitchell.com* (4 packages) 32 | - **Julian Gruber** *julian@juliangruber.com* (4 packages) 33 | - **doowb** *brian.woodward@gmail.com* (4 packages) 34 | - **Kevin Mårtensson** *kevinmartensson@gmail.com* (4 packages) 35 | - **George Zahariev** *z@georgezahariev.com* (4 packages) 36 | - **Thiago de Arruda** *tpadilha84@gmail.com* (3 packages) 37 | - **Forbes Lindesay** *forbes@lindesay.co.uk* (3 packages) 38 | - **qix** *i.am.qix@gmail.com* (3 packages) 39 | - **vdemedes** *vdemedes@gmail.com* (3 packages) 40 | - **Nathan Rajlich** *nathan@tootallnate.net* (3 packages) 41 | - **Felix Geisendörfer** *felix@debuggable.com* (3 packages) 42 | - **Mark Cavage** *mcavage@gmail.com* (3 packages) 43 | - **TJ Holowaychuk** *tj@vision-media.ca* (3 packages) 44 | - **Robert Kieffer** *robert@broofa.com* (3 packages) 45 | - **Andrew Goode** *andrewbgoode@gmail.com* (3 packages) 46 | - **Jake Verbaten** *raynos2@gmail.com* (3 packages) 47 | - **royriojas** *royriojas@gmail.com* (2 packages) 48 | - **Jonathan Ong** *jonathanrichardong@gmail.com* (2 packages) 49 | - **Ariya Hidayat** *ariya.hidayat@gmail.com* (2 packages) 50 | - **James Nylen** *jnylen@gmail.com* (2 packages) 51 | - **Zhiye Li** *github@zhiye.li* (2 packages) 52 | - **Addy Osmani** *addyosmani@gmail.com* (2 packages) 53 | - **Pascal Hartig** *passy@twitter.com* (2 packages) 54 | - **Dav Glass** *davglass@gmail.com* (2 packages) 55 | - **Simon Lydell** (2 packages) 56 | - **lydell** *simon.lydell@gmail.com* (2 packages) 57 | - **Vitaly Puzrin** *vitaly@rcdesign.ru* (2 packages) 58 | - **Eddie Monge** *eddie+npm@eddiemonge.com* (2 packages) 59 | - **alexindigo** *iam@alexindigo.com* (2 packages) 60 | - **Thorsten Lorenz** *thlorenz@gmx.de* (2 packages) 61 | - **Nicholas C. Zakas** *nicholas+npm@nczconsulting.com* (2 packages) 62 | - **cainus** *gregg@caines.ca* (2 packages) 63 | - **Kat Marchaán** *kzm@sykosomatic.org* (2 packages) 64 | - **Ingvar Stepanyan** *me@rreverser.com* (2 packages) 65 | - **Domenic Denicola** *domenic@domenicdenicola.com* (2 packages) 66 | - **Calvin Metcalf** *calvin.metcalf@gmail.com* (2 packages) 67 | - **Dominic Tarr** *dominic.tarr@gmail.com* (2 packages) 68 | - **Rod Vagg** *r@va.gg* (2 packages) 69 | - **Roy Riojas** (2 packages) 70 | - **Jordan Harband** *ljharb@gmail.com* (2 packages) 71 | - **celer** *celer@scrypt.net* (1 package) 72 | - **jamestalmage** *james@talmage.io* (1 package) 73 | - **dubban** *stefanduberg@me.com* (1 package) 74 | - **ivolodin** *ivolodin@gmail.com* (1 package) 75 | - **byk** *ben@byk.im* (1 package) 76 | - **lo1tuma** *schreck.mathias@gmail.com* (1 package) 77 | - **Randall Koutnik** *@rkoutnik* (1 package) 78 | - **Jeff Morrison** *jeff@anafx.com* (1 package) 79 | - **Paul O’Shannessy** *paul@oshannessy.com* (1 package) 80 | - **gabelevi** *gabelevi@gmail.com* (1 package) 81 | - **matatbread** (1 package) 82 | - **Ramesh Nair** *ram@hiddentao.com* (1 package) 83 | - **Max Ogden** *max@maxogden.com* (1 package) 84 | - **James Burke** *jrburke@gmail.com* (1 package) 85 | - **mklabs** (1 package) 86 | - **Manuel Stofer** *manuel@takimata.ch* (1 package) 87 | - **idralyuk** *igor@buran.us* (1 package) 88 | - **celer** *dtyree77@gmail.com* (1 package) 89 | - **mhernandez** *michael.hernandez1988@gmail.com* (1 package) 90 | - **coderhaoxin** *coderhaoxin@outlook.com* (1 package) 91 | - **fengmk2** *fengmk2@gmail.com* (1 package) 92 | - **dead_horse** *dead_horse@qq.com* (1 package) 93 | - **swatinem** *arpad.borsos@googlemail.com* (1 package) 94 | - **Neil Fraser** *root@neil.fraser.name* (1 package) 95 | - **marijn** *marijnh@gmail.com* (1 package) 96 | - **Yehuda Katz** *wycats@gmail.com* (1 package) 97 | - **Kevin Decker** *kpdecker@gmail.com* (1 package) 98 | - **Petka Antonov** *petka.antonov@gmail.com* (1 package) 99 | - **thegoleffect** *thegoleffect@gmail.com* (1 package) 100 | - **evanw** *evan.exe@gmail.com* (1 package) 101 | - **Arthur Verschaeve** *arthur.versch@gmail.com* (1 package) 102 | - **Joyent, Inc** (1 package) 103 | - **pfmooney** *patrick.f.mooney@gmail.com* (1 package) 104 | - **Alexander Shtuchkin** *ashtuchkin@gmail.com* (1 package) 105 | - **Qix** (1 package) 106 | - **Feross Aboukhadijeh** *feross@feross.org* (1 package) 107 | - **Parsha Pourkhomami** (1 package) 108 | - **parshap** *supster+npm@gmail.com* (1 package) 109 | - **freeall** *freeall@gmail.com* (1 package) 110 | - **watson** *w@tson.dk* (1 package) 111 | - **yoshuawuyts** *i@yoshuawuyts.com* (1 package) 112 | - **Nick Fitzgerald** *nfitzgerald@mozilla.com* (1 package) 113 | - **Mikola Lysenko** (1 package) 114 | - **mikolalysenko** *mikolalysenko@gmail.com* (1 package) 115 | - **mozilla-devtools** *mozilla-developer-tools@googlegroups.com* (1 package) 116 | - **segmentio** *friends@segment.io* (1 package) 117 | - **Zeke Sikelianos** *zeke@sikelianos.com* (1 package) 118 | - **wayfind** (1 package) 119 | - **Krishnan Anantheswaran** *kananthmail-github@yahoo.com* (1 package) 120 | - **zloirock** *zloirock@zloirock.ru* (1 package) 121 | - **Gregg Caines** (1 package) 122 | - **mozilla** *dherman@mozilla.com* (1 package) 123 | - **nickmerwin** *n@mer.fm* (1 package) 124 | - **moll** *andri@dot.ee* (1 package) 125 | - **Aseem Kishore** *aseem.kishore@gmail.com* (1 package) 126 | - **Douglas Crockford** (1 package) 127 | - **Jan Lehnardt** *jan@apache.org* (1 package) 128 | - **marcbachmann** *marc.brookman@gmail.com* (1 package) 129 | - **azer** (1 package) 130 | - **nickfitzgerald** *fitzgen@gmail.com* (1 package) 131 | - **Dervus Grim** *dervus.grim@gmail.com* (1 package) 132 | - **Robert Mustacchi** *rm@fingolfin.org* (1 package) 133 | - **Stefan Duberg** *stefanduberg@gmail.com* (1 package) 134 | - **Caolan McMahon** *caolan.mcmahon@gmail.com* (1 package) 135 | - **Benjamin Thomas** *ben@bentomas.com* (1 package) 136 | - **Jeremiah Senkpiel** *fishrock123@rocketmail.com* (1 package) 137 | - **Douglas Wilson** *doug@somethingdoug.com* (1 package) 138 | - **Guillermo Rauch** *rauchg@gmail.com* (1 package) 139 | - **Matt Lavin** *matt.lavin@gmail.com* (1 package) 140 | - **AJ ONeal** *awesome@coolaj86.com* (1 package) 141 | - **Viacheslav Lotsmanov** *lotsmanov89@gmail.com* (1 package) 142 | - **Meryn Stol** *merynstol@gmail.com* (1 package) 143 | - **Ilya Radchenko** *ilya@burstcreations.com* (1 package) 144 | - **robertkowalski** *rok@kowalski.gd* (1 package) 145 | - **Andres Suarez** *zertosh@gmail.com* (1 package) 146 | - **** (1 package) 147 | - **Beau Gunderson** *beau@beaugunderson.com* (1 package) 148 | - **Kris Kowal** *kris@cixar.com* (1 package) 149 | - **Nathan LaFreniere** *quitlahok@gmail.com* (1 package) 150 | - **Alexander Early** *alexander.early@gmail.com* (1 package) 151 | - **Graeme Yeates** *yeatesgraeme@gmail.com* (1 package) 152 | - **'Julian Viereck'** *julian.viereck@gmail.com* (1 package) 153 | - **Cloud Programmability Team** (1 package) 154 | - **mattpodwysocki** *matthew.podwysocki@gmail.com* (1 package) 155 | - **Artur Adib** *arturadib@gmail.com* (1 package) 156 | - **julien-f** *julien.fontanet@isonoe.net* (1 package) 157 | - **linusu** *linus@folkdatorn.se* (1 package) 158 | - **Masaki Komagata** (1 package) 159 | - **The Linux Foundation** (1 package) 160 | - **Alexandru Marasteanu** *hello@alexei.ro* (1 package) 161 | - **Angry Bytes** *info@angrybytes.com* (1 package) 162 | - **stephank** *stephan@kochen.nl* (1 package) 163 | - **Michael Hart** *michael.hart.au@gmail.com* (1 package) 164 | - **Joakim Carlstein** *joakim@klei.se* (1 package) 165 | - **Jaguard OSS** *oss@jaguard.com* (1 package) 166 | - **Jeremy Stashewsky** *jstashewsky@salesforce.com* (1 package) 167 | - **jstash** *jeremy@goinstant.com* (1 package) 168 | - **goinstant** *services@goinstant.com* (1 package) 169 | - **Henrik Joreteg** *henrik@andyet.net* (1 package) 170 | - **komagata** *komagata@gmail.com* (1 package) 171 | - **Fred K. Schott** *fkschott@gmail.com* (1 package) 172 | - **Simeon Velichkov** *simeonvelichkov@gmail.com* (1 package) 173 | - **Mihai Bazon** *mihai.bazon@gmail.com* (1 package) 174 | - **Caires Vinicius** *cairesvs@gmail.com* (1 package) 175 | - **Mathias Pettersson** *mape@ma.pe* (1 package) 176 | - **Alex Ford** *alex.ford@codetunnel.com* (1 package) 177 | - **Jeremy Ashkenas** *jashkenas@gmail.com* (1 package) 178 | - **Ed Tsech** *edtsech@gmail.com* (1 package) 179 | - **Pavel Pravosud** *pavel@pravosud.com* (1 package) 180 | - **Esa-Matti Suuronen** *esa-matti@suuronen.org* (1 package) 181 | - **Tim** *tim@fostle.com* (1 package) 182 | - **Roman Shtylman** *shtylman@gmail.com* (1 package) 183 | - **Vincent Voyer** *vincent.voyer@gmail.com* (1 package) 184 | - **Michael Hernandez - michael.hernandez1988@gmail.com** (1 package) 185 | - **shimondoodkin** *helpmepro1@gmail.com* (1 package) 186 | 187 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var exec = require( 'child_process' ).exec; 4 | var Promise = require( 'pinkie-promise' ); 5 | var findVersions = require( 'find-versions' ); 6 | var semver = require( 'semver' ); 7 | var isH2Util = require( './util' ); 8 | 9 | 10 | /** 11 | * Has a given host HTTP/2 support 12 | * 13 | * @param {String} url host url 14 | * @param {Object} options options 15 | * 16 | * @return {Promise} 17 | */ 18 | function isH2( url, options ) { 19 | options = options || {}; 20 | var openssl = options.openssl || 'openssl'; 21 | 22 | return new Promise( function( resolve, reject ) { 23 | exec( openssl + ' version', function( error, result ) { 24 | if ( error ) { 25 | if ( error.code === 127 ) { 26 | return reject( 27 | new Error( 28 | 'Command `openssl` not found. Please make sure it\'s installed.' 29 | ) 30 | ); 31 | } 32 | 33 | return reject( error ); 34 | } 35 | 36 | var version = findVersions( result, { loose : true } )[ 0 ]; 37 | 38 | if ( semver.lt( version, '1.0.0' ) ) { 39 | return reject( 40 | new Error( 41 | 'Your `openssl` version is too old. Please update to at least 1.0.0' 42 | ) 43 | ); 44 | } 45 | 46 | url = isH2Util.getFormattedUrl( url ); 47 | 48 | if ( ! url ) { 49 | return reject( 50 | new Error( 51 | 'Please enter a valid url in format like [a-b]\.[a-z] -> `example.com`' 52 | ) 53 | ); 54 | } 55 | 56 | exec( 57 | 'true | ' + openssl + ' s_client -connect ' + url + ':443 -servername ' + url + ' -nextprotoneg ""', 58 | function( error, result ) { 59 | if ( error ) { 60 | if ( 61 | /gethostbyname failure/.test( error.message ) || 62 | /Connection refused/.test( error.message ) 63 | ) { 64 | return reject( 65 | new Error( 'Connection to host `' + url + '` failed.' ) 66 | ); 67 | } 68 | } 69 | 70 | resolve( isH2Util.getResultObject( result, options ) ); 71 | } 72 | ); 73 | } ); 74 | } ); 75 | } 76 | 77 | 78 | module.exports = isH2; 79 | -------------------------------------------------------------------------------- /index.spec.js: -------------------------------------------------------------------------------- 1 | import test from 'ava'; 2 | import isH2 from './index'; 3 | 4 | test.cb( 'is HTTP/2', t => { 5 | isH2( 'twitter.com' ) 6 | .then( function( result ) { 7 | t.true( result.isHttp2 ); 8 | t.end(); 9 | } ); 10 | } ); 11 | 12 | test.cb( 'is not HTTP/2', t => { 13 | isH2( 'github.com' ) 14 | .then( result => { 15 | t.false( result.isHttp2 ); 16 | t.end(); 17 | } ); 18 | } ); 19 | 20 | test.cb( 'no valid url', t => { 21 | isH2( 'github.' ) 22 | .catch( error => { 23 | t.same( 24 | error.message, 25 | 'Please enter a valid url in format like [a-b]\.[a-z] -> `example.com`' 26 | ); 27 | t.end(); 28 | } ); 29 | } ); 30 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "is-http2", 3 | "version": "1.2.0", 4 | "description": "Detect if a server support http/2", 5 | "main": "index.js", 6 | "scripts": { 7 | "lint": "eslint *.js", 8 | "test": "npm run lint && nyc ava *.spec.js", 9 | "coveralls": "nyc report --reporter=text-lcov | coveralls" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "git+https://github.com/stefanjudis/is-http2.git" 14 | }, 15 | "keywords": [ 16 | "http/2", 17 | "network", 18 | "performance" 19 | ], 20 | "engines": { 21 | "node": ">= 0.12.0" 22 | }, 23 | "author": "stefan judis ", 24 | "license": "MIT", 25 | "bugs": { 26 | "url": "https://github.com/stefanjudis/is-http2/issues" 27 | }, 28 | "homepage": "https://github.com/stefanjudis/is-http2#readme", 29 | "dependencies": { 30 | "coveralls": "^2.11.4", 31 | "find-versions": "^2.0.0", 32 | "pinkie-promise": "^2.0.0", 33 | "semver": "^5.1.0" 34 | }, 35 | "devDependencies": { 36 | "ava": "^0.16.0", 37 | "eslint": "^3.8.1", 38 | "nyc": "^8.3.2" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /util.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | /** 5 | * Check url and return formatted url to continue working with it 6 | * 7 | * @param {String} url url 8 | * 9 | * @return {String} formatted url 10 | * 11 | * @tested 12 | */ 13 | getFormattedUrl : function getFormattedUrl( url ) { 14 | var resultWeb = url.match( /^(http(s)?:\/\/)?(.+\..+?)(:\d+)?$/ ); 15 | 16 | if ( resultWeb ) { 17 | return resultWeb[ 3 ]; 18 | } 19 | 20 | var resultLocal = url.match( /^localhost(:\d+?)?$/ ); 21 | 22 | // no formatting for localhost 23 | if ( resultLocal ) { 24 | return url; 25 | } 26 | 27 | return null; 28 | }, 29 | 30 | 31 | /** 32 | * Format the result object and bring all 33 | * evaluated data in right place 34 | * 35 | * @param {String} opensslOutput openssl output 36 | * @param {Object} options option 37 | * 38 | * @return {Object} formatted result object 39 | * 40 | * @tested 41 | */ 42 | getResultObject : function getResultObject( opensslOutput, options ) { 43 | var protocolMatch = opensslOutput.match( 44 | /\nProtocols advertised by server:\s(.*?)\n/ 45 | ); 46 | 47 | if ( protocolMatch ) { 48 | var supportedProtocols = protocolMatch[ 1 ].split( ', ' ); 49 | var isH2Supported = supportedProtocols.indexOf( 'h2' ) !== - 1 ; 50 | 51 | if ( options.includeSpdy ) { 52 | var isSpdySupported = !! supportedProtocols.filter( function( protocol ) { 53 | return /spdy/.test( protocol ); 54 | } ).length; 55 | 56 | isH2Supported = isH2Supported || isSpdySupported; 57 | } 58 | 59 | return { 60 | isHttp2 : isH2Supported, 61 | supportedProtocols : supportedProtocols 62 | }; 63 | } 64 | 65 | return { 66 | isHttp2 : false, 67 | supportedProtocols : null 68 | }; 69 | } 70 | }; 71 | -------------------------------------------------------------------------------- /util.spec.js: -------------------------------------------------------------------------------- 1 | import test from 'ava'; 2 | import isH2Util from './util'; 3 | 4 | test( 'getFormattedUrl', t => { 5 | t.same( isH2Util.getFormattedUrl( 'http://twitter.com' ), 'twitter.com' ); 6 | t.same( isH2Util.getFormattedUrl( 'https://twitter.com' ), 'twitter.com' ); 7 | t.same( isH2Util.getFormattedUrl( 'http://www.twitter.com' ), 'www.twitter.com' ); 8 | t.same( isH2Util.getFormattedUrl( 'http://www.twitter.com:80' ), 'www.twitter.com' ); 9 | 10 | t.same( isH2Util.getFormattedUrl( 'http://twitter.' ), null ); 11 | t.same( isH2Util.getFormattedUrl( 'http://twitter' ), null ); 12 | t.same( isH2Util.getFormattedUrl( 'twitter' ), null ); 13 | 14 | t.same( isH2Util.getFormattedUrl( 'localhost' ), 'localhost' ); 15 | t.same( isH2Util.getFormattedUrl( 'localhost:8080' ), 'localhost:8080' ); 16 | t.same( isH2Util.getFormattedUrl( 'localhost:' ), null ); 17 | } ); 18 | 19 | test( 'getResultObject', t => { 20 | t.same( 21 | isH2Util.getResultObject( '', {} ), 22 | { isHttp2 : false, supportedProtocols : null } 23 | ); 24 | 25 | t.same( 26 | isH2Util.getResultObject( '\nProtocols advertised by server: foo, bar, baz\n', {} ), 27 | { isHttp2 : false, supportedProtocols : [ 'foo', 'bar', 'baz' ] } 28 | ); 29 | 30 | t.same( 31 | isH2Util.getResultObject( '\nProtocols advertised by server: h2, bar, baz\n', {} ), 32 | { isHttp2 : true, supportedProtocols : [ 'h2', 'bar', 'baz' ] } 33 | ); 34 | 35 | t.same( 36 | isH2Util.getResultObject( '\nProtocols advertised by server: spdy, bar, baz\n', {} ), 37 | { isHttp2 : false, supportedProtocols : [ 'spdy', 'bar', 'baz' ] } 38 | ); 39 | 40 | t.same( 41 | isH2Util.getResultObject( '\nProtocols advertised by server: spdy, bar, baz\n', { includeSpdy : true } ), 42 | { isHttp2 : true, supportedProtocols : [ 'spdy', 'bar', 'baz' ] } 43 | ); 44 | } ); 45 | --------------------------------------------------------------------------------