-
Notifications
You must be signed in to change notification settings - Fork 641
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
Use URL under /admin for live previews #1758
Comments
I'm wondering if providing a subdomain which on Cloudflare DNS control points to the base IP but is set to bypass caching (grey bypass arrow) will solve your problem. I use this to avoid similar issues with sftp for various accesses that need it, such as direct editing, usually for staging when that is on a remote server.. The setting on Cloudflare means that only the DNS is being handled, with no influence from any Cloudflare process possibilities on the data transferred -- which is then actually coming direct from your server. You'd run admin then on the subdomain, |
Sorry - above got truncated before sent -- repaired. |
Using (AWS) Cloudfront here, not Cloudflare. This (or just bypassing the CDN entirely) would possibly work in this particular case as long as Craft doesn't build full URLs including the domain when doing things like generating live preview URLs. But I believe it does, and so the requests would just end up being sent to the regular Cloudfront-domain URLs anyway. I wonder if this is a configuration issue. But bypassing the CDN by using a different subdomain would not help in the case where people are already using different subdomains for different pages on their site, as described here. My suggested change would, I believe, handle that case too. |
Think you've got your names swapped (Cloudfront is AWS), but see your points. Indeed actually the site itself won't run, much less CP, with a subdomain url. But this is rewritable to the expected url via nginx config or apache .htaccess, no? I'm kind of wondering if this approach might also remove the subdomains problem you mention also -- maybe you could try it. |
Yes, I noticed after posting and edited it.
I think perhaps we don't understand each other. If I'm understanding your suggestion correctly, I would have a new subdomain But the Craft website is configured to know that its URL is
I don't have a site which has different subdomains for different languages. It's just a problem I foresee (for other people) with having a special "admin" subdomain. You'd need special "admin" subdomains for each language subdomain then, and I'm guessing Craft would have to be aware of the mappings. It seems like it would be overcomplicated. Do you see any issues with my suggested fix of moving all live preview endpoints to some URL under |
The reason LP uses the normal entry URL is so any conditions/other logic in templates that factor in the entry URL will work as expected, and any relative CSS/JS URLs will load correctly. We could fake the entry URL for template logic if we switched to something like this, but it would still break relative CSS/JS URLs (not that people should be doing that anyway). That said it’s worth considering, especially when we get around to #1521 & #1489 |
About to leave here, but some quick responses:
|
Clients' IPs, not server IPs. We wouldn't want a non-cached entry point to the site available to the public. I suppose we could add HTTP basic auth on this special domain and lock it down that way...
But as I said, Craft sends the POST request to its canonical URL, not to the current one, so how would the live previews hit |
Interesting. Would adding a
Agreed. I wouldn't be against breaking live preview for these users and documenting it... |
@tremby sorry, really am in a hurry .Think this looks good on quick scan, about how it's done on nginx, and similarly enough for apache. On the auth/available problem, not sure I see that if SEO (answerable via canonical would seem) isn't the issue, but that's up to you and client of course - a pleasant smile :) As well, seems you could with related server config also redirect if someone accessed the non-cached url not as a CP request, which wouldn't need the headache of auth. Given Craft is set up properly with regard to clicking on the Site name from CP, should work even there? Best fortune, in any case, Bart, and you see Craft principals are already on the case...! |
Probably but we'd also need to check if they already define a |
Sorry, but I really still don't see how this helps. Aren't these just regular rewrite rules, which change how the server interprets a request URL or cause an HTTP redirection to elsewhere? The problem is the URLs the server (Craft) is sending back out. In the Javascript chunk for live previews, for example, it gives the URL to send the POST request to as a full URL with domain, and that domain is the canonical domain. So the Javascript will then send the POST request to the canonical domain. Are you suggesting I set up rewrite rules on the |
Definitely crossed wires here, and my hurry isn't helping.
Ok, and that really is all I can cook up for now. Fire away though for the thread where I'm missing something, as likelihood seems reasonably high at this level of handwaving -- cheers |
They'd have a common ancestor domain, so with CORS and cookie domain set up correctly that shouldn't be an issue. It's still the issue that the POST will go to the canonical URL, and that this will point at Cloudfront.
This is exactly what my original post here is suggesting, but which Brandon points out could break theme logic and relative CSS/JS URLs. In the mean time I'm exploring some solutions. The current one I'm exploring is a small opinionated patch on Craft CMS (:-1:) to alter the preview URLs sent out, combined with some nginx configuration. If I come up with a working solution I'll post it, but as yet I've found no way to do this without altering Craft code. |
OK, my current solution is this:
The browser sends the auth cookie through thanks to the cookie domain being an ancestor of both sites, and the alternative domain allows the POST request due to its CORS headers. The alternative domain hits PHP with the request with serves the response. Any GET requests which come through to the alternative domain (maybe for assets and that kind of thing, or followed links to other pages) will get I don't much like this solution. |
(couldn't get out of here, realized it will have to be tomorrow)
Regards, |
I agree with everything you've said. I hope changing the endpoint for live previews is something which might eventually make it into Craft. I guess it's just a matter of making a decision about whether it's okay to break live previews for sites with relative asset URLs. In the mean time, I wonder if there are any ideas about how I might alter my above solution so that no files from Craft itself are modified? Is there a way I can achieve the same thing by configuration and possibly extending classes rather than editing core files? |
You know, I had another quick go at this and discovered Cloudfront rule matching is pretty unelaborate, no doubt for the efficiency - no regex-like abilities. A glance at CloudFlare doesn't show much better. Reading once again your original problem statement, though, might you be able to solve by simply excluding any CP (admin) paths from caching? At first glance this looks unsupported, as there isn't a NOT operator in path patterns, but then I stumbled across something which you can find on this page: Developer Guide
So, could your solution be to encode a rule matching the Craft admin introducer, which doesn't cache, and put that rule before others that do? ...I am quite possibly being too simpleminded about this, and also this time jumping right out the door, but you can look at it... |
That doesn't help. The |
Hmm, yes, you did say that at the outset. I was in fact fishing around in the code at some rapid rate this afternoon and wanted to think it said something else, but what I saw makes more sense this way. I believe I might have misinterpreted your example because it looked like (though reversed of) the number-hyphen addition the CP puts on the entry slug when editing it; was thinking too much about that.
Very interested actually in what you might make of one of these paths, Bart. p.s. just for completeness I went out looking for any equivalent services on CloudFlare. I didn't find any, though there are a number of initiatives for public domain or commercial Lambda alternatives on platforms, not so far along yet it seemed. However, CloudFlare has by now long had Railgun, a different take on active page caching, which I once tried to pretty nice results for a site needing European presence, potentially serving especially Russia. Using CloudFlare, you could go to the simple alternative uncached domain equivalent I early mentioned here, and as you actually use in your patch scheme above. Probably not attractive since you appear embedded with AWS, but any of these mentioned could possibly be worth a little keeping track of, no? |
The Lambda@Edge idea is interesting, and I'll look into it. Thanks. |
Good enough. I had a flash this morning on why CloudFlare/Railgun didn't seem to have problems that you run into with the SessionId cookie. It's because it sends back only the delta for the cached item each time. This means you pay at least ttfb including latency for each page access, so it is not quite as effective as a cache, though they employ a pre-http/2-spdy persistent channel that speeds up any other delta. Still, this flavor might interest, if you don't get somewhere positive with Lambda for example. If you wanted to try an experiment with it, Arcustech who runs Craft's own site and has a long good history with the community offers Railgun-included even on lowest-price hosting; you just have to ask for it. |
I don't understand. If you are sending a |
In my present view of how Railgun works, nothing is filtered out -- that was the basis of the flash. SessionId, CSRF, and any other changed cookies would all come through as efficient deltas, with the minimal delay of one accelerated server access, then patched into the cached delivery of all the rest. |
I looked up Railgun. I appears to be a compression scheme between the origin server and the CDN. It's not something we're interested in, but thanks. |
Well, I think you'll find it's actually a cache -- overlaid with the accelerated delta of anything that does actually change on active pages. A careful read of first section here? https://www.cloudflare.com/docs/railgun/intro.html The normal cache operation occurs for non-active accesses like images, js, etc.. But anyway, of course you have to see what's good for your purpose... |
I did read it. We want public pages which are essentially static (which is everything but admin pages) to be cached too. Requests for each should not hit the origin server more than once per hour or so. Even with Railgun the origin server is still fully processing each request and building the response, and then additionally the Railgun daemon is processing or diffing it in whatever way Cloudflare has devised and sending a smaller payload back to the CDN. |
All true, and only you know how efficient you want to be. It's just natural on long experience to question the degree necessary -- realities vs. ideal concept images -- but probably you and team are well aware of that also, as a 'disease', 'sometimes' occuring in software circles :) |
Bart, you may well be tired of hearing from me on this, but something possibly interesting got pushed to my phone by Google Now over the weekend. http://codingthesmartway.com/introduction-to-server-rendered-vue-js-apps-with-nuxt/ Given you could fit with Vue, nuxt-generate would produce a completely static image of your site at will. Given your site is so largely static as you indicate, may be a way to quite simplify matters? The developers look an interesting bunch, in any case. Their doc site here is running this kind of static arrangement, and turns out they even use a Lambda script to cleanly deploy it. |
As well, the Vuejs-nuxt discussion of async data suggests a couple of things:
Not delving into this, but quite possibly /action could be useful this way also for protecting any actions that would like to have session information...whether that comes up now or in the future. |
The agency I'm contracting for launched a new site today, this time with Craft 3. It seems nothing changed on this topic between Craft 2 and 3 -- still no previews possible with the CDN setup we want. So I had a go at making the Lambda@Edge function suggested above and have that working. Cloudfront is set up like this:
This Lambda function simply removes any cookies from incoming HEAD and GET requests, and leaves others alone. Here it is: exports.handler = async (event) => {
// See https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-event-structure.html
const request = event.Records[0].cf.request;
if (['HEAD', 'GET'].includes(request.method)) {
// These methods are cacheable and we don't ever take the cookies into
// account. Remove them from the headers.
delete request.headers.cookie;
}
// For other methods like POST we want to take cookies into account, since
// they matter for page previews (and possibly in other cases).
return request;
}; This has the effect of allowing cookies through for POST requests for the default ruleset, which is exactly what we need for previews. Cookies are removed from GET and HEAD requests, so they can be cached as they usually would be. |
@tremby this is basically what I tend to do when working with Varnish ... I only cache HEAD and GET then strip all cookies from most requests and just let action ones keep their cookies and bypass the cache. I did want to try and use something more off the shelf like CloudFront but keep steering away given how finicky you have to get with all this! Good to see your solution. |
We’ve made checking for Live Preview requests in Cloudfront/CloudFlare much easier in Craft 3.1, as now Live Preview requests are sent with |
Currently live previews work by making a POST request to an entity's public URL.
For example, an entity which would normally be publicly visible via a GET request to
/articles/article-1
is live previewed by making a POST request to/articles/article-1
while logged in as an admin.This causes live preview to fail when using Cloudfront (a caching CDN) for delivery of the website:
/admin/
prefix./articles/article-1
we either have to always drop the session ID cookie or never drop it. But it renders Cloudfront pretty useless if we never drop it.If the endpoint for all live previews was at a particular URL (something under
/admin
would be appropriate, since it's an admin function) we could add a Cloudfront rule to allow the cookie for POST requests there, and live previews would work.Some suggestions:
POST /admin/live-preview?url=%2Farticles%2Farticle-1
with no change to posted dataPOST /admin/live-preview
with something likeurl=/articles/article-1
added to the posted dataThis shouldn't affect cross-domain live previews; those could either be sent to the other domain's
/admin/live-preview
endpoint, or to the current domain's one with the full URL including domain in the data being passed.The text was updated successfully, but these errors were encountered: