Skip to content

Commit 70d8cc0

Browse files
authored
feat: redirect vite.plus vanity domain to installer scripts (#30)
## What The `vite.plus` apex domain now points at this Worker. This adds a host-based redirect so the short domain works as an installer entry point: | Request | Result | | --- | --- | | `https://vite.plus` | 302 -> `https://viteplus.dev/install.sh` | | `https://vite.plus/ps1` | 302 -> `https://viteplus.dev/install.ps1` | So `curl https://vite.plus | sh` and `irm https://vite.plus/ps1 | iex` both work. ## How New middleware `middleware/02.redirect-vite-plus.ts`, mirroring the existing `01.redirect-to-custom-domain.ts` pattern with an extracted, unit-tested `buildViteplusRedirect()` helper. - Only the `vite.plus` apex host is matched. The canonical `setup.viteplus.dev` host, the legacy `vp-setup.void.app` host, and `localhost` (dev) fall through untouched, so the download page and existing legacy redirect keep working. - `www.vite.plus` is intentionally not matched (only the apex was requested). - Any path other than `/ps1` defaults to `install.sh`; a trailing slash on `/ps1` is tolerated. ## Tests Adds `tests/redirect-vite-plus.test.ts` (9 cases): both redirect rules, trailing slash, arbitrary paths, query strings, and the null/fall-through cases for other hosts and a missing host header. `vp check` and `vp test` (31 tests) pass. ## Note for deploy For these redirects to fire, `vite.plus` must be attached as a custom domain/route on the deployed Worker, not just pointed via DNS. Once requests reach the Worker with `Host: vite.plus`, the redirect applies.
1 parent 61b472c commit 70d8cc0

2 files changed

Lines changed: 70 additions & 0 deletions

File tree

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { defineMiddleware } from "void";
2+
3+
// The vite.plus vanity domain exists purely as an installer entry point:
4+
// curl https://vite.plus | sh -> shell installer
5+
// irm https://vite.plus/ps1 | iex -> PowerShell installer
6+
const INSTALL_HOST = "vite.plus";
7+
const INSTALL_SH = "https://viteplus.dev/install.sh";
8+
const INSTALL_PS1 = "https://viteplus.dev/install.ps1";
9+
10+
export function buildViteplusRedirect(host: string | undefined, requestUrl: string): string | null {
11+
if (host !== INSTALL_HOST) return null;
12+
const path = new URL(requestUrl).pathname.replace(/\/+$/, "");
13+
return path === "/ps1" ? INSTALL_PS1 : INSTALL_SH;
14+
}
15+
16+
export default defineMiddleware(async (c, next) => {
17+
const target = buildViteplusRedirect(c.req.header("host"), c.req.url);
18+
if (target) return c.redirect(target, 302);
19+
await next();
20+
});

tests/redirect-vite-plus.test.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { describe, expect, it } from "vite-plus/test";
2+
import { buildViteplusRedirect } from "../middleware/02.redirect-vite-plus";
3+
4+
describe("buildViteplusRedirect", () => {
5+
it("redirects the bare domain to the shell installer", () => {
6+
expect(buildViteplusRedirect("vite.plus", "https://vite.plus/")).toBe(
7+
"https://viteplus.dev/install.sh",
8+
);
9+
});
10+
11+
it("redirects /ps1 to the PowerShell installer", () => {
12+
expect(buildViteplusRedirect("vite.plus", "https://vite.plus/ps1")).toBe(
13+
"https://viteplus.dev/install.ps1",
14+
);
15+
});
16+
17+
it("tolerates a trailing slash on /ps1", () => {
18+
expect(buildViteplusRedirect("vite.plus", "https://vite.plus/ps1/")).toBe(
19+
"https://viteplus.dev/install.ps1",
20+
);
21+
});
22+
23+
it("redirects any other path to the shell installer", () => {
24+
expect(buildViteplusRedirect("vite.plus", "https://vite.plus/anything")).toBe(
25+
"https://viteplus.dev/install.sh",
26+
);
27+
});
28+
29+
it("ignores query strings when picking the target", () => {
30+
expect(buildViteplusRedirect("vite.plus", "https://vite.plus/?ref=docs")).toBe(
31+
"https://viteplus.dev/install.sh",
32+
);
33+
});
34+
35+
it("returns null for the canonical download host", () => {
36+
expect(buildViteplusRedirect("setup.viteplus.dev", "https://setup.viteplus.dev/")).toBeNull();
37+
});
38+
39+
it("returns null for the legacy host (handled by its own middleware)", () => {
40+
expect(buildViteplusRedirect("vp-setup.void.app", "https://vp-setup.void.app/")).toBeNull();
41+
});
42+
43+
it("returns null for localhost during dev", () => {
44+
expect(buildViteplusRedirect("localhost:5173", "http://localhost:5173/ps1")).toBeNull();
45+
});
46+
47+
it("returns null when the host header is missing", () => {
48+
expect(buildViteplusRedirect(undefined, "https://vite.plus/")).toBeNull();
49+
});
50+
});

0 commit comments

Comments
 (0)