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

Allow Dev Server to Work Behind a Proxy #19219

Open
4 tasks done
titouandk opened this issue Jan 17, 2025 · 6 comments
Open
4 tasks done

Allow Dev Server to Work Behind a Proxy #19219

titouandk opened this issue Jan 17, 2025 · 6 comments

Comments

@titouandk
Copy link

titouandk commented Jan 17, 2025

Description

I am developing a Vue app.

The app is served behind a proxy in development—not in production.

Problem: The proxy removes a part at the start of the path—confusing Vite dev server.

Current flow of a page request from the browser (to test a change during development):

          BROWSER                REVERSE PROXY       VITE DEV SERVER:5050
             |                        |                       |
  Lets get the homepage of            |         Start Vite Server on port 5050
 my app, which is located at          |          Set base URL as /proxy/5050/
        /proxy/5050/                  |                       |
             |                        |                       |
             |    GET /proxy/5050/    |                       |
             |----------------------->|                       |
             |                        |                       |
             |               Removes /proxy/5050/             |
             |                 prefix from path               |
             |                        |                       |
             |                        |         GET /         |
             |                        |---------------------->|
             |                        |                       |
             |                        |            My Base path is configured
             |                        |                as /proxy/5050/ ...
             |                        |             Lets redirect the user.
             |                        |                       |
             |                        | REDIRECT /proxy/5050/ |
             |                        |<----------------------|
             |                        |                       |
             |                 Adds /proxy/5050/              |
             |                to the redirection              |
             |                  target path                   |
             |                        |                       |
             | REDIRECT /proxy/5050/proxy/5050/               |
             |<-----------------------|                       |
             |                        |                       |
Weird URL (not a problem per se.)     |                       |
      Let's request it.               |                       |
             |                        |                       |
             | GET /proxy/5050/proxy/5050/                    |
             |----------------------->|                       |
             |                        |                       |
             |               Removes /proxy/5050/             |
             |                 prefix from path               |
             |                        |                       |
             |                        |   GET /proxy/5050/    |
             |                        |---------------------->|
             |                        |                       |
             |                        |                   All right!
             |                        |            Sending index.html homepage
             |                        |                (containing the Vue
             |                        |               app script located at
             |                        |             /proxy/5050/src/main.ts)
             |                        |                       |
             |                        |  200 OK (index.html)  |
             |                        |<----------------------|
             |  200 OK (index.html)   |                       |
             |<-----------------------|                       |
             |                        |                       |
      Now, I need the                 |                       |
       main.ts file                   |                       |
             |                        |                       |
             | GET /proxy/5050/src/main.ts                    |
             |----------------------->|                       |
             |                        |                       |
             |               Removes /proxy/5050/             |
             |                 prefix from path               |
             |                        |                       |
             |                        |    GET /src/main.ts   |
             |                        |---------------------->|
             |                        |                       |
             |                        |           I know /proxy/5050/src/main.ts
             |                        |               but not /src/main.ts
             |                        |        Lets send a 404 with an error message.
             |                        |            (No redirect in this case.)
             |                        |                       |
             |                        |       ERROR 404       |
             |                        |<----------------------|
             |        ERROR 404       |                       |
             |<-----------------------|                       |

Suggested solution

Vite dev server should allow us to indicate a REVERSE_PROXY_BASE_URL, in addition of the BASE_URL:

  • BASE_URL:
    • Changes the resources include paths in the source files (prepend with /proxy/5050/)
      • <script src="/proxy/5050/src/main.ts"> from the browser's perspective.
    • Changes the resources location on the server (/proxy/5050/)
      • GET /proxy/5050/src/main.ts to retrieve the resources.
  • REVERSE_PROXY_BASE_URL:
    • Would change the resources include paths in the source files (prepend with /proxy/5050/)
      • <script src="/proxy/5050/src/main.ts"> from the browser's perspective.
    • Would NOT change the resources location on the server (/)
      • GET /src/main.ts to retrieve the resources (would work from the proxy's perspective)

We could set both variables at the same time:

  • BASE_URL="/base/"
  • REVERSE_PROXY_BASE_URL="/proxy/5050/"

In this case, if both variables are set:

  • <script src="/proxy/5050/base/src/main.ts"> from the browser's perspective (combining both variables.)
  • GET /base/src/main.ts to retrieve the resource from the proxy.
    • (Serving resources under BASE_URL only, since REVERSE_PROXY_BASE_URL has been stripped by the proxy).

Alternative

A temporary workaround is to avoid using the Vite dev server in this case—at the cost of a bad developer experience.

Build the app, and use a third-party static server to serve the dist/ directory from the / url:

# Configure vue/vite with a base path of "/proxy/5050/"
# We then build and serve the app on "/":

$ npm run build
$ cd build
$ python -m http.server 5050

Additional context

No response

Validations

@titouandk
Copy link
Author

(Edit: Variable name changed to REVERSE_PROXY_BASE_URL in my previous message.)

@sapphi-red
Copy link
Member

I guess you can tell the reverse proxy to not to strip the prefix. If that's not acceptable for some reason, probably setting base to / only for dev would work (base: command === 'build' ? '/' : '/proxy/5050/').

@titouandk
Copy link
Author

titouandk commented Jan 19, 2025

I guess you can tell the reverse proxy to not to strip the prefix.

I have no control over the reverse proxy. (I use a private cloud solution that allows me to create development VMs.)

When I request / from by browser, I get a VSCode web IDE to develop my Vue app.
When I request /proxy/5050/ from by browser, I get the homepage of my Vue application.
(The proxy strips the /proxy/5050/ part of the URL and calls the dev server with the following part of the URL.)

...probably setting base to / only for dev would work...

Unfortunately not. The request for /src/main.ts would not hit the Vue dev server, but the VSCode server.

To summarize:

The problem is that the URLs of the resources requested by the client must contain the /proxy/5050/ base to hit the Vue dev server.
(Problem solved by setting a BASE_URL.)

But by setting a BASE_URL, the Vue dev server expects the calls to be prefixed with the /proxy/5050/ url base, wich does not happen (the base URL being striped at the proxy level).

We need a way to tell the Vue dev server to keep adding a base URL to the resources URLs (/proxy/5050/), but to still serve the resources from / (this is more subtle than this - see the Suggested solution section of my initial message.)

@sapphi-red
Copy link
Member

sapphi-red commented Jan 20, 2025

Then, I think a plugin like this would work:

import { defineConfig } from 'vite';

export default defineConfig({
  base: '/proxy/5050/',
  plugins: [
    {
      name: 'strip-base',
      apply: 'serve',
      configureServer({ middlewares }) {
        middlewares.use((req, res, next) => {
          if (!req.url.startsWith('/proxy/5050/')) {
            req.url = '/proxy/5050' + req.url;
          }
          next();
        });
      },
    },
  ],
});

https://stackblitz.com/edit/vitejs-vite-mzubcv8v?file=vite.config.js&terminal=dev

@titouandk
Copy link
Author

Well done @sapphi-red, it is working! Thanks!

@titouandk
Copy link
Author

titouandk commented Jan 21, 2025

I reopen this issue because I think implementing the support of the REVERSE_PROXY_BASE_URL env variable could be beneficial (easier for the next devs that could have this problem).

It would be nice to support dev and production envs. (In dev, adding a base to the URL of the resources and changing the incoming requests inside the middleware to add the base striped by the proxy, and in production, just add a base to the URL of the resources.)

Feel free to close this issue if this change is too complicated to implement / unecessary.

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

2 participants