vbenjs / vite-plugin-html

A vite plugin for processing html. It is developed based on lodash template
MIT License
601 stars 96 forks source link

[Bug] Query parameters are lost in the URL when redirected by assigning the URL to window.location. #120

Open Xooone47 opened 1 year ago

Xooone47 commented 1 year ago

Demo

https://codesandbox.io/p/sandbox/vite-plugin-html-redirect-demo-jhjqtn?file=%2Fvite.config.js

Reproduce steps

  1. Set server.proxy rules and use vite-plugin-html
    
    import { defineConfig } from "vite";
    import vue from "@vitejs/plugin-vue";
    import { createHtmlPlugin } from "vite-plugin-html";

export default defineConfig({ plugins: [ vue(), createHtmlPlugin({ entry: "/src/main.js", template: "index.html", }), ], server: { cors: true, proxy: { "/api": { target: "https://www.baidu.com", changeOrigin: true, configure: (proxy, _options) => { proxy.on("proxyReq", function (proxyReq, req, res, options) { if (req.url.includes("/api")) { console.log("req.url", req.url); console.log("req.originalUrl", req.originalUrl); console.log("req._parsedUrl", req._parsedUrl); } }); }, }, }, }, });


2. Assign a URL (/api/login?redirect=mockUrl) to window.location.href when clicking the `Redirect button`

```js
<script setup>
const url = "/api/login?redirect=mockUrl";

const onFetch = async () => {
  try {
    const res = await fetch(url);
    console.log(res);
  } catch (e) {
    console.error("fetch e", e);
  }
};

const onRedirect = () => {
  window.location.href = url;
};
</script>

<template>
  <div>
    <div class="card">
      <button type="button" @click="onFetch">Fetch</button>
      <button type="button" @click="onRedirect">Redirect</button>
    </div>
  </div>
</template>
  1. Losing the query params in request image

On the console, we can see the originalUrl that was requested is /api/login?redirect=mockUrl, but it becomes /api/login after being handled by the proxy middleware.

And the URL is correct when we click the Fetch button to trigger a xhr request.

image

Reason

code

// https://github.com/vbenjs/vite-plugin-html/blob/main/packages/core/src/htmlPlugin.ts#L87-L93
server.middlewares.use(
    history({
      disableDotRule: undefined,
      htmlAcceptHeaders: ['text/html', 'application/xhtml+xml'],
      rewrites: rewrites,
    }),
)

// https://github.com/vbenjs/vite-plugin-html/blob/main/packages/core/src/htmlPlugin.ts#L331
function createRewire(
  reg: string,
  page: any,
  baseUrl: string,
  proxyUrlKeys: string[],
) {
  return {
    from: new RegExp(`^/${reg}*`),
    to({ parsedUrl }: any) {
      const pathname: string = parsedUrl.pathname

      const excludeBaseUrl = pathname.replace(baseUrl, '/')

      const template = path.resolve(baseUrl, page.template)

      if (excludeBaseUrl === '/') {
        return template
      }
      const isApiUrl = proxyUrlKeys.some((item) =>
        pathname.startsWith(path.resolve(baseUrl, item)),
      )
      return isApiUrl ? excludeBaseUrl : template
    },
  }
}

The vite-plugin-html adds a proxy handling rule for text/html type request, and uses parsedUrl.pathname which doesn't contain query params (pic below) as the path to redirect. So the problem occurs when starts a document request but the xhr requests is good.

image

jonay1 commented 1 year ago

up up up

jseto commented 1 year ago

Actually, when createHtmlPlugin is enabled, any route is ignored and only the root path is rendered. This happens even with the public folder.

As a quick test:

wojtekmaj commented 12 months ago

Try vite-plugin-simple-html. It has fewer features, but as a result, far less magic required. I developed it specifically to cover my needs while not be affected by this bug, which was a blocker for me migrating to Vite.