Skip to content

Commit

Permalink
Add support for https protocol. Closes GH-15.
Browse files Browse the repository at this point in the history
 - Added 'protocol' with default of 'http' to options
 - grunt.fatal if protocol is not 'http' or 'https'
  - Added set of self-signed certs with passphrase 'grunt'
   to be used by default / with tests
 - Updated docs with info on how to configure custom HTTPS
  • Loading branch information
Iristyle authored and shama committed Sep 2, 2013
1 parent d2ef60e commit 0aca993
Show file tree
Hide file tree
Showing 13 changed files with 259 additions and 7 deletions.
18 changes: 18 additions & 0 deletions Gruntfile.js
Expand Up @@ -7,6 +7,8 @@
*/

'use strict';
var path = require('path');
var certs = path.join(__dirname, 'tasks', 'certs');

module.exports = function(grunt) {
grunt.initConfig({
Expand Down Expand Up @@ -36,6 +38,22 @@ module.exports = function(grunt) {
port: 9000,
},
},
custom_https: {
options: {
port: 8001,
protocol: 'https',
}
},
custom_https_certs: {
options: {
port: 8002,
protocol: 'https',
key: grunt.file.read(path.join(certs, 'server.key')).toString(),
cert: grunt.file.read(path.join(certs, 'server.crt')).toString(),
ca: grunt.file.read(path.join(certs, 'ca.crt')).toString(),
passphrase: 'grunt',
}
},
custom_middleware: {
options: {
port: 9001,
Expand Down
62 changes: 60 additions & 2 deletions README.md
@@ -1,4 +1,4 @@
# grunt-contrib-connect [![Build Status](https://secure.travis-ci.org/gruntjs/grunt-contrib-connect.png?branch=master)](http://travis-ci.org/gruntjs/grunt-contrib-connect)
# grunt-contrib-connect v0.3.0 [![Build Status](https://travis-ci.org/gruntjs/grunt-contrib-connect.png?branch=master)](https://travis-ci.org/gruntjs/grunt-contrib-connect)

> Start a connect web server.
Expand Down Expand Up @@ -36,6 +36,12 @@ Default: `8000`

The port on which the webserver will respond. The task will fail if the specified port is already in use. You can use the special values `0` or `'?'` to use a system-assigned port.

#### protocol
Type: `String`
Default: `'http'`

May be `'http'` or `'https'`.

#### hostname
Type: `String`
Default: `'localhost'`
Expand Down Expand Up @@ -150,6 +156,58 @@ grunt.registerTask('connect', 'Start a custom static web server.', function() {
});
```

#### Support for HTTPS

A default certificate authority, certificate and key file are provided and pre-
configured for use when `protocol` has been set to `https`.

NOTE: The passphrase used on the files is `grunt`

####### Advanced HTTPS config

If the default certificate setup is unsuitable for your environment, OpenSSL
can be used to create a set of self-signed certificates with a local ca root.

```shell
### Generate the CA key
### Set a passphrase and remember what it is
openssl genrsa -des3 -out ca.key 2048
### Generate a CA root
openssl req -new -x509 -days 3650 -key ca.key -out ca.crt

### Generate the server key
openssl genrsa -out server.key 1024
### Generate the request to the self-signed CA root
openssl req -new -key server.key -out server.csr
### Generate the server certificate
openssl x509 -req -in server.csr -out server.crt -CA ca.crt -CAkey ca.key -CAcreateserial -days 3650
```

For more details on the various options that can be set when configuring SSL,
please see the Node documentation for [TLS][].

Grunt configuration would become

```javascript
// Project configuration.
grunt.initConfig({
connect: {
server: {
options: {
protocol: 'https',
port: 8443,
key: grunt.file.read('server.key').toString(),
cert: grunt.file.read('server.crt').toString(),
ca: grunt.file.read('ca.crt').toString(),
passphrase: 'grunt',
},
},
},
});
```

[TLS]: http://nodejs.org/api/tls.html#tls_tls_createserver_options_secureconnectionlistener


## Release History

Expand All @@ -165,4 +223,4 @@ grunt.registerTask('connect', 'Start a custom static web server.', function() {

Task submitted by ["Cowboy" Ben Alman](http://benalman.com)

*This file was generated on Thu Apr 11 2013 00:01:44.*
*This file was generated on Sun Sep 01 2013 19:52:23.*
52 changes: 52 additions & 0 deletions docs/connect-examples.md
Expand Up @@ -69,3 +69,55 @@ grunt.registerTask('connect', 'Start a custom static web server.', function() {
connect(connect.static('www-root')).listen(9001);
});
```

## Support for HTTPS

A default certificate authority, certificate and key file are provided and pre-
configured for use when `protocol` has been set to `https`.

NOTE: The passphrase used on the files is `grunt`

##### Advanced HTTPS config

If the default certificate setup is unsuitable for your environment, OpenSSL
can be used to create a set of self-signed certificates with a local ca root.

```shell
# Generate the CA key
# Set a passphrase and remember what it is
openssl genrsa -des3 -out ca.key 2048
# Generate a CA root
openssl req -new -x509 -days 3650 -key ca.key -out ca.crt

# Generate the server key
openssl genrsa -out server.key 1024
# Generate the request to the self-signed CA root
openssl req -new -key server.key -out server.csr
# Generate the server certificate
openssl x509 -req -in server.csr -out server.crt -CA ca.crt -CAkey ca.key -CAcreateserial -days 3650
```

For more details on the various options that can be set when configuring SSL,
please see the Node documentation for [TLS][].

Grunt configuration would become

```javascript
// Project configuration.
grunt.initConfig({
connect: {
server: {
options: {
protocol: 'https',
port: 8443,
key: grunt.file.read('server.key').toString(),
cert: grunt.file.read('server.crt').toString(),
ca: grunt.file.read('ca.crt').toString(),
passphrase: 'grunt',
},
},
},
});
```

[TLS]: http://nodejs.org/api/tls.html#tls_tls_createserver_options_secureconnectionlistener
6 changes: 6 additions & 0 deletions docs/connect-options.md
Expand Up @@ -6,6 +6,12 @@ Default: `8000`

The port on which the webserver will respond. The task will fail if the specified port is already in use. You can use the special values `0` or `'?'` to use a system-assigned port.

## protocol
Type: `String`
Default: `'http'`

May be `'http'` or `'https'`.

## hostname
Type: `String`
Default: `'localhost'`
Expand Down
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -28,7 +28,7 @@
"test": "grunt test"
},
"dependencies": {
"connect": "~2.7.3"
"connect": "~2.7.11"
},
"devDependencies": {
"grunt-contrib-jshint": "~0.2.0",
Expand Down
21 changes: 21 additions & 0 deletions tasks/certs/ca.crt
@@ -0,0 +1,21 @@
-----BEGIN CERTIFICATE-----
MIIDczCCAlugAwIBAgIJAKdGg4YIc6/TMA0GCSqGSIb3DQEBBQUAMFAxCzAJBgNV
BAYTAlVTMRMwEQYDVQQIDApTb21lLVN0YXRlMRAwDgYDVQQKDAdHcnVudEpTMRow
GAYDVQQDDBFodHRwczovL2xvY2FsaG9zdDAeFw0xMzAyMDcyMDI5NDVaFw0yMzAy
MDUyMDI5NDVaMFAxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApTb21lLVN0YXRlMRAw
DgYDVQQKDAdHcnVudEpTMRowGAYDVQQDDBFodHRwczovL2xvY2FsaG9zdDCCASIw
DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANY8SGJgaPsW/MfKyXx5VgtdNM4X
UJCYK5EC6hjBOi8CT46l85vM5c6dall5IfGZPvJtxydM+bnevlhmgBr28Q0Z+ury
U/sgzCn9fs4nqJPCX62jxYJmJDDLxnqDWBq+TMyX1keGpfJ9V9TOd8S/PkKfa8AN
aglB4Nf4USEbcERIwKt5nLZA44n62E98zm78YKrOdkx/hB8nwOfiphVkyUnDGIXj
fTmWduoVEf4bLq91Wk6lgKzVq26IxFQRP5T59kX19XH0j/s0a3M+2rrT/dIH1NjZ
wgdYPBBXsIfLAAw3eB8OobUcI+ILlXUG/ezIxTCsC/fLEnzK7COnVd0iY8UCAwEA
AaNQME4wHQYDVR0OBBYEFDsffAk3JaQRD1xJb7g06pgpPrhyMB8GA1UdIwQYMBaA
FDsffAk3JaQRD1xJb7g06pgpPrhyMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEF
BQADggEBAG8jDiUmZs/g4SyDeLRkos/vyEUaSzxolU9/7S4gbo7ckq35Uk+1dz8x
NfwIYmhdW5BsDK2HHC1lQ3HLyM5IeIQmULHacCPhbbEJ2dRtx3F4oRxeRn5jVWu3
RI8CWAC7klH3WcE9cajY6WS/6EbpypMceT060hAPBXxPT7YTnY87VByj3Q/e4FMt
WnlvEuoFUfekayd4GFXhd+ReCL6xf8IXWmI6d5c/YJmY1p2AV8ILeXf0RDTfr832
mxSuKzG+VopTJrUBkzkoSdYG9srftTlnSBE174rcgDzpqDDTFnwQYpMa5dIKOUHA
n/DK9mAnOaZHymcWl4bl/HSiXfMy/2U=
-----END CERTIFICATE-----
30 changes: 30 additions & 0 deletions tasks/certs/ca.key
@@ -0,0 +1,30 @@
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,D6AD3B624B34C274

Vg+XXN7UnJRk9FQpHRXWxVZy21qwQZcfkICIx5vcUjQZKArpTVWUpGq9QCXhGuUR
NnzrdScjQCGBDrmlMCS7ENltE1WXImOzZfI9gvU+Tc0Yhze7Dou8QNvB59+7Kye/
RYOkQH4KdUsw9IMEt2ELrxCnO9D2qwCofUJq9tdh/R5uqKPlybSKMBaiKDY/JV88
rNAp9uJhgFoDsZb8rKLoZqFSgrGHbH+eg67A8ZmHDAf5hMFo7Bt1cL61w+iEFAvU
wFdecJK6RlZRRGBkOJ6y1Wq1WL2Vlp1WHQJOSsPoV+cuC2DqRyb+liH2lffcYnIS
0cL1jAZ3FQ7V+8kZ37sZmAvLm4ELD0A72PH3Zv54/DVkQCHA/BHsOGm95zW+BoN/
DnoRqbBQ6weH55dPHGCdbhADMsEuFqS2cSPOO2cik4Uvmnoh0M/wZYBWxbFO6qSE
Za1E60wvdcPWPGnu320qC05DQjCGvCNWFudovKYbbUv6xyfxqjEw0I1FjdUzJsJR
gF9hEPe99sAbRGSvU3aNoksjTTdgJaVk5+DMSekMmTF9M/mY9VgWu9YHL8tsEUv0
6BcHK2hWXfZWwf/+HJmgI9JBXUfxVCpeoh+VHK6kpDL2ezjXAd/3jK4EhANc24/7
Lk47KCs+1F8JXAnma1Hkit3nNdyWql4rHM6W7j0+v8vAG1t7pbr9ixipLD7qp8Jl
x30j+GiffzbBOZ3JWUcUm0MYwrfen+0ed3qQmrv7DMgK6uiwyLZJMEDA+0Pu920L
Zw6Z7YkYHZWfPciWDBP+aXKzFayg6SSFnYLdUUOjNBc2DZGTr8UuR07xdK/dNNW4
WE0Wlbxma6jwrU3qYmsPY/21x5e54cu4o0qZWrYWbAsvAKaqQIkR6mDI4KIQbJ7d
+tfKe5Hck4CsTZJbjszQ4EZYOtMHCHg8tPYZTOGEBUeG3CTe4VY0zmjv5Jg6YUmq
88Cnz0WyNXA1dDcQDp/vUWQZBUZbIVxk1iAB8ZhHO8z51GnZQAcKoOq2R4fDQhlE
BMSbcn3gKEXf5dqwR6caosQmFA+kIg8ydonMbysucuUeCfShx5s9SjVDaOVlsb1V
LMXtt/IPGaBnNAOKLgtczaViOWsFULMdC5lAbg60P+PnhadDPTV40uOj9dDp8Lji
uKd5oj8REGT/TxQGdGS87RntJced0ukkc09JVVXdHCTeUbQ8zujxq2jIXFycvNtk
8oTSmPUzIKhuhkBq4++MoiGnYk/Ya9UW5Byl4FIoSTJkFTgGOI18WW7V0CcZ9xPW
rdlo5OjNGf9FhsoNyUVkm1460iwUnknT/+AeCkGrIkh9NKXD6KR9hgR3mZN/k6/I
2o4PlUMSpf5i94gzscMrZ8YsuT3Cu4MK7IlpnRrtnxKQqBW8Kv7zq4Xk9LRcf1bQ
xbf5rq3/i/7J7lV7VAY1y+wmN+KidmQ8Q/souaetVW24zG2c2kHTNp5WgQd8lA0T
n5WrpYJXiLYyiCVtoNTIsne9tDcbkMfiHJqyAjnDYfMOsOuZkmU/jh8L8FBdjM3v
11zk/6XQK8c4hFM0MOMRHcCs3yGcyRAQn7VwaYHqM5qt6tzFLteL+w==
-----END RSA PRIVATE KEY-----
1 change: 1 addition & 0 deletions tasks/certs/ca.srl
@@ -0,0 +1 @@
BE1BAB345BC0CC88
16 changes: 16 additions & 0 deletions tasks/certs/server.crt
@@ -0,0 +1,16 @@
-----BEGIN CERTIFICATE-----
MIICmDCCAYACCQC+G6s0W8DMiDANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJV
UzETMBEGA1UECAwKU29tZS1TdGF0ZTEQMA4GA1UECgwHR3J1bnRKUzEaMBgGA1UE
AwwRaHR0cHM6Ly9sb2NhbGhvc3QwHhcNMTMwMjA3MjAzMjU1WhcNMjMwMjA1MjAz
MjU1WjBQMQswCQYDVQQGEwJVUzETMBEGA1UECAwKU29tZS1TdGF0ZTEQMA4GA1UE
CgwHR3J1bnRKUzEaMBgGA1UEAwwRaHR0cHM6Ly9sb2NhbGhvc3QwgZ8wDQYJKoZI
hvcNAQEBBQADgY0AMIGJAoGBAM6KcAJQb4fxTS/rDEx7rxaeAdEsGUzp03yMAzHz
l74oCTCqikzNFSn7A5pUAlU7W80hR81h7wuT6/gR9BkRRckN2LlNOkKuF5EjLwvc
K0B6zljerBbjrjEQ6DEm83uhgqrOtgynM3f0wYrQm2C4LKi82hlG2ApFzwsj8G3w
7MZFAgMBAAEwDQYJKoZIhvcNAQEFBQADggEBABKCuy9DP25tRKQ+kd6d/N0IS8N2
3rLKD79+MQ3Y3fSdwjJnCjEMa0oAOJnLnG14x2BYCSAd6HCnZ42yemMt1BwITASJ
dXK4lWDALf4VOKhVIJjcWw81970JBDXpPGhJ1t0D5k2CAJXb72WATGLX7UIuRdJ2
7f7ZTlXo3KRbHMwE4B3BwT+e/MWfwndMuvsSxQBGclw8RpmeF1W/wCLvYvpCtDeW
exBJohEZs/cb0Tu2dkrborYAmhCGt2ujB5612PVRxttCTua0eM615XW1UGlBZBW1
vSKglmeWDK022gATPvplWVNp98yMMYmNmu3DHutCbdFxslLyqYlpCXq/3co=
-----END CERTIFICATE-----
11 changes: 11 additions & 0 deletions tasks/certs/server.csr
@@ -0,0 +1,11 @@
-----BEGIN CERTIFICATE REQUEST-----
MIIBjzCB+QIBADBQMQswCQYDVQQGEwJVUzETMBEGA1UECAwKU29tZS1TdGF0ZTEQ
MA4GA1UECgwHR3J1bnRKUzEaMBgGA1UEAwwRaHR0cHM6Ly9sb2NhbGhvc3QwgZ8w
DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM6KcAJQb4fxTS/rDEx7rxaeAdEsGUzp
03yMAzHzl74oCTCqikzNFSn7A5pUAlU7W80hR81h7wuT6/gR9BkRRckN2LlNOkKu
F5EjLwvcK0B6zljerBbjrjEQ6DEm83uhgqrOtgynM3f0wYrQm2C4LKi82hlG2ApF
zwsj8G3w7MZFAgMBAAGgADANBgkqhkiG9w0BAQUFAAOBgQCguHE/Ae/It4pKK73B
80Wehc0gglUXtPpLvu0n4NwGQ7kEybYrpR4EFnjD76Jt6oJ/vqfVB/8tLPRX3Mvq
8U+spcyD2km4stApbp3u6V8XxPlVcvY0YNzL1XIRv5p9ODCjF6+xnz2BEW/WjbfP
c29uUw2q+5OydPffx7Zd1YPABA==
-----END CERTIFICATE REQUEST-----
15 changes: 15 additions & 0 deletions tasks/certs/server.key
@@ -0,0 +1,15 @@
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDOinACUG+H8U0v6wxMe68WngHRLBlM6dN8jAMx85e+KAkwqopM
zRUp+wOaVAJVO1vNIUfNYe8Lk+v4EfQZEUXJDdi5TTpCrheRIy8L3CtAes5Y3qwW
464xEOgxJvN7oYKqzrYMpzN39MGK0JtguCyovNoZRtgKRc8LI/Bt8OzGRQIDAQAB
AoGBAJG7eKEJZEjFaDMhZEIrGzWYM6wFs6xjaEf++toqCK2xzho6mu7p3b8LUFV6
ZVMCWRn6G5G9QlAnBV66PEPbviKCi1SuarGQe3B7QsxdkUSpdg3RrmhrzsHsSjkW
YGBwF3XvOxiWv1tlkKLiizoIP9wGE503AK/vtR9n0jFTuseBAkEA/2ZjrtXwMdJX
XNfZGMrbyhH2/8fjKHdeOwAdGwp7scdd2B1BBqwfa4tttbQUfuWaWaA2gShcTHVK
PfJNdXvMVQJBAM8GqWdBgBL9kn4IO8j1fXdEa04+PZLCzLT0deCFbySUajv7BIzP
NvAYDNsMskdq1wnA+G0Nz2NADH57JcwaAjECQQCbza6J/eElw5ef/91kjnw+bW8s
4pflG8zUWWFoGaET9vd823vLwjz4snofGthWAWODwYT+jcygp/y+hY5TWU5xAkBV
kmpZPNDEiL2RjLOxiA9ZShWUnNN0o0JcFaPXry/WjeYvbr1dupT5vucpb+EM9hN2
e6Xz5b5wRtwjN6HS8HkxAkBxrTNDV2/+8TYtUp6KzHOiXpF1iaC6MtLLUPsLvccT
C/TlBD8ZwvW02G6BLgJF/woJ273EmK3Oehlf9Uwgm9yv
-----END RSA PRIVATE KEY-----
24 changes: 22 additions & 2 deletions tasks/connect.js
Expand Up @@ -11,10 +11,13 @@
module.exports = function(grunt) {
var path = require('path');
var connect = require('connect');
var http = require('http');
var https = require('https');

grunt.registerMultiTask('connect', 'Start a connect web server.', function() {
// Merge task-specific options with these defaults.
var options = this.options({
protocol: 'http',
port: 8000,
hostname: 'localhost',
base: '.',
Expand All @@ -29,6 +32,10 @@ module.exports = function(grunt) {
}
});

if (options.protocol !== 'http' && options.protocol !== 'https') {
grunt.fatal('protocol option must be \'http\' or \'https\'');
}

// Connect requires the base path to be absolute.
options.base = path.resolve(options.base);

Expand Down Expand Up @@ -56,8 +63,21 @@ module.exports = function(grunt) {
var taskTarget = this.target;
var keepAlive = this.flags.keepalive || options.keepalive;

var server = connect
.apply(null, middleware)
var app = connect.apply(null, middleware);
var server = null;

if (options.protocol === 'https') {
server = https.createServer({
key: options.key || grunt.file.read(path.join(__dirname, 'certs', 'server.key')).toString(),
cert: options.cert || grunt.file.read(path.join(__dirname, 'certs', 'server.crt')).toString(),
ca: options.ca || grunt.file.read(path.join(__dirname, 'certs', 'ca.crt')).toString(),
passphrase: options.passphrase || 'grunt',
}, app);
} else {
server = http.createServer(app);
}

server
.listen(options.port, options.hostname)
.on('listening', function() {
var address = server.address();
Expand Down
8 changes: 6 additions & 2 deletions test/connect_test.js
Expand Up @@ -2,9 +2,14 @@

var grunt = require('grunt');
var http = require('http');
var https = require('https');

function get(url, done) {
http.get(url, function(res) {
var client = http;
if (url.toLowerCase().indexOf('https') === 0) {
client = https;
}
client.get(url, function(res) {
var body = '';
res.on('data', function(chunk) {
body += chunk;
Expand All @@ -23,5 +28,4 @@ exports.connect = {
test.done();
});
},

};

0 comments on commit 0aca993

Please sign in to comment.