ElMassimo / ElMassimo/vite_ruby
Inquiry: absolute-form REQUEST_URI not stripped by DevServerProxy#normalize_uri — Hanami-only regex misses RFC 7230 absolute-form
- Dominant language
- Ruby
- Stars
- 1.6k
- Forks
- 149
- Avg merge
- 5h 13m
- Merged PRs (30d)
- 2
Description
[troubleshooting section]: https://vite-ruby.netlify.app/guide/troubleshooting.html
- [x] I have tried upgrading by running `bundle update vite_ruby`.
- [x] I have read the __[troubleshooting section]__ before opening an issue.
### Description 📖
Filing as an inquiry rather than a pure bug report — want to confirm whether this is known/intentional before sending a PR.
In our setup, `env["REQUEST_URI"]` sometimes arrives at `ViteRuby::DevServerProxy` as an RFC 7230 §5.3.2 absolute-form URI (`https://host/vite-dev/...`) rather than origin-form (`/vite-dev/...`). This causes `DevServerProxy` to forward an absolute-form request-target to the Vite dev server. Vite's `baseMiddleware` then returns the "public base URL of /vite-dev/ — did you mean to visit …" error page because `req.url.startsWith('/vite-dev/')` is false when `req.url` is a full URL.
`normalize_uri` already exists to defend against this class of problem (the comment reads "Hanami adds the host and port"), but the regex is narrow to `host:port/`:
https://github.com/ElMassimo/vite_ruby/blob/vite_ruby%403.10.2/vite_ruby/lib/vite_ruby/dev_server_proxy.rb
```ruby
HOST_WITH_PORT_REGEX = %r{^(.+?)(:\d+)/}
def rewrite_uri_for_vite(env)
uri = env.fetch("REQUEST_URI") { ... }
env["PATH_INFO"], env["QUERY_STRING"] =
(env["REQUEST_URI"] = normalize_uri(uri)).split("?")
end
def normalize_uri(uri)
uri
.sub(HOST_WITH_PORT_REGEX, "/") # Hanami adds the host and port.
.sub(".ts.js", ".ts")
.sub(/\.(sass|scss|styl|stylus|less|pcss|postcss)\.css$/, '.\1')
end
```
With `REQUEST_URI = "https://our.frontend.dev/vite-dev/@vite/client"`:
- `HOST_WITH_PORT_REGEX` requires an explicit `:\d+`. Default HTTPS (443) has no port in the URI, so the regex does not match.
- `normalize_uri` returns the string unchanged.
- `PATH_INFO` is rewritten to the full URL.
- `rack-proxy` uses `source_request.fullpath` verbatim, sending `GET https://our.frontend.dev/vite-dev/@vite/client HTTP/1.1` to the Vite dev server.
- `baseMiddleware` rejects.
Questions:
1. Is this a known limitation? I searched open/closed issues and didn't find a match (closest are #194 and #231, which are different).
2. Was `HOST_WITH_PORT_REGEX` restricted to `host:port/` intentionally, or simply because Hanami was the only shape encountered at the time? Absolute-form in `REQUEST_URI` seems plausibly common under TLS-terminating reverse proxies and Rack instrumentation libraries.
3. Would a broadening like this be acceptable? Happy to send a PR with tests:
```ruby
def normalize_uri(uri)
uri
.sub(%r{\Ahttps?://[^/]+}, "") # RFC 7230 absolute-form
.sub(HOST_WITH_PORT_REGEX, "/") # Hanami-style host:port/
.sub(".ts.js", ".ts")
.sub(/\.(sass|scss|styl|stylus|less|pcss|postcss)\.css$/, '.\1')
end
```
### Reproduction 🐞
No minimal repro yet — in our own app the absolute `REQUEST_URI` originates somewhere in a complex Rack/Puma load path we haven't fully isolated. The general-principle question is whether `DevServerProxy` should be resilient to the RFC absolute-form shape given it already has a defense for the Hanami variant.
If a reproduction is required before you want to look at this, I can work on isolating a minimal Rack middleware that reproduces the env shape.
Vite Ruby Info
_Run `bin/rake vite:info` and provide the output:_
```
bin/vite present?: false
vite_ruby: 3.10.2
vite_rails: 3.10.0
rails: 8.0.2
ruby: ruby 3.3.11 (2026-03-26 revision 1f2d15125a) +YJIT [aarch64-linux]
node: v25.9.0
yarn: 4.9.2
```
Additional versions from Gemfile.lock / yarn.lock:
| Component | Version |
|---|---|
| `rack-proxy` | 0.7.7 |
| `rack` | 2.2.9 |
| `puma` | 6.4.2 |
| `vite` (Node) | 5.4.21 |
| `vite-plugin-ruby` (Node) | 5.0.0 |
### Logs 📜
Symptom in the browser:
> The server is configured with a public base URL of /vite-dev/ - did you mean to visit /vite-dev/… instead?
Debug confirming `REQUEST_URI` is absolute before `DevServerProxy` runs (prepended logger in front of `forward_to_vite_dev_server`):
```
[vite-proxy] REQUEST_URI="https://our.frontend.dev/vite-dev/@vite/client"
PATH_INFO="/vite-dev/@vite/client"
HTTP_HOST="0.0.0.0"
```
For comparison, a sibling app on the same infra produces origin-form and works:
```
[vite-proxy] REQUEST_URI="/vite-dev/@fs/.../some-dep.js?v=3347216f"
PATH_INFO="/vite-dev/@fs/.../some-dep.js"
HTTP_HOST="sibling.frontend.dev"
```
Vite's own debug (`DEBUG=vite-plugin-ruby:*`) confirms `base: '/vite-dev/'` resolves correctly and the plugin chain is intact — the issue is purely that the request-target arriving at Vite is absolute-form.
### Screenshots 📷
(None — error text above is the complete browser output.)
Contributor guide
Assessment
This issue has not been assessed yet.