Can Pages do rewrites (not redirects)
Hi. I'm trying Cloudflare Pages as an alternative to Firebase hosting for my existing site. I'm having a pretty positive experience so far, especially with the build-from-git integration. But I've come to an issue which seems to block the migration.
Amongst some of the routes my static site uses I have ones that have a pattern such as
/ws/<wsid>/viewtypexxx
, which I would like to be rewritten as /ws/viewtypexxx.html
. By "rewritten" I mean the httpd server serves the content of the latter when the client requests the former. The JS in my page parses the wsid value out of the location for itself so the right content is loaded dynamically after initial page load.
I'm not finding any solution in docs, but it doesn't say clearly that it isn't supported either, and rewrite rules seem common enough these days in other hosting I've been uisng over the last couple of years. Are they supported?10 Replies
Not out of the box, but you could create your own _middleware.js which does the rewrite for you
(https://developers.cloudflare.com/pages/functions/middleware/)
Thank you for showing that example, and clearing up there isn't a rewrite config option in Pages.
Part of my reason for trying out Cloudflare was to see if workers were going to be better for me than firebase's "cloud functions", for something else unrelated to this question.
So I'm not against trying a worker. And you're making it very easy for me by providing the sample, much appreciated. But doesn't this introduce cost, and latency. Sounds like two servers are going to be involved - a workers server (with it's v8 js runtime daemon?) and then a network hop to the static content-serving httpd.
Yeah, technically there is a small overhead, but the worker is executing at the edge close to your users. I think even with this type of setup you're probably better than firebase (which could definitely have higher cold start times unless you pay for reserved instances)
At this point if hadn't been planning to use workers already, for a different reason, I think I would move on. I appreciate that the javascript workers support high flexibility, but on the other hand this one rule becomes its own script, kept in subdirectory in the source that I would bet other collaborators won't think to look into for site config, when they're checking it.
I know what I'll do, I'll probably add a dummy _redirects file, because that sounds like it could be related, _rewrites file (which means nothing to Pages hosting, but it'll be noticed) and write a comment in there explaining the middleware worker is doing it.
But I will try it.
This was not successful.
Firstly adding the class specifier(?) MiddlewareHandler was reported as a syntax error. And it doesn't appear in the documentation either. So I removed it, after which the build with my new functions/_middleware.js file succeeded.
But using this middleware function the page request to
https://xxx.com/ws/<wsid>/ts
was redirected by a HTTP 308 response to https://xxx.com/ws/ts
, not 'rewritten' by supplying the content of /ws/ts[.html]
at the request path of /ws/<wsid>/ts
.
("ts" is one value for what I described as viewpagexxx yesterday.)
When I saw the fetch() call in the example kindly provided yesterday I had faith it would work as I was thinking, but somehow it's become this 308 redirect instead.
I worked out a correct function. The key thing was using env.ASSETS.fetch(), not plain fetch() (or whatever it is that fetch() is in cloudflare worker).
I'm using onRequestGet rather than onRequest simply because I know that is the only HTTP verb that will be used on these routes.
If it does, then that documentation needs improvement.
Currently it says:
"Redirects" / "Yes" (supported), but only with HTTP codes "(301, 302, 303, 307, 308)"
"Rewrites" / "No" (not supported).
Is the thing I learnt to call "rewrite" rules from other hosting solutions called proxying here?
FYI some other hosting (and dev server) where the term is called rewrite rule:
https://firebase.google.com/docs/hosting/full-config#rewrites
https://github.com/lwsjs/local-web-server/wiki/How-to-rewrite-URLs-to-local-or-remote-destinations
https://docs.digitalocean.com/products/app-platform/how-to/url-rewrites/
I think it might have become popular when SPAs became a common thing, not that I'm using an SPA.
I tested your suggestion Skye. I assumed you meant try a 'proxying' rule. In my case that is:
This failed - it became a redirect, with an not-really-being-used-as-it-is-supposed-to-be 200 HTTP response code.
And not a URL rewrite.
There's a lot of confusion about URL rewrites.
I think confusion is expanding as the document for DNS proxying (which is out of scope for Pages, and my deliberately simple static site) has URL rewrites:
https://developers.cloudflare.com/rules/transform/url-rewrite/
URL rewrite: A server-side operation that converts a source URL into a target URL. It occurs before a web server has fully processed a request. A rewrite is not visible to website visitors, since the URL displayed in the browser does not change. Configure URL Rewrite Rules to perform rewrites on the Cloudflare global network without reaching your web server.
URL redirect: A client-side operation that converts a source URL into a target URL. It occurs after the web server has loaded the initial URL. In this case, a website visitor can notice the URL changing when the redirect occurs. Refer to Redirects to learn more about configuring redirects.The *.html value is the correct path to the file asset though. And it worked at doing the redirect, the user sees the path in the URL bar become
/ws/<wsviewname>.html
when it should have stayed /ws/<wsid>/<wsviewname>
the same as was requested from the link going to it from a prior page.
And also, I've already spent the time to get out of that testing branch and merge / pull things as they should be in the main branch again, I'm not going to spend the time reopening that testing setup again.
You were right @Skye
I really didn't want to go back into it, but I am nothing if not methodical.
With the .html suffix the request to files became a 308.
Would you like the HAR files for reference?
I took one at each of three cases - using the functions middleware, trying your suggested syntax without the actual file suffix, and then again with what I did yesterday.
They're small.I was doing this in Firefox, in case it doesn't open in Chrome ... I've never tried the cross compatibility of those now I think about it.
Ah, an extra gotcha - after having the 308 I think it persisted, as you would expect given it is the "Permanent Redirect" one. So deploying the right redirect rule was at first going to the incorrect URL. I had to disable cache for a bit to get past it.
Something else to keep in mind if you create a Docs ticket.
Hi @Skye .
No, it was using
/ws/:wsid/:wsview.html /ws/:wsview 200
that caused the 308 redirect.
But when I edited and redeployed with /ws/:wsid/:wsview /ws/:wsview 200
the requests to were still going wrong - my hypothesis is my browser (Firefox) 'remembered' the 308 and keep following that.
Disabling cache in the network pane of the developer tools and requesting again was the resolution.
I'm just sharing this detail in case any other public reader is trying something similar and is being fooled by the after-effects of a redirect even after they deploy.