workers-sdk icon indicating copy to clipboard operation
workers-sdk copied to clipboard

๐Ÿ› BUG: pages dev with https cannot proxy request (to https server)

Open eltorio opened this issue 3 years ago โ€ข 4 comments

What version of Wrangler are you using?

2.1.6

What operating system are you using?

MacOS

Describe the Bug

I'm unable to proxy to vite when using --local-protocol https step to reproduce:

npm create vite@latest my-vue-app -- --template vue-ts
cd my-vue-app
npm i -D wrangler
npx wrangler pages dev --local-protocol https -- npx vite --https

in vite.config.ts add:

  server:{  https: {
    key: fs.readFileSync('./localhost.internal.tld.key'),
    cert: fs.readFileSync('./localhostinternal.tld.pem')
  }}

or with an automatic self signed certificate (with @vitejs/plugin-basic-ssl plugin):

import mkcert from '@vitejs/plugin-basic-ssl'
โ€ฆโ€ฆโ€ฆ
 plugins: [ 
       mkcert(),vue() ],
 server: { https: true },

Open https://127.0.0.1:8788 On console:

๐Ÿšง 'wrangler pages <command>' is a beta command. Please report any issues to https://github.com/cloudflare/wrangler2/issues/new/choose
Running npx vite...
Sleeping 5 seconds to allow proxy process to start before attempting to automatically determine port...
To skip, specify the proxy port with --proxy.
[proxy]: 
  VITE v3.1.3  ready in 354 ms


[proxy]:   โžœ  Local:   http://127.0.0.1:5173/
  โžœ  Network: use --host to expose

Automatically determined the proxy port to be 5173.
No functions. Shimming...
โ–ฒ [WARNING] Passing --inspect is unnecessary, now you can always connect to devtools.


โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
โ”‚ [b] open a browser, [d] open Devtools, [c] clear console, [x] to exit                                                                                                                                          โ”‚
โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ
Starting inspector on 0.0.0.0:9229 failed: address already in use
[pages:wrn] Service bindings are experimental. There may be breaking changes in the future.
[pages:inf] Generating new self-signed certificate...
[pages:inf] Updated `Request.cf` object cache!
[pages:inf] Worker reloaded! (322B)
[pages:inf] Listening on 0.0.0.0:8788
[pages:inf] - https://127.0.0.1:8788
[pages:inf] - https://192.168.2.42:8788
[pages:err] Error: Could not proxy request: TypeError: fetch failed
    at file:///Users/--/my-vue-app/node_modules/wrangler/miniflare-dist/index.mjs:5995:27
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at Fetcher.fetch (/Users/--/my-vue-app/node_modules/@miniflare/core/src/plugins/bindings.ts:130:17)
    at Object.fetch (/Users/--/my-vue-app/node_modules/wrangler/templates/pages-shim.ts:6:20)
    at EventTarget.[kDispatchFetch] (/Users/--/my-vue-app/node_modules/@miniflare/core/src/standards/event.ts:385:13)
    at Server.<anonymous> (/Users/--/my-vue-app/node_modules/@miniflare/http-server/src/index.ts:298:20)
GET / 502 Bad Gateway (70.85ms)

On browser: [wrangler] Could not proxy request: TypeError: fetch failed

I tried to configure vite to listen to a https port with the same resule

eltorio avatar Sep 22 '22 18:09 eltorio

Dear @nevikashah , I investigated a bit, I put a breakpoint at

node_modules/wrangler/miniflare-dist/index.mjs:5993

I open with the browser https://localhost.internal.tld:8788 On the breakpoint miniflareFetch2(url, miniflareRequest) url='https://localhost:5173' So vite must listen on https so I declared:

  server:{  https: {
    key: fs.readFileSync('./localhost.internal.tld.key'),
    cert: fs.readFileSync('./localhost.internal.tld.pem')
  }}

localhost.internal.tld.pem is a certificate signed with our company dev subca and it is valid on my browsers on my dev machine. https://localhost:5173 and https://localhost.internal.tld:5173 are working The exact thrown.cause is Error: Client network socket disconnected before secure TLS connection was established

I must use https because I'm developping an oAuth app and the provider refuse so set an http:// callback url

eltorio avatar Sep 23 '22 06:09 eltorio

I've created a repo for reproducting it https://github.com/highcanfly-club/wrangler2-issues-1908 Steps to reproduce:

git clone https://github.com/highcanfly-club/wrangler2-issues-1908.git
cd wrangler2-issues-1908
# checkout the bugged state
git checkout aefa6c599b15e809979aed9f4a0b182724ddf1ff
npm i
npm run dev

open https://127.0.0.1:8788 on a browser

> [email protected] dev
> wrangler pages dev --local-protocol https -- npx vite

๐Ÿšง 'wrangler pages <command>' is a beta command. Please report any issues to https://github.com/cloudflare/wrangler2/issues/new/choose
Running npx vite...
Sleeping 5 seconds to allow proxy process to start before attempting to automatically determine port...
To skip, specify the proxy port with --proxy.
[proxy]: 
  VITE v3.1.3  ready in 373 ms


[proxy]:   โžœ  Local:   https://127.0.0.1:5173/
  โžœ  Network: use --host to expose

Automatically determined the proxy port to be 5173.
No functions. Shimming...
โ–ฒ [WARNING] Passing --inspect is unnecessary, now you can always connect to devtools.


โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
โ”‚ [b] open a browser, [d] open Devtools, [c] clear console, [x] to exit                                                             โ”‚
โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ
Starting inspector on 0.0.0.0:9229 failed: address already in use
[pages:wrn] Service bindings are experimental. There may be breaking changes in the future.
[pages:inf] Generating new self-signed certificate...
[pages:inf] Updated `Request.cf` object cache!
[pages:inf] Worker reloaded! (322B)
[pages:inf] Listening on 0.0.0.0:8788
[pages:inf] - https://127.0.0.1:8788
[pages:inf] - https://127.51.68.120:8788
[pages:inf] - https://127.94.0.1:8788
[pages:inf] - https://192.168.2.38:8788
[pages:inf] - https://192.168.2.39:8788
[pages:err] Error: Could not proxy request: TypeError: fetch failed
    at file:///Users/--/Development/wrangler2-issues-1908/node_modules/wrangler/miniflare-dist/index.mjs:5995:27
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at Fetcher.fetch (/Users/--/Development/wrangler2-issues-1908/node_modules/@miniflare/core/src/plugins/bindings.ts:130:17)
    at Object.fetch (/Users/--/Development/wrangler2-issues-1908/node_modules/wrangler/templates/pages-shim.ts:6:20)
    at EventTarget.[kDispatchFetch] (/Users/--/Development/wrangler2-issues-1908/node_modules/@miniflare/core/src/standards/event.ts:385:13)
    at Server.<anonymous> (/Users/--/Development/wrangler2-issues-1908/node_modules/@miniflare/http-server/src/index.ts:298:20)
GET / 502 Bad Gateway (53.31ms)

eltorio avatar Sep 23 '22 10:09 eltorio

I continue investigation since it is a blocking bug for us: at undici/lib/fetch/index.js:900 - if (response.type === 'error') { response.error.code='ERR_TLS_CERT_ALTNAME_INVALID' so undici needs to be configured without cert check (perhaps via an option)

eltorio avatar Sep 23 '22 13:09 eltorio

I found a workaround I produced a certificate with:

            X509v3 Subject Alternative Name: 
                DNS:localhost.internal.tld, DNS:localhost., IP:127.0.0.1

signed by our subca internal.tld certificate I added an environment variable in my VsCode environment

"NODE_EXTRA_CA_CERTS":"${workspaceFolder}/subca.internal.tld.pem",

And finally it works !

So for using --local-protocol https to https server you must have a valid signed certificate witch it does not make sense. I think the Agent of undici.fetch must include

Agent({ connect: { rejectUnauthorized: false } })

eltorio avatar Sep 23 '22 13:09 eltorio

I'd suggest creating a certificate for vite with mkcert (https://github.com/FiloSottile/mkcert) for local development.

We are facing the same problem as OP though (even with the workaround, which is ugly):

  1. Wrangler expects the proxied app to use the same protocol as that of --local-protocol. That's a false assumption / limiting assumption to make imho. Instead of just accepting a proxy port, command or directory, it would be useful to specify a full proxy hostname.
  2. However, if you insist to keep this behavior (wrangler https requires underlying proxied app to also be https), then I'd agree with OP that we should set the rejectUnauthorized: false option (to my knowledge, undici doesn't support NODE_TLS_REJECT_UNAUTHORIZED).
  3. Wrangler doesn't let you "bring your own certificate". This is annoying for local development. I'd love to be able to configure that somehow after creating a self-signed, trusted certificate with mkcert locally for development.
  4. With this workaround, wrangler now produces spammy log output (despite --log-level none) like this:
WARNING: known issue with `fetch()` requests to custom HTTPS ports in published Workers:

Unrelated (I think I might create a general "feedback" issue with all these comments if that's welcome?):

With all the options necessary to spin up a full reproduction of the prod app running on CF pages the command is starting to get a bit unwieldy. At this point, I think it would be great to allow users to configure a config file. I see you are using yargs for the CLI, how about making use of the .env() and/or .config()

  • https://github.com/yargs/yargs/blob/main/docs/api.md#config
  • https://github.com/yargs/yargs/blob/main/docs/api.md#envprefix

fubhy avatar Sep 27 '22 17:09 fubhy

Still same with 2.2.1

I updated my test repo for using my (worst/ugly/โ€ฆ) workaround. only once issue:

npm run create-cert

next use as usual:

npm run dev
#or
npm run build && npm run preview

package.json

{
  "name": "my-vue-app",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "create-ca":"openssl req -x509 -sha256 -days 3562 -nodes -newkey rsa:4096 -subj '/CN=demo.highcanly.club/C=FR/L=Flers-en-Escrebieux' -keyout localhost-rootCA.key -out localhost-rootCA.pem",
    "create-key":"openssl genrsa 4096 > localhost.key",
    "create-csr":"openssl req -new -key localhost.key -subj '/CN=localhost/C=FR/L=Flers-en-Escrebieux'  > localhost.csr",
    "create-crt":"openssl x509 -req -in localhost.csr -out localhost.pem -sha256 -CA localhost-rootCA.pem -days 3600 -CAkey localhost-rootCA.key -CAcreateserial -CAserial localhost-rootCA.srl",
    "create-cert":"npm run create-ca && npm run create-key && npm run create-csr && npm run create-crt",
    "dev": "NODE_EXTRA_CA_CERTS=`pwd`/localhost-rootCA.pem npx wrangler pages dev --local-protocol https -- npx vite",
    "build": "vite build",
    "preview": "NODE_EXTRA_CA_CERTS=`pwd`/localhost-rootCA.pem npx wrangler pages dev --local-protocol https -- npx vite preview"
  },
  "dependencies": {
    "vue": "^3.2.45"
  },
  "devDependencies": {
    "@vitejs/plugin-basic-ssl": "^0.1.2",
    "@vitejs/plugin-vue": "^3.2.0",
    "plugin": "^0.3.3",
    "typescript": "^4.8.4",
    "vite": "^3.2.3",
    "vue-tsc": "^1.0.9",
    "wrangler": "^2.2.1"
  }
}

eltorio avatar Nov 13 '22 12:11 eltorio

I'd love to be able to configure that somehow after creating a self-signed, trusted certificate with mkcert locally for development.

You mostly can. First, mkcert -key-file key.pem -cert-file. Then mv them to~\.config\.wrangler\local-cert\. This is, unfortunately, per user, so all miniflare instances will share that cert. But it's enough for my purposes.

Credit.

AlexErrant avatar Feb 05 '23 02:02 AlexErrant

Hi folks! Thanks for the report. We're adding this information to our documentation, including instructions on how to use the NODE_EXTRA_CA_CERTS environment variable, but have no plans to change the behavior in Wrangler at this time.

https://github.com/cloudflare/cloudflare-docs/pull/8084

GregBrimble avatar Mar 17 '23 11:03 GregBrimble