FreshPorts now answers “not modified”

In FreshPorts October speed-up I wrote about making pages cheaper to build. This post is about not sending them at all, when your browser already has the latest copy.

Conditional GET

When FreshPorts sends a page, it can include a Last-Modified time and an ETag, a short tag for that version of the page. On your next visit, the browser sends them back and asks whether anything has changed. If nothing has, the server answers 304 Not Modified with no page at all, and the browser shows the copy it already has.

FreshPorts has had code for this for many years. While adding the release number to the source of /other-copyrights.php, I found that it had never worked for browsers. The browser sends the ETag back in quotes, as the standard says, and FreshPorts compared it with a copy without quotes. They never matched. It also required both headers to match, when the ETag alone should decide. Only clients that send the time alone, such as some crawlers, ever got a 304.

Wrong answers for the few who got one

For those clients, many pages gave the wrong answer:

  • The information pages (About, FAQ, Privacy and others) used the date of their own file. That date does not change when a release changes the shared header or the sidebar, or when you log in, so a 304 could bring back a stale sidebar.
  • Search used the current time, which almost never matches, but sometimes did within the same second.
  • The port pages used only part of their cache, so a change to the packages section did not change the page's time.

The information pages, search, the commit pages and the daily pages no longer send a Last-Modified or ETag. Their content depends on too many things to sum up in one time.

What sends a 304 now

The following all send a 304 now after this release: port pages, category pages, the list pages (broken, deprecated, and so on), New ports, and /other-copyrights.php. Their content comes from the cache, and their time is the time of the cache entry, which is emptied when a commit arrives. A port page uses the newest of its four cached parts.

The ETag also changes with:

  • the release, so a new release always sends a fresh page
  • your language
  • who is logged in, so logging in or out gets you the right sidebar
  • on a port page, whether the port is on your watch list, so the icon is right after you add or remove it

A port page is about 14.8 KB compressed. A 304 has no body. The server still checks its cache, but it no longer builds or sends the rest of the page.

Every page with the sidebar, which shows who is logged in, now also sends Cache-Control: private, no-cache. Shared caches, such as a company proxy, must not keep the page, and your browser checks with FreshPorts before reusing its copy.

Try it

Ask for a port page and note its ETag:

curl -s -D- -o /dev/null https://www.freshports.org/sysutils/bacula15-server/ | grep -i etag

Then send that ETag back, quotes included:

curl -s -o /dev/null -w '%{http_code}\n' -H 'If-None-Match: "the etag from above"' https://www.freshports.org/sysutils/bacula15-server/

You should see 304. Change one character of the ETag and you get 200 and the whole page.

Releases

  • 2.16.13: the fix itself, and the pages that no longer send a time
  • 2.16.14: port pages count every cached part and the watch list status, found while testing
  • 2.16.15: a logged-in browser no longer downloads a port page in full again after each cache rebuild

All three reached www.freshports.org on 25 October 2026. I checked the 304s on every FreshPorts server.

Website Pin Facebook Twitter Myspace Friendfeed Technorati del.icio.us Digg Google StumbleUpon Premium Responsive

Leave a Comment

Scroll to Top