-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
allow explicitly setting the protocol from the public option #1117
Changes from 6 commits
eecad00
3b204ee
972825e
650182f
21c54c6
b1a4eb8
ef0e57b
9e6b272
cfdb070
f481d0f
e170f18
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
FROM node:6 | ||
|
||
EXPOSE 80 | ||
|
||
VOLUME /devserver | ||
WORKDIR /devserver/examples/cli-public-protocol |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
FROM nginx | ||
|
||
COPY nginx-default.conf /etc/nginx/conf.d/default.conf | ||
|
||
RUN openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/nginx-selfsigned.key -out /etc/ssl/certs/nginx-selfsigned.crt -subj "/C=US/ST=Denial/L=Springfield/O=Dis/CN=localhost" && \ | ||
openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# CLI - public protocol | ||
|
||
NOTE: make sure you have docker and docker-compose (at least version 2) installed and already installed all dependencies via `npm install` in the repository. | ||
|
||
```shell | ||
docker-compose up | ||
``` | ||
|
||
If you're manually injecting an entrypoint to an iframe, the client needs to know where to connect to the server. Since an iframe with `src="about:blank` doesn't know which protocol you're using on the outside we need to explicitly define it with the `public` option (have a look to the config provided in `webpack.config.js`). | ||
|
||
To be able to show how this works together with an nginx reverse proxy there's a small docker setup which does this for you. | ||
|
||
## What should happen | ||
|
||
The `docker-compose up` starts up two containers (nginx and devserver), whereas nginx is exposing port 80 and 443 (with a self-signed certificate). If you open your browser and navigate to `https://localhost` you have to accept the self-signed certificate which is - of course - not secure but ok for testing purposes. After that you can see an iframe which says `I'm sitting in the iframe and the socket connection to dev-server works!`. | ||
|
||
If you have a look at the network tab of the inspector you'll see that the `sockjs-node` connection is up and running. If you wouldn't specify the `https://` protocol in the `public` option, it would try to connect to the socket via `http://localhost` which would fail because the parent window is loaded via `https` and therefore violate the security rules of the browser. | ||
|
||
If you edit the contents of `app.js` you'll also see that auto-reloading works. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
'use strict'; | ||
|
||
const h3El = document.createElement('h3'); | ||
h3El.innerHTML = 'I\'m sitting in the iframe asdfand the socket connection to dev-server works!'; | ||
document.body.appendChild(h3El); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
version: '2' | ||
|
||
services: | ||
nginx: | ||
build: | ||
context: . | ||
dockerfile: Dockerfile.nginx | ||
ports: | ||
- 80:80 | ||
- 443:443 | ||
links: | ||
- devserver | ||
|
||
devserver: | ||
build: | ||
context: . | ||
dockerfile: Dockerfile.devserver | ||
volumes: | ||
- ../../:/devserver | ||
command: 'node /devserver/bin/webpack-dev-server.js' |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
</head> | ||
<body> | ||
<iframe id="testframe" src="about:blank"></iframe> | ||
|
||
<script> | ||
var testframe = document.getElementById('testframe'); | ||
var scriptEl = document.createElement('script'); | ||
scriptEl.setAttribute('src', 'https://localhost/bundle.js'); | ||
testframe.contentDocument.head.appendChild(scriptEl); | ||
</script> | ||
</body> | ||
</html> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
server { | ||
listen 80; | ||
listen 443 ssl; | ||
|
||
ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt; | ||
ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key; | ||
|
||
ssl_dhparam /etc/ssl/certs/dhparam.pem; | ||
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA'; | ||
ssl_session_timeout 1d; | ||
ssl_session_cache shared:SSL:50m; | ||
ssl_stapling on; | ||
ssl_stapling_verify on; | ||
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; | ||
ssl_prefer_server_ciphers on; | ||
|
||
charset UTF-8; | ||
|
||
location /sockjs-node { | ||
proxy_pass http://devserver; | ||
|
||
proxy_buffering off; | ||
proxy_http_version 1.1; | ||
proxy_set_header Upgrade $http_upgrade; | ||
proxy_set_header Connection "upgrade"; | ||
proxy_read_timeout 1d; | ||
} | ||
|
||
location / { | ||
proxy_pass http://devserver; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
'use strict'; | ||
|
||
module.exports = { | ||
context: __dirname, | ||
entry: './app.js', | ||
devServer: { | ||
host: '0.0.0.0', | ||
port: 80, | ||
public: 'https://localhost', | ||
disableHostCheck: true | ||
} | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,8 +10,12 @@ module.exports = function createDomain(options, listeningApp) { | |
const port = options.socket ? 0 : appPort; | ||
const hostname = options.useLocalIp ? internalIp.v4() : options.host; | ||
|
||
// use explicitly defined public url (prefix with protocol if not explicitly given) | ||
if (options.public) { | ||
return /^[a-zA-Z]+:\/\//.test(options.public) ? `${options.public}` : `${protocol}://${options.public}`; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sorry, but this is not what was requested in previous comments
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wrote in the commit comment that
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry, but I looked up url.parse documentation again, as well as searching for issues with what I'm experiencing, and there's no easy solution possible by using url.parse. Why? The > url.parse("localhost:8080")
Url {
protocol: 'localhost:',
slashes: null,
auth: null,
host: '8080',
port: null,
hostname: '8080',
hash: null,
search: null,
query: null,
pathname: null,
path: null,
href: 'localhost:8080' } As you can see, the protocol is incorrect and I would need to do more processing to find out what's going on. I think the solution using regex is the better option here. Also have a look at nodejs/node#5755, where they're discussing the same issue on parsing urls. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. great documentation of the why. that'll certainly be beneficial in the future |
||
} | ||
// the formatted domain (url without path) of the webpack server | ||
return options.public ? `${protocol}://${options.public}` : url.format({ | ||
return url.format({ | ||
protocol, | ||
hostname, | ||
port | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
'use strict'; | ||
|
||
const webpack = require('webpack'); | ||
const internalIp = require('internal-ip'); | ||
const Server = require('../lib/Server'); | ||
const createDomain = require('../lib/util/createDomain'); | ||
const config = require('./fixtures/simple-config/webpack.config'); | ||
|
||
describe('check utility funcitons', () => { | ||
let compiler; | ||
before(() => { | ||
compiler = webpack(config); | ||
}); | ||
|
||
const tests = [{ | ||
name: 'default', | ||
options: { | ||
host: 'localhost', | ||
port: 8080 | ||
}, | ||
expected: 'http://localhost:8080' | ||
}, { | ||
name: 'https', | ||
options: { | ||
host: 'localhost', | ||
port: 8080, | ||
https: true | ||
}, | ||
expected: 'https://localhost:8080', | ||
timeout: 10000 | ||
}, { | ||
name: 'override with public', | ||
options: { | ||
host: 'localhost', | ||
port: 8080, | ||
public: 'myhost.test' | ||
}, | ||
expected: 'http://myhost.test' | ||
}, { | ||
name: 'override with public (port)', | ||
options: { | ||
host: 'localhost', | ||
port: 8080, | ||
public: 'myhost.test:9090' | ||
}, | ||
expected: 'http://myhost.test:9090' | ||
}, { | ||
name: 'override with public (protocol)', | ||
options: { | ||
host: 'localhost', | ||
port: 8080, | ||
public: 'https://myhost.test' | ||
}, | ||
expected: 'https://myhost.test' | ||
}, { | ||
name: 'override with public (protocol + port)', | ||
options: { | ||
host: 'localhost', | ||
port: 8080, | ||
public: 'https://myhost.test:9090' | ||
}, | ||
expected: 'https://myhost.test:9090' | ||
}, { | ||
name: 'localIp', | ||
options: { | ||
useLocalIp: true, | ||
port: 8080 | ||
}, | ||
expected: `http://${internalIp.v4()}:8080` | ||
}]; | ||
|
||
tests.forEach((t) => { | ||
const itInstance = it(`test createDomain '${t.name}'`, (done) => { | ||
const options = t.options; | ||
const server = new Server(compiler, options); | ||
const expected = t.expected; | ||
server.listen(options.port, options.host, (err) => { | ||
if (err) { | ||
done(err); | ||
} | ||
const generatedDomain = createDomain(options, server.listeningApp); | ||
if (generatedDomain !== expected) { | ||
done(`generated domain ${generatedDomain} doesn't match expected ${expected}`); | ||
} else { | ||
done(); | ||
} | ||
server.close(); | ||
}); | ||
}); | ||
if (t.timeout) { | ||
itInstance.timeout(t.timeout); | ||
} | ||
}); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is almost never a good idea in the browser - on the off chance that the
while
condition is not met, this will lock the browser forcing a close. please usesetInterval
in conjunction withclearInterval
. the log message should also be moved to just before the actual call toreload
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't really get what you mean with using
setInterval
andclearInterval
here and how this will improve the code.+1 for moving the log down