Skip to content
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

The protocol passed to the client for live reloading is not respected #763

Closed
mgol opened this issue Jan 27, 2017 · 9 comments
Closed

The protocol passed to the client for live reloading is not respected #763

mgol opened this issue Jan 27, 2017 · 9 comments

Comments

@mgol
Copy link

mgol commented Jan 27, 2017

Do you want to request a feature or report a bug?

A bug.

What is the current behavior?

Webpack Dev Server, when passed the path where the live reload server is supposed to lie, doesn't respect the protocol and instead always uses the protocol of the current page. That is, if you add 'webpack-dev-server/client?http://localhost:8888' to the entry array and run a reverse proxy that points at this server, if this proxy works on pure HTTP, it will work. But if it runs on HTTPS, the dev server will query https://localhost:8888 which is a non-existing server. You can see a lot of requests to URLs like https://localhost:8888/sockjs-node/info?t=SOMETHING which won't work.

If the current behavior is a bug, please provide the steps to reproduce.

Run:

Create the following webpack.config.js:

'use strict';

const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
	entry: [
		'webpack-dev-server/client?http://localhost:8888',
		'webpack/hot/dev-server',
		'./app.js',
	],
	output: {
		filename: '[name].bundle.js',
		publicPath: '/',
		path: '/',
	},
	plugins: [
		new HtmlWebpackPlugin(),
		new webpack.HotModuleReplacementPlugin(),
	],
};

and run:

webpack-dev-server --port 8888

Set up any reverse proxy pointing to http://localhost:8888, an example nginx config:

server {
    server_name localhost default;
    
    listen 9800;
    listen 9801 default ssl;

    ssl_certificate     ssl/server.crt;
    ssl_certificate_key ssl/server.key;
    
    charset utf-8;

    # Proxy the Websocket connection to the Webpack server.
    location /sockjs-node/ {
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_http_version 1.1;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_pass http://localhost:8888;
    }

    # Proxy everything to the Webpack server
    location / {
        proxy_pass http://localhost:8888;
    }
}

If you now open http://localhost:9800, everything works and you can see requests to things like http://localhost:8888/sockjs-node/info?t=SOMETHING. But open https://localhost:9801 and it suddenly queries https://localhost:8888/sockjs-node/info?t=SOMETHING which won't work.

What is the expected behavior?

It should use the provided protocol instead of using the one on the current page.

If this is a feature request, what is motivation or use case for changing the behavior?

N/A

Please mention your webpack and Operating System version.

Webpack 2.2.0, macOS 10.12.3 (16D32)

Some Angular CLI users have been hit by this issue, see e.g. angular/angular-cli#2123, in particular this comment.

@SpaceK33z
Copy link
Member

Thanks for your bugreport. I think the issue is in these lines, where it will use the protocol of the current page instead of the provided one if it is https.

After a git blame I found this was introduced in #470. As mentioned in that PR, insecure websockets don't work from https. That makes sense. I don't get why you wouldn't run the websockets also over the nginx proxy?

@mgol
Copy link
Author

mgol commented Jan 28, 2017

I see. It still seems weird to change the protocol in that way as it then queries a server that may not exist.

But maybe, at the core, this can be qualified as an Angular CLI issue as that's what makes the connection use the full URL (and, hence, skip the proxy).

@SpaceK33z
Copy link
Member

SpaceK33z commented Jan 28, 2017

It still seems weird to change the protocol in that way as it then queries a server that may not exist.

True, but since it wouldn't work anyway, we can make an assumption that the user wants to connect to a secure protocol instead. Because of this there is at least a chance that it works.

Going to close this since we can't force a browser to connect to an insecure websocket AFAIK, thus we can never fix that in this project.

@Sfinx
Copy link

Sfinx commented Feb 7, 2017

To SpaceK33z: The nginx is proxying the websockets here - just study these lines in nginx.conf:

...
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
...

This means that nobody use the unsecure websockets here - app (WDS at least) checks for https transport and start making calls to wss:// (nginx) and nginx successfully proxies the connection to the ws:// (webpack) in the same way as it does with http:// calls.
This is definitely webpack bug. I think it should provide the template/rewrite option for outgoing URL generation but not blindly use the fixed local one.

The temporary workaround is to use 443 port at the both sides - webpack and nginx.

P.S. The simplest solution I see is to add config option something like ReverseProxyForcePort.

@shadowwzw
Copy link

On the client side, you can specify an arbitrary protocol.
https://github.com/shadowwzw/webpack-dev-server

@rigolepe
Copy link

I'm running against this same problemen in my development setup and I can't understand why this cannot be fixed? Just keep the protocol that is listed in:

'webpack-dev-server/client?http://localhost:8888'

@jandsu
Copy link

jandsu commented Oct 6, 2017

@rigolepe as explained above, keeping http rather than forcing https causes a mixed content issue

Mixed Content: The page at 'https://foo.bar.com/' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://localhost:4200/sockjs-node/

So the only option when https is involved would be to use window.location to get the host name and rely on the reverse proxy (nginx, apache, ...) to route it properly

@jandsu
Copy link

jandsu commented Oct 10, 2017

Check out angular/angular-cli#2123 (comment) if you want a workaround for this issue.

@viridia
Copy link

viridia commented Oct 18, 2019

I'm having the same problem - I'm working with a system that allows a local dev server, but only for javascript resources - the index.html cannot be hosted locally and must be served via https (it's part of a larger system that has a lot of infrastructure). It seems like there is no way to override the protocol for the socksjs url, which is surprising given that almost everything else can be overridden.

I need a way to force the protocol for the socksjs connection to match the protocol of the javascript bundle, instead of picking it up from the page.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants