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

Resource handler: serve index file without a redirect #678

Open
philipmw opened this issue May 1, 2024 · 2 comments
Open

Resource handler: serve index file without a redirect #678

philipmw opened this issue May 1, 2024 · 2 comments

Comments

@philipmw
Copy link

philipmw commented May 1, 2024

I am using ring's resource handler (ring/create-resource-handler) to serve a Vite application. Vite builds the application as index.html and other files in the same distribution directory. I rely on the resource handler's support for index files to serve this application. However, the resource handler's index files support doesn't work quite like I expect or would like.

When I request /, this handler responds with an HTTP 302 redirect to /index.html. This results in an undesired customer-visible URL. I want index.html to be an implementation detail, and for the resource handler to serve the content of index.html in response to GET / without a redirect. This would be consistent with how Apache httpd's mod_dir works; see default for DirectoryIndexRedirect directive.

Can you suggest how I can achieve the desired behavior of serving index.html transparently on GET /?

Some options I see:

  1. Create a custom route for just /index.html that serves my file directly, with the existing resource handler as a fallback for other routes. I imagine then I'd need to disable conflict resolution, which doesn't sound good.
  2. Add a configuration parameter to the ring resource handler to support the equivalent of apache httpd's DirectoryIndexRedirect options. Do you think this would be a good idea?
@opqdonut
Copy link
Member

opqdonut commented Sep 5, 2024

For option 1, you don't need to disable conflict resolution. You'll just have a handler set up for the path "/", and a default handler after that.

For option 2, a PR is welcome. I think it's a reasonable feature.

@philipmw
Copy link
Author

philipmw commented Dec 27, 2024

I went with option 1 for now. Documenting it here to help others, or if anyone has any suggestions for improving it:

My original ring handler definition (template from kit-clj):

(ring/ring-handler
  (router)
  (ring/routes
    (ring/redirect-trailing-slash-handler)
    (ring/create-resource-handler {:path "/"})
...))

I created a new handler:

(def index-filename "index.html")

(defn index-handler [{:keys [uri]}]
  (if (= uri "/")
    (ring-response/content-type
      (ring-response/resource-response index-filename {:root "public"})
      (mime-type/ext-mime-type index-filename))))

and plugged it into the router:

(ring/ring-handler
  (router)
  (ring/routes
    (ring/redirect-trailing-slash-handler)
    index-handler
    (ring/create-resource-handler {:path "/"})
...))

I ran into a curious problem with the mime-type. My original code was simply returning (ring-response/resource-response index-filename {:root "public"}), and it was working for me locally. Locally it was sending the Content-Type: text/html header, but once I deployed it to production, the webapp was sending Content-Type: application/octet-stream. I don't know why the discrepancy.

Once I wrapped resource-response in the content-type call, it worked well both locally and in production.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: 🇰‍🇼 Waiting
Development

No branches or pull requests

2 participants