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

Dev server ping fails with secured Valet site #27

Closed
bakerkretzmar opened this issue Jun 24, 2022 · 19 comments
Closed

Dev server ping fails with secured Valet site #27

bakerkretzmar opened this issue Jun 24, 2022 · 19 comments
Assignees

Comments

@bakerkretzmar
Copy link

  • Laravel Vite Plugin Version: 0.2.3
  • Laravel Version: 9.x-dev 4d46bda
  • Node Version: 16.15.0
  • NPM Version: 8.5.5
  • Chrome Version: 102.0.5005.115
  • Firefox Version: 101.0.1
  • Laravel Valet Version: 3.1.7
  • macOS Version: 12.3.1 (M1)

Description:

When serving a local development site, e.g. valet-vite.test, using Valet, after the site is secured with HTTPS using valet secure the connection to wss://valet-vite.test:3000 fails, and all the pings to https://valet-vite.test/__vite_ping 404.

The errors look like this (screenshot is Firefox, errors are the same in Chrome).

Screen Shot 2022-06-24 at 2 17 21 PM

Steps To Reproduce:

  • composer create-project laravel/laravel:9.x-dev valet-vite && cd valet-vite
  • valet link valet-vite && valet secure
  • add @vite('resources/js/app.js') to resources/views/welcome.blade.php
  • set APP_URL to https://valet-vite.test
  • npm install && npm run dev
@eminos
Copy link

eminos commented Jun 24, 2022

This is probably not Valet related. I have the same issue serving the local dev site with Lando (Docker).

@innocenzi
Copy link
Contributor

This is only an issue with Vite 2.x, the ping works differently in Vite 3.x which will be released in the upcoming days/weeks (see vitejs/vite#6819). I'm not even sure if this is fixable on our side because the ping uses the base URL, which must be /.

@bakerkretzmar
Copy link
Author

That's good to know 👍🏻 I think the socket connection is also failing initially, which is a bigger problem right? It must have something to do with using HTTPS locally but I'm not sure if the fix would be something in Vite, this plugin, Valet, or somewhere else.

@innocenzi
Copy link
Contributor

Yes, you're getting the ping loop because Vite couldn't connect in the first place - I think the Vite plugin should do that automatically, but for now maybe try configuring server.https yourself?

I'll try that tomorrow, I don't recall what needs to be setup on the top of my head

@jessarcher
Copy link
Member

Thanks for reporting this, @bakerkretzmar.

The __vite_ping issue is known and will be fixed in Vite 3 as mentioned by @innocenzi.

I don't have a Mac (and therefore Valet) to reproduce the socket issue, but I'll check it out with @timacdonald's help tomorrow.

@innocenzi
Copy link
Contributor

Hey, so I just tried and at least the following server configuration is needed for https to work and the websocket to connect:

import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';

export default defineConfig({
    plugins: [
        laravel([
            'resources/css/app.css',
            'resources/js/app.js',
        ]),
    ],
    server: {
      https: true,
      hmr: {
        host: 'localhost',
      }
    }
});

The host is necessary because otherwise the websocket will try to connect using location.hostname.

@jessarcher I think the hmr host should always be set, and https should be auto-determined depending on APP_URL, like vite-plugin-laravel does.

I haven't looked into why ws://browser-hostname works and wss://browser-hostname doesn't, but setting the host to the dev server's host works in both cases.

@bakerkretzmar
Copy link
Author

@innocenzi thanks a ton, I'll add that config! It sounds like that wouldn't be super hard to figure out and configure automatically inside this plugin, hopefully that can be added 👍🏻

@hailwood
Copy link
Contributor

hailwood commented Jun 26, 2022

@jessarcher

I don't have a Mac (and therefore Valet) to reproduce the socket issue

Just pointing out here that this isn't valet specific, it's anything that allows you to have a valid https local dev setup that's not on https://localhost.
If you're going to work on this (which I'd totally get if we just skip it until Vite3 and maybe pin this issue instead) I'd suggest checking out Lando as that runs on Windows, Linux, and Mac and takes about 5 minutes to setup :)

@jessarcher
Copy link
Member

I agree that setting server.https to true makes sense when the APP_URL starts with https:. This works around the Vite client defaulting to wss when visiting a https site.

It's also possible to force the Vite client to connect over ws by setting server.hmr.protocol, however browsers understandably don't want to connect to ws when visiting a https site.

As for server.hmr.host, I think this is more complicated. The bigger issue is the use of self-signed certificates.

When you browse to your Valet site over https site (e.g. https://valet-vite.test) with a self-signed certificate, you need to accept the certificate, however, this only accepts the Valet certificate, and only for the hostname and port you've visited (i.e. valet-vite.test:443).

It does not accept the Vite certificate.

The only way I can see to accept the Vite certificate is to browse to the https version of the wss URL and accept it there. E.g. https://valet-vite:3000, https://localhost:3000, or https://127.0.0.1:3000. I don't think it matters much what server.hmr.host is set to, as long as you accept the certificate at whichever host the browser connects to. The only benefit I can see to setting it to localhost is that it will probably work for any Valet site once you've done it once.

I haven't looked into why ws://browser-hostname works and wss://browser-hostname doesn't, but setting the host to the dev server's host works in both cases.

I suspect this would work if you browsed to https://browser-hostname:3000 and accepted the certificate. I'm also assuming wss://localhost:3000 works for you because you've previously accepted Vite's certificate at https://localhost:3000.

It is possible to configure Vite to use Valet's key and certificate, however, this does not solve the issue because the certificate needs to be accepted separately for each port (i.e. 443 and 3000). This is not a problem in the normal Vite world because they always browse to port 3000.

@hailwood
Copy link
Contributor

You are absolutely correct it's more complicated than it first seems.
Our personal setup is using lando so the SSL cert is actually valid (*.lndo.site is a real domain registered that points to 127.0.0.1) and we use mkcert to generate our localhost valid certificate and pass that through to vite instead of letting it generate its own.

I was considering whether we could setup vite to proxy through to the laravel site so we could manage it the same way they do in the vite world, but that wouldn't work for subdomain routed apps.

I feel like the only suitable 'solution' to this issue is going t o be education on typical debugging steps given the range of setups people may have.

@jessarcher
Copy link
Member

jessarcher commented Jun 27, 2022

I feel like the only suitable 'solution' to this issue is going t o be education on typical debugging steps given the range of setups people may have.

This is what I'm leaning towards as well. I still think it's worth setting server.https when APP_URL starts with https: so at least all the developer needs to do is get the certificate accepted.

We could also consider adding some output to the console when this is set, with a link to the vite dev server URL so they can easily click it and accept the certificate.

It's also worth noting that this issue exists with Mix as well.

@timacdonald
Copy link
Member

timacdonald commented Jun 27, 2022

I don't think we should detect this from the APP_URL. The APP_URL is not directly related to the URL that the site is being viewed at...

APP_URL=http://foo.bar

composer create-project laravel/laravel my-app

cd my-app

valet link

open http://my-app.test

# or...

php -S 0.0.0.0:8998

open http://0.0.0.0:8998

# or...

php artisan serve

open http://127.0.0.1:8000

# or...

sail up -d

open http://localhost

None of these are related in anyway to the APP_URL, so I don't think auto-detecting is a good idea.

The APP_URL may be https and the site may not be and vice-versa.

@jessarcher
Copy link
Member

That's a good point @timacdonald.

Also, if no one provides a server.host setting, the hot file will get https://127.0.0.1:3000 (auto-detected from the Vite dev server) while the Vite client will auto-detect wss://valet-vite.test:3000 from the browser, meaning that the user would need to accept two certificates, in addition to the one they already have to accept at https://valet-vite.test.

Until we can think of something more reliable, I think we'll just document adding this to vite.config.js:

server: {
    https: true,
    host: 'localhost',
}

And then to make sure to visit the following link to accept the certificate:

image

@jessarcher
Copy link
Member

This has been added to the docs PR at laravel/docs@168786d

Going to close this issue for now. Thanks again for all your help everyone!

@innocenzi
Copy link
Contributor

innocenzi commented Jun 27, 2022

@timacdonald I still think APP_URL is a good heuristic - it should correspond to most defaults, and one can override the server configuration anyway.

I can confirm we still need to accept the certificate, but we indeed need to do that only once. Laravel Vite auto-detects Valet and Laragon certificates and uses them, which reduces the configuration needed by the user to get https working.

I don't think it's bad to have good defaults that would work in a lot of cases, even if not all of them.

@bakerkretzmar
Copy link
Author

@jessarcher thanks a lot! Glad this is documented now, and I think accepting the additional certificate is a good workaround.

I still think it makes sense to use APP_URL to do even more automatically when possible. This won't cover absolutely every use case, but I think it actually is—usually—directly related to the URL that the site is being viewed at.

@timacdonald
Copy link
Member

I'm not shutting down the idea at all, just sharing a perspective. Will chat to Jess more about it and maybe have a play with the idea a bit more.

Thanks for all the discussion folks ❤️

@paulocastellano
Copy link

I had the same problem, I fixed it by adding the key and certificate as I already did with laravel mix.

I created an article to show this working.

👉 https://dev.to/paulocastellano/how-to-make-vite-valet-and-ssl-works-together-5hbb

@enkota
Copy link

enkota commented Jul 3, 2022

I had the same problem, I fixed it by adding the key and certificate as I already did with laravel mix.

I created an article to show this working.

👉 https://dev.to/paulocastellano/how-to-make-vite-valet-and-ssl-works-together-5hbb

While this works, when testing npm run build it essentially breaks as we have explicitly set the domain. I get the error Unable to locate file in Vite manifest: resources/css/app.css. when using @Vite on the header.

Hopefully there's a cleaner way to make this work with Valet. Seems a bit of extra fluff to start new projects compared to Mix.

jxjj added a commit to UMN-LATIS/Camino that referenced this issue Jul 10, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

9 participants