picocms / Pico

Pico is a stupidly simple, blazing fast, flat file CMS.
http://picocms.org/
MIT License
3.85k stars 615 forks source link

Add support for serving static files from content folder #368

Closed mpavelka closed 8 years ago

mpavelka commented 8 years ago

Blog posts usually contain images. Adding this code makes it convenient for bloggers to include them in Pico content. In a content/content-subfolder/post.md file add pictures like this:

![My image](my_image.jpg)

or like this without mod rewrite enabled

![My image](?content-subfolder/my_image.jpg)
PhrozenByte commented 8 years ago

First of all, thank you for your PR and making Pico even better @mpavelka! :+1:

Unfortunately I've to tell you that this is against Pico's recommended way of managing assets. Let me explain the reasons:

Passing static files (like images) through PHP is a highly unperformant solution. A user usually generates just a single dynamic/interpreted request per page impression (i.e. the actual page), plus a much higher number of static requests (e.g. stylesheets, images, JavaScript ...). A dynamic/interpreted request causes an order of magnitude higher performance impact on your server than a static request and is - by far! - the most important limiting factor of how many concurrent requests your webserver can handle.

By serving just one image through PHP, a single page impression results in two dynamic/interpreted requests. Serving just two or three images are then very likely sufficient to cause the same performance impact as two "normal" page impressions. This bisects the number of concurrent requests your webserver can handle!

Therefore passing static file requests through PHP is no option. However, I agree that users want to store their assets together with their contents. Nevertheless, we deny access to the content/ folder for security reasons. This protection actually isn't necessary for a vanilla Pico installation because it serves all contents of the content/ folder anyway, however, plugins may restrict access to certain pages. As this may cause hidden security issues for users who want to use such plugins, we deny access to the content/ folder by default ("security by default").

This unfortunately leads to a conflict of aims between convenience and security. The obvious solution is to still deny access by default, but allow access to certain files (e.g. by matching MIME types). However, configuring your webserver to do so is (besides its still not negligible performance impact) a pretty complex topic and varies from webserver to webserver. I think that this is a topic for very advanced users only.

Thus we recommend to create a distinct assets/ folder. This definitely is not a convenient solution, but - as far as I know - the only practicable.

Personally I recommend you to configure your webserver to behave as elucidated above. If you still want to pass asset files through PHP, I recommend you to create a plugin (simply hook into Pico's onRequestFile event). Again, thank you for contributing! :+1:

mpavelka commented 8 years ago

@PhrozenByte, thank you very much for the most exhaustive explanation to the topic, it makes a lot of sense. I'm sure I'm not the first one to wonder about this problem, perhaps it would help others too to include a little how-to with above described solution in docs/about page.

PhrozenByte commented 8 years ago

@mpavelka, you're welcome, I've added this to Pico's ToDo list to create a appropriate "advanced asset handling howto" :smiley:

@smcdougall, do you want to incorporate the above explanation into #359 (beginning with "Nevertheless, we deny access to the content/ folder for security reasons. […]")?

mayamcdougall commented 8 years ago

Sure. :+1:

I've made a note on #359 to come back here and reference your explanation.