Welcome Guest, Not a member yet? Register   Sign In
Caching and headers

You'll have to remind me what DRY stands for.

You're right, this is just the important bit from Suffix cache. But actually the problem you've highlighted has nothing to do with this. It's a problem already present in the CI core. Without the additions I've made, your problem will still crop up (and with them too); indeed, these additions don't even address that problem, Suffix cache does (per title).

My additions fix the problem one step along the way. If both index.css and index.js both have caching enabled, currently in CI one will overwrite the other. The next time you load index.css you'll get the JavaScript. All my additions will do will make that JavaScript come along with a "text/javascript" Content-Type header (if you'd set it).

In other words, the problem you've described is actually two problems: the lack of cached headers, and the lack of suffix recognition. Suffix cache solves both. My addition solves just one (the caching of headers). Neither causes the problem you're describing. CI has been causing that one on its own.

DRY = Don't repeat yourself.

In my setup, I'm using suffixes to divert my controller call down different rendering paths. Different XSL can be specified, unique css and js, or even just as a way to avoid the cache library such as when session->flashdata is being used. This saves me from having to keep a separate URI for each mime-type. Since, I am not repeating controller code, I am DRY.

[quote author="beemr" date="1216696902"]DRY = Don't repeat yourself ... Since, I am not repeating controller code, I am DRY.[/quote]

As far as I can see, then, what I'm suggesting is bone-DRY. Currently you may have a page styles/css sent with header "text/css". Cached, it's sent without that header.

To send the cache with the header, you'd have to somehow hard-code in an extension that if $this->uri->uristring() == "styles/css", send the header. i.e. repeat yourself in the hard extra coding.

Or just fix CI so that that header was cached too.

[eluser]Randy Casburn[/eluser]
@Derek -- Anyone

Has anyone looked at the OP's query at the top of this post lately?

Quote:I want that CSS cached so it isn’t generated every time. But I also must send the “text/css” mimetype header, or it won’t work.

First, the short term fix:

- @OP - Please allow me to offer a short term solution while you are waiting for a longer term solution. The short term solution to your problem is to place your CSS style information directly into your View file's HTML <head> tags. While this may not be ideal, it will certainly ensure your CSS is cached, thereby resolving this issue in the short term.

If you want to cache CSS by sending a header into the cache there are deeper questions to be resolved.

1) This implies you are generating your style sheet dynamically on-the-fly and the header is only the first part. If "you want the CSS cached" you MUST load the remainder of the style information into an appropriate storage location for the CSS to be cached along with the header.

-- you've not disclosed that part of your use case or how you intend on solving or coding that solution

2) If you are not generating the style sheet on-the-fly you've not provided the code for reading the style sheet from disk so that it can be loaded into the cache. Please provide the method for that as well.

3) if your intent is not:
Quote:I want that CSS cached so it isn’t generated every time...

Please clarify your intent because simply caching a header for a CSS file will not fulfill your needs.

I hope the short term solution will get you over the speed bump while we take a longer look at a problem with more depth that perhaps you imagined at first.


[quote author="Aquillyne" date="1216701072"]Currently you may have a page styles/css sent with header "text/css".[/quote]

That implies a controller "Styles" with method "css". If you are going to go the route of writing a controller/method for each mime-type you attach to a given URI, I wouldn't consider that DRY enough for my tastes. Remember, your main requesting routes will run through the controllers that send HTML. From within that HTML, you will be making calls to a CSS URI and a JS URI with "link" tags and "script" tags. That's two more controllers that you will have to write to effectively accomplish one request. It just gets worse from there if you want to create RSS feeds or apply XSLT.

Simply recognizing the suffix will give you enough flexibility to extend CI's rendering abilities while still based around a common URI.

[eluser]Randy Casburn[/eluser]
@beemr -- that's the implication then -

a JS controller/method = cached content

a CSS controller/method = cached content

an HTML controller/method = cached content

an XSLT controller/method = cached content


got it... understand.


But I still only want to deal with one URI.

My router catches (.*)\.(css|js|xsl){1} and returns assets/$2/$1.

That's where my Assets controller gets passed the URI as rsegments and loads the view from view subfolders that mirror the URI structure.

[eluser]Randy Casburn[/eluser]
I'm still interested in hearing from the OP about the use case for caching the CSS and not just the header. In other words, the Paul Harvey part...the Rrrest of the story...


[quote author="Randy Casburn" date="1216705596"]First, the short term fix:[/quote]

A good fix for the meantime, although far from desirable.

[quote author="Randy Casburn" date="1216705596"]If "you want the CSS cached" you MUST load the remainder of the style information into an appropriate storage location for the CSS to be cached along with the header.[/quote]

I'm not sure what you're getting at. Let's say I have a controller "styles/css", containing:

$data["body"] = array("background" => "white");

$this->load->view("styles/css_file", $data)

The view simply converts that $data into a CSS document, e.g.:

body {
background: white

The view also - as it must - has a first line:

$this->output->set_header("Content-Type: text/css");

This completes the use scenario. My XHTML links to the styles controller like so:

<link rel="stylesheet" href="styles/css" type="text/css" media="all" />

So when the page loads, the browser loads the CSS via the CSS controller, which outputs CSS specified in the controller and tidied into a document by the view. And crucially, either the CSS controller or view outputs the CSS header - or the browser will interpret the link as plain text and not render the CSS.

So now I've got controller-delivered CSS, which has a host of uses I needn't go into. However, as that CSS might go through long period where it isn't changed, I'd like to cache it. So in the CSS controller I insert the line:


This now means that everything output by the controller and the view, i.e.

body {
background: white

is cached and that cache is served directly next time, rather than the controller running at all.

But there's the problem - because the cache skips the controller, that CSS file is delivered on subsequent loads without the "text/css" header, meaning on subsequent loads there is no CSS rendering.

There are of course more solutions to this than caching headers, but actually if you think about it it's the best one. Here are three basic reasons:

1. Headers are attached to documents. That's what they're for. They're meta-data, but they aren't separate. If a user has elected to use $this->output->set_header() then he's clearly wanted a header to be sent with his document. And he clearly wants it every time that document is delivered, too. (But if he doesn't, using header() will bypass header-caching under my proposed changes).

2. The CI code comments actually say "Darn, we need to figure out how to cache headers."

3. It's the most intuitive behaviour. I found it stunning that using the integrated function from the Output class didn't include my headers sent with the same class. It seemed all too obvious. Why not? As an original respondant wrote:

[quote author="Seppo" date="1215792983"]I believe that if you send the header trhough the output class ($this->output->set_header) it will also be cached and delivered the next time... but I hadn't use it, so I'm not sre[/quote]

I hope that explains a usage scenario for you. But obviously there are a host more than just for dynamically generated CSS.

And I will point out again that I'm not trying to do anything extra-funky here, I'm not changing the way the cache works and nor am I trying to cache things in a strange way. Nor am I creating any new errors (e.g. the suffix error is nothing to do with this; that's already a problem in CI addressed separately by the Suffix cache extension).

I'm just caching a file that needs its headers, but loses them in the cache. I'm trying to put them together again.

[quote author="beemr" date="1216706571"]Simply recognizing the suffix will give you enough flexibility to extend CI's rendering abilities while still based around a common URI.[/quote]

People have continually associated this thread with suffixes and the Suffix cache extension, because of its clear usage in pages of different mime-types.

Wrong association.

Recognising the suffix won't fix my problem. Mine isn't a problem about mime-types, it's about headers. (Which send mime-types. But the difference, as you will appreciate, is huge).

If the suffix is recognised then I can get a separate cache for foo.css and foo.js. Fantastic. But still, neither of them, when the cache is delivered, will be accompanied by their respective "text/css" and "text/javascript" headers. That's the issue I'm trying to address. Regardless of how the cache grabs the URI, subsequent returns of the cache don't also return the appropriate headers.

Theme © iAndrew 2016 - Forum software by © MyBB