red house 87
red house 87

Reputation: 2415

Server side rendering issue over a CDN

I have recently launched a site that uses server side rendering (with next.js). The site has login functionality where if an authentication cookie is present from a user's request then it will render a logged in view for that user on the server and return the rendered logged in view to the users browser. If the user does not have an authentication cookie present then it renders a logged out view on the server and returns that to the users browser.

Currently it works great but I have hit a snag when trying to serve the site over a CDN. My issue is that the CDN will cache a servers response to speed it up so what will happen is the first user to hit the website on the CDN will have their logged in view cached and returned to the browser. This in turn means because it is cached then other users who hit the site also see the other users logged in view as opposed to their own as that's what has been cached by the CDN. Not ideal.

I'm trying to think of what the best way to solve this problem would be. Would love to hear any suggestions of the best practice way to get around this?

One way I have thought of would be to potentially always return a logged out view request on the first page visit and so the authentication/ logging in client side and from then on always do the authentication on the server. This method would only work however if next.js only does server side rendering on the first request and let's subsequent requests do all rendering on the client and I'm not sure if that's the case.

Thanks and would love all the help/ suggestions I could get!

UPDATE

From what I can gather so far from the answers it seems that the best way for me to get around this will be to serve a CDN cached logged out view to every user when they first visit the site. I can then log them in manually from the frontend if an authentication token is present in their cookies. All pages after the first page they land on will have to return a logged in view - is this possible with Next.js? Would this be a good way to go about it? Here is a summary of these steps:

  1. The user lands on any webpage
  2. A request is made to the server for that page along with the users cookies.
  3. Because this is the first page they are visitng the cookies are ignored and a "logged out" view is returned to the users browser (that will have been cached in the CDN)
  4. The frontend then loads a logged out view. Once loaded it checks for an authentication token makes a call to the API to log them in if there is one present
  5. Any other page navigation after that is returned from the server as a "logged in" view (ie the authentication cookie is not ignored this time). This avoids having to do step 4 again which would be annoying for the user on every page.

Upvotes: 10

Views: 5121

Answers (4)

Masih Jahangiri
Masih Jahangiri

Reputation: 10907

All CDNs cache and distribute data rely on the cache header in the HTTP response. You should consider these two simple notes to get the best performance without miss the power of CDN.

1. No-cache header for dynamic content (HTML response, APIs,...):

  • You should make sure all dynamic contents (HTML response, APIs,...) cache header response is Cache-Control: no-cache.
  • If you're using next.js can use a custom server (express.js) to serve your app and full control on the response header or you can change next.js config.

2. Set cache header for static content (js, CSS, images, ...)

  • You should make sure all statics contents (js, CSS, images, ...) cache header response is Cache-Control: max-age=31536000.
  • If you're using next.js in every build all assets have a unique name and you can set a long-term cache for static assets.

Upvotes: 1

Brad
Brad

Reputation: 163334

For well-behaved caching proxies (which your CDN should be), there are two response headers you should use:

Cache-Control: private

Setting this response header means that intermediary proxies are not allowed to cache the response. (The browser can still cache it, if it's appropriate to do so. If you want to prevent any caching, you'd use no-store instead.)

See also: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control

Vary: Cookie

This response header indicates that the data in the response is dependent on the Cookie request header. That is, if my request has the header Cookie: asdf and your request has the header Cookie: zxcv, then the requests are considered different, and will be cached independently. Note that using this response header may drastically impact your caching if cookies are used for anything on your domain... and I'd bet that they are.

See also: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Vary

An alternative...

A common alternative approach these days is to handle all the user facing dynamic data client-side. That way, you can make a request to some API server which has no caching CDN at all. The page is then filled client-side with the data needed. The static parts of the site are served directly from the CDN.

Upvotes: 3

felixmosh
felixmosh

Reputation: 35493

Try to add cache control header to your Auth required pages.

Cache-Control: Private

The private response directive indicates that a resource is user specific—it can still be cached, but only on a client device. For example, a web page response marked as private can be cached by a desktop browser, but not a content delivery network (CDN).

Upvotes: 0

Ankush Chavan
Ankush Chavan

Reputation: 1184

What I understand from your question is that when a user logged in, the logged-in view is getting cached on the CDN and when the user is logged out then also the site is shown in the logged-in view from the CDN cache.

There are some solutions to this issue are as follows:

  1. Set some TTL(Time To Live) for the CDN so that it will automatically invalidate the cache data after a specific time.
  2. As you want to deliver the site fastly means you want to achieve low latency. For this you can do one thing, just cache the big files from the website like images, videos, documents, etc to the CDN. And don't cache the entire website there. Now, every time the user request comes then the site will be served from the regular server and the media files will be taken from the CDN. In this way, you can achieve low latency. And as the media files are taken from the CDN cache, the website code will load fastly and the site will be served quickly. In this way, the authentication will be done on the server-side.
  3. Another solution would be to invalidate the cookie and the authentication after a certain time of inactivity. And after that when a user comes then the site should render a logged-out view.

Upvotes: -1

Related Questions