ionic-cli icon indicating copy to clipboard operation
ionic-cli copied to clipboard

Ionic serve launches browser to "Invalid Host header" only

Open ionitron-bot[bot] opened this issue 5 years ago • 29 comments

Bug Report

Ionic Info

Ionic:

   ionic (Ionic CLI)          : 4.0.1 (/home/david/.nvm/versions/node/v9.11.2/lib/node_modules/ionic)
   Ionic Framework            : @ionic/angular 4.0.0-beta.0
   @angular-devkit/core       : 0.7.0-rc.3
   @angular-devkit/schematics : 0.7.0-rc.3
   @angular/cli               : 6.0.8
   @ionic/ng-toolkit          : 1.0.0
   @ionic/schematics-angular  : 1.0.1

System:

   NodeJS : v9.11.2 (/home/david/.nvm/versions/node/v9.11.2/bin/node)
   npm    : 5.6.0
   OS     : Linux 4.14

Describe the Bug

In a new Ionic v4 beta project when I simply run ionic serve it launches a browser but only displays the message "Invalid Host header" as the only page content.

Steps to Reproduce Steps to reproduce the behavior:

(Follow exact steps in docs for a new v4 beta project.)

  1. npm install -g ionic
  2. ionic start myApp tabs --type=angular
  3. ionic serve
  4. See error in browser

Related Code

N/A

Expected Behavior

That it launches the app content in the browser.

Additional Context

I'm on a Pixelbook so running inside a LXC container so this issue might be limited to containers.

Maybe a workaround would be to configure webpack to work with the Chrome OS Linux LXC container (aka Crostini) default hostname of penguin.linux.test?

ionitron-bot[bot] avatar Jul 30 '18 14:07 ionitron-bot[bot]

@DavidFrahm This works, then, correct?

ionic serve --address penguin.linux.test

imhoffd avatar Jul 30 '18 20:07 imhoffd

I had the same problem, and adding the --address parameter did solve it for me.

eslindsey avatar Jul 31 '18 07:07 eslindsey

The default host for ionic serve is 0.0.0.0, which should be accessible on all interfaces, including the alias 'localhost'. If your computer can't resolve localhost, then the value needs to be changed.

imhoffd avatar Jul 31 '18 16:07 imhoffd

My server (vanilla Debian install) resolves localhost without a problem, but that wasn't the issue for me. The --address parameter is necessary if you want to test from the network or Internet (which makes sense in retrospect), but ionic serve doesn't make that very clear, nor does the slightly cryptic "Invalid Host header" message. A hint in the console to the developer when they run ionic serve might be in order.

eslindsey avatar Jul 31 '18 19:07 eslindsey

I was wrong about the default, sorry! The default is actually 0.0.0.0, but localhost should resolve to the host. If it does not, then the value needs to be changed.

imhoffd avatar Jul 31 '18 20:07 imhoffd

@eslindsey So actually the default for ionic serve is to spin up a server on all network interfaces (0.0.0.0), allowing testing from the network. localhost will resolve, but other hosts/addresses will resolve as well.

ionic serve --help does make this clear:

    By default, ionic serve boots up a development server on all network interfaces and prints the external address(es)
    on which your app is being served. It also broadcasts your app to the Ionic DevApp on your network. To disable the
    DevApp and bind to localhost, use --local.

imhoffd avatar Jul 31 '18 20:07 imhoffd

Okay and this makes sense, because if it wasn't listening on all interfaces then I never could have gotten the "Invalid Host header" message in the first place (it would have refused the connection instead, probably).

Still, the server presents an error message with the default ionic serve when it didn't before, which could confuse some people. I maintain my recommendation for some kind of hint that the --address parameter is now necessary. (Unless you're using an IP address to access the site? What is the default --address, anyway, localhost? What exactly will the default server respond to without the manual --address parameter?)

eslindsey avatar Aug 01 '18 02:08 eslindsey

Interestingly, without the --address parameter, I get the following (snipped) output:

   Local: http://localhost:8100
   External: http://50.192.28.253:8100
   DevApp: Blitz@8100 on blitz

so this might lead me to believe that I could copy and paste that address (External) and it should work--and it does. But since I have a domain name associated with that address, I naively thought that I could just use that instead (which worked in previous versions of Ionic).

Now, if I add the --address parameter, then the output becomes:

   Local: http://localhost:8100
   DevApp: Blitz@8100 on blitz

...which would seem to imply that now I can't access it externally at all! (Although that assumption is incorrect and everything works the way it's supposed to.)

How come the External line disappears when you manually supply an address?

eslindsey avatar Aug 01 '18 03:08 eslindsey

Obviously there's some work to be done here!

To try to explain what's going on:

  • The default value for --address is 0.0.0.0, which binds to all interfaces, which means connecting to localhost will resolve on nearly all computers (according to /etc/hosts).

  • The Angular CLI/webpack-dev-server have a mechanism for validating the host. I ran into the "Invalid Host header" issue when using 0.0.0.0 and attempting to access it via customhost, which I defined in my /etc/hosts file like so (at bottom):

    127.0.0.1	localhost
    255.255.255.255	broadcasthost
    ::1             localhost
    127.0.0.1	customhost
    

    This validation can be disabled using the Angular CLI's --disable-host-check, but a better, safer way would be to use both --host and --public-host. The Ionic CLI only has a concept of --address, which is the bind address, and then localhost is always used for public host, which is used in the browser.

    I think the behavior may need to change such that whenever --address is used, we use it for both the host and the browser URL. If 0.0.0.0 is used, localhost should be fine unless your computer can't resolve it... which is very rare. This issue is the first I've heard of it.

  • Not showing External when an IP address is used is definitely a bug 😂 The server should still work externally, but it's just not being printed.

imhoffd avatar Aug 01 '18 17:08 imhoffd

I agree with what you've said there.

I think there's more at play, as well (although I'm new to Ionic so I may be wrong). If I do ionic start myApp blank --type ionic-angular && ionic serve (for Angular2 and no address), then I can access the server non-locally using an assigned domain name. However, if I do ionic start myApp blank --type angular && ionic serve (for Angular4) then I cannot access the server non-locally--it gives me this "Invalid Host header" message. I think the host header check is new, and it changes the behavior of the default ionic serve.

eslindsey avatar Aug 01 '18 19:08 eslindsey

It's new because ionic-angular does not use the Angular CLI at all. Only angular.

Additionally, ionic-angular is for (stable) Ionic 3 (Angular 5), angular is for (beta) Ionic 4 (Angular 6).

imhoffd avatar Aug 01 '18 20:08 imhoffd

@dwieeb No, using my container hostname as you suggest does not work.

david@penguin:~/projects/play/ionic-v4-beta$ ionic serve --address penguin.linux.test
> ng run app:serve --host=penguin.linux.test --port=8100
[INFO] Waiting for connectivity with ng...

[INFO] Development server running!

       Local: http://localhost:8100
       DevApp: myApp@8100 on penguin

       Use Ctrl+C to quit this process

[INFO] Browser window opened to http://localhost:8100!

[ng] getaddrinfo ENOTFOUND penguin.linux.test
[ng] Error: getaddrinfo ENOTFOUND penguin.linux.test
[ng]     at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:67:26)

[ERROR] A utility CLI has unexpectedly closed.

        The Ionic CLI will exit. Please check any output above for error details.

What I thought was working the other day was finding my current external IP and passing that in. But now that's not working or I'm doing it wrong :(

So would be great if ionic serve could magically do that kind of thing, but I don't know if that's really the right thing for general behavior or how challenging that would be.

DavidFrahm avatar Aug 11 '18 23:08 DavidFrahm

@dwieeb Just remembered what I was doing the other day to get something usable:

  1. I run a default ionic serve
  2. Above launches my browser to http://penguin.linux.test:8100/ with failure "Invalid Host header"
  3. I get the "External" ip address output from the ionic serve command (where it displays Local/External/DevApp)
  4. Open the browser to that External address, and it works

DavidFrahm avatar Aug 12 '18 00:08 DavidFrahm

@davidfrahm using a hostname will only work if the hostname is resolvable at the server and the client, which can be complicated if you're not testing locally. But here are a few pointers:

If the container is penguin.linux.test, then you should be able to ping penguin.linux.test successfully. If you can't, you need to add

127.0.0.1 penguin.linux.test

to your /etc/hosts on the server.

Additionally, if you are testing from non-local, then you need to resolve the name there as well, so you would need to add

<ip_addr_of_penguin> penguin.linux.test

to that machine's /etc/hosts.

That's a lot of work, so usually if you get to the point where you need that kind of testing, you'd add something like dnsmasq to take care of those details for you.

Regardless, the name you specify in --address MUST be resolvable on the server and client in order for everything to work.

Edit: I often see problems like this if a host name is set in /etc/hostname but doesn't have a corresponding entry in /etc/hosts. The first sets the machine's hostname, but that doesn't automatically make it reachable or resolvable. For that, you need the second step. Doing one but not the other can lead to a plethora of mysterious Linux problems. Ionic is probably trying to use penguin.linux.test because that's what you've told Linux this machine's name is. But your DNS server (or hosts file if local) are unaware of that, so the name can't be resolved.

It's also worth noting that if you get to the point of using TLS/SSL/HTTPS, you will need to be able to resolve by name, because using the IP address won't match the certificate and you'll get security errors.

eslindsey avatar Aug 12 '18 00:08 eslindsey

Not showing External when an IP address is used is definitely a bug 😂 The server should still work externally, but it's just not being printed.

@dwieeb is this bug? CLI checked using 0.0.0.0 in https://github.com/ionic-team/ionic-cli/blob/develop/packages/%40ionic/cli-utils/src/lib/serve.ts#L342 and if use other port, cam't access from dev Apps.

ref: https://github.com/ionic-team/ionic-cli/blob/develop/packages/%40ionic/cli-utils/src/lib/serve.ts#L248-L249

rdlabo avatar Aug 28 '18 03:08 rdlabo

@rdlabo That code looks right to me. If options.address is configured with a custom IP, it is used. If it's the default (0.0.0.0), then it has to ask the user to select a specific one. This is for Cordova livereload so the CLI can write the specific IP to config.xml so that the device can reach the livereload server on the dev's computer.

I think the issue is more with the display. It assumes an IP is only external if the externalNetworkInterfaces array is not empty, which is not the case if a custom IP is provided.

imhoffd avatar Aug 28 '18 16:08 imhoffd

This does appear to be Ionic-Angular related. When I create an Ionic only app I don't have the issue. I also don't have it with an Angular only app. The way to get around it was to get my containers IP Address and use it in the browser. I had tried to disable host check but that didn't work. Use the container IP for now.

innovateworld avatar Sep 08 '18 10:09 innovateworld

@innovateworld You would get the issue with an Angular app if you used --host 0.0.0.0 and tried to access it via a different public host.

imhoffd avatar Sep 10 '18 13:09 imhoffd

Trying to use ChromeOS Crostini and ngrok + devapp for testing and hitting this issue. What is the recommendation here in 2019?

philips avatar Apr 30 '19 06:04 philips

@philips I'm experiencing this on Crostini too. I wasn't able to get penguin.linux.test working but the external IP worked.

This should be added to the docs at least, everyone on Crostini can't even get past the getting started steps. All new Chromebooks starting this year (announced at Google I/O) will be Linux compatible so I imagine more people will run into this.

kevin-brotcke avatar May 12 '19 06:05 kevin-brotcke

@kevin-brotcke @philips The default host is changing to localhost with Ionic CLI 5 (likely to be released this month). Want to give it a try? npm i -g ionic@beta. For external addresses, we'll have to document the --public-host option, when implemented: https://github.com/ionic-team/ionic-cli/issues/3558

imhoffd avatar May 13 '19 14:05 imhoffd

Having kind of the same problem. I have every .lcl domain pointed to localhost (127.0.0.1) and want ionic serve to open xxx.lcl instead of localhost. When I do this with ionic serve --source-map --ssl --no-open --consolelogs --devapp --host='xxxx.lcl' I still shows this:

[INFO] Development server running!

       Local: https://localhost:8100
       External: https://xxx.xxx.xxx.xxx:8100
       DevApp: APPNAME@8100 on xxxx.xxxxx

muuvmuuv avatar Jun 24 '19 16:06 muuvmuuv

Has anyone found a solution to this? I just want to develop on a remote machine and it seems there is no clear answer to get --disableHostCheck into the command line that starts the server.

thenetimp avatar Oct 31 '19 19:10 thenetimp

My work around. Install angular at a global level.

npm install -g @angular/cli

Then run

ng run app:serve --host=0.0.0.0 --port=8100 --disable-host-check

thenetimp avatar Nov 01 '19 05:11 thenetimp

Thank you! Working perfectly.

jdalleniii avatar Feb 16 '20 19:02 jdalleniii

I used:

ionic serve --port 8080 --address 0.0.0.0 -- --disableHostCheck true

thielpeter avatar Feb 19 '20 16:02 thielpeter

Hello all (especially @DavidFrahm @eslindsey @philips @kevin-brotcke) 👋

I have implemented the --public-host option for the Ionic CLI which should resolve all issues here. This option provides a way for devs to specify which host the browser should use, regardless of which host the dev server is bound to.

Please help me test this PR by installing a test version of the Ionic CLI:

npm i -g @ionic/[email protected]

Couple things to note:

  • --address is now named --host
  • the default host is localhost, not 0.0.0.0
  • use ionic serve --host=0.0.0.0 --public-host=<hostname> to test

Let me know what you think! 💙

imhoffd avatar Feb 22 '20 07:02 imhoffd

ionic serve --port 4200 --no-open --host=0.0.0.0 --public-host=iloveu.dev.luketic

Invalid Host header

server {
    listen 80;
    listen [::]:80;
    server_name iloveu.dev.luketic;
    index index.html;

    error_log /var/log/nginx/iloveu.error;

    location /sockjs-node/ {
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        rewrite ^/(.*)$  /$1  break;
        proxy_set_header Host localhost;
        proxy_pass http://localhost:4200/;
    }

    location / {
        proxy_pass http://localhost:4200;
        proxy_read_timeout 30;
        proxy_connect_timeout 30;
        proxy_redirect off;
        proxy_set_header Host               $host;
        proxy_set_header X-Real-IP          $remote_addr;
        proxy_set_header X-Forwarded-For    $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto  $scheme;
    }

    location /api/ {
        proxy_pass http://unix:/tmp/i-lov.eu-restful.sock;
        proxy_read_timeout 30;
        proxy_connect_timeout 30;
        proxy_redirect off;
        proxy_set_header Host               $host;
        proxy_set_header X-Real-IP          $remote_addr;
        proxy_set_header X-Forwarded-For    $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto  $scheme;
    }
}

For the record nothing I did could make vue-cli play along and not show the invalid host header.

Where can we set the "devserver" webpack configuration?

idc77 avatar Jan 07 '22 14:01 idc77

Ok here's how: create /vue.config.js relative to project root

module.exports = {
  devServer: {
    allowedHosts: 'all'
  }
}

docs: https://webpack.js.org/configuration/dev-server/#devserverallowedhosts

idc77 avatar Jan 07 '22 14:01 idc77