简体   繁体   中英

Server sent response but Client not loading the sent content

I have simple node server (nodejs + express + ejs rendering) , when user tried to load a particular page server sends that compiled html and sends that in response.

In order to track users I have added 2 counters

a. counter which increments when server receives request for that page

b. when client loads the page it contains one some code which will make HTTP requests back to my server which I use as counter

Now the issue is that as time passes on the difference between sentResponse counter and clientLoad counter increases increases so much so that I get sentResponse = 7000 and clientLoad = 3600 .

Any suggesstions on what could cause that kind of behavior

Note: I also have setup Cloudfare before requests reaches my server and I paused it but still I was getting huge differences ?

Note: I also noticed that lots of users are making requests to the page frequently like multiple times under 4s but I am sure that I am sending valid html and I different is almost 50% so I dont think that every user that visits the page is pressing ctrl+r 2 or more times under 4s.

Code:

server.js

app.get('/dashboard', (res, res) => {
    ...
    ...
    ...

    Tracker.incrementCount('sentResponse');
    res.render(page.ejs, {...});
});

app.get('/client-load-start', (req, res) => {
    Tracker.incrementCount('clientLoadStart');
    res.send(200);
});

page.ejs

<html>
    <head>
        ...
        <script src='/client-load-start?version=<some_random_4_digit_number>'></script>
        ...
    </head>

    <body>
        ...
        ...
    </body>
</html>

I can think of the following possibilities on why the count could be different.

  • Setting caching headers (Cache-Control) could cause the browser to cache requests.
  • JS is not enabled in client's browser and so there is no possibility in making an AJAX call to the server to update clientLoad counter (This is less possible , but still is one of the possibility).
  • People interacted with the page even before the page loaded causing the AJAX call to not fire. People reloaded the page before the page could load.

If you are simply looking to track

You can try to use cache-busting methods. Every time the browser loads /dashboard the browser is getting a script source to your /client-load-start route. The problem is the only time /client-load-start is being requested is when the browser's cache is cleared, or the first time the site loads. This will cause the problem where the two counts can differ greatly over time.

Try to make the browser think /client-load-start is a new script that needs to be downloaded. You can do this by adding query parameters to the src.

<script src='/client-load-start?<%- Date.now()%>=1'></script>

Every time the browser goes to /dashboard it'll attempt to download the new script because the query parameters have changed thus busting the cache.

Sequence of Events

  1. Browser requests /dashboard
  2. Server increases sentResponse , renders and sends page.ejs to the browser
  3. Browser receives page.ejs and detects the <script> tag
  4. Browser checks if the script URL is in the browser cache
    • The sequence ends here if the script URL is found in the cache; clientLoad remains unchanged
  5. Browser requests script from your server
  6. Server executes get request, increases clientLoad

Problem

The "problem" here is that the browser - or any proxy between the browser and your server - will cache the returned script unless you instruct it otherwise.

Note that caching is actually expected and intended behaviour in most cases. It's also the browsers's default behaviour.

Solution

To instruct the browser (or proxies) to avoid caching the file, you can set cache control headers .

app.get('/client-load-start', (req, res) => {
    Tracker.incrementCount('clientLoadStart');
    res
       .set('cache-control', 'max-age=0; private; no-cache')
       .send(200);
});

This would instruct the browser to never cache the request and always get a new copy, thus increasing clientLoadStart with every request.

Another way is " cache busting ", meaning you intentionally change the script's URL, eg by appending a random number as you did above, thus "breaking" the cache key.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM