<!--toc-->
|
|
## Introduction
|
|
For serving static files the web server it the best option, lighttpd, nginx or Apache would do much better job then you probably can.
|
For serving static files using a web server is the best option: lighttpd, nginx or Apache would do much better job than you probably can.
|
|
However, when you want to apply the same permission logic to the static files as used for other dynamic contents,
|
you can't use the web server directly.
|
|
When serving static files you should be aware of two very important factors:
|
|
|
1. Security
|
2. Performance
|
|
## Security
|
|
|
Let's start from the first. I assume you want to let user
|
to download certain files that you are controlling.
|
|
For url like
|
|
/some/files/[...] <- these are allowed
|
|
Things you should **never do:**
|
|
class my_server {
|
|
my_server(...)
|
{
|
dispatcher().assign("/some/files/(.*)",&my_server::serve_file,this,1)
|
}
|
void serve_file(std::string file_name)
|
{
|
|
std::ifstream f(("some_dir_name/" + file_name).c_str());
|
if(!f) {
|
response().status(404)
|
}
|
else {
|
response().content_type("application/octet-stream")
|
response().out() << f.rdbuf();
|
}
|
}
|
...
|
}
|
|
|
Because attacker can create path
|
|
/some/files/../../../etc/some_secret.txt
|
|
And read it... It would be **very bad**.
|
|
|
If you want to serve a file create a very strict **white** list of allowed names like:
|
|
|
/some/files/([a-z_0-9\.]+\.txt)
|
|
Or even better convert the name to sha1 or md5 representation and save files using names generated
|
from their hash.
|
|
For example:
|
|
name = some_dir_per_user + "/" + cppcms::util::md5hex(file_name) + ".dat";
|
|
std::ifstream f(name.c_str());
|
|
|
## Performance
|
|
For small files (several K or even MB)
|
|
response().out() << f.rdbuf();
|
|
Is fine and works very well.
|
|
For the big files it is better to use headers like X-Send-File that are
|
supported by lighttpd, apache and nginx.
|
|
<http://redmine.lighttpd.net/projects/1/wiki/X-LIGHTTPD-send-file>
|
|
So instead of calling
|
|
|
response().content_type("application/octet-stream")
|
response().out() << f.rdbuf();
|
|
You call:
|
|
response().content_type("application/octet-stream")
|
response().set_header("X-Lighttpd-Send-File",pysical_file_name);
|
|
|
This is specially critical for big files were the
|
server may for example save the entire FastCGI output
|
to temporary file and before serving it (Nginx) or
|
cache entire (huge) buffer in the memory (Lighttpd)
|
|
`X-SendFile` usually much more effective than
|
`X-SendFile` is usually much more effective than
|
serving files via FastCGI as it reduces the data transfer
|
over IPC and sometimes does not even copy file
|
data to the user space.
|
|
|
---
|
|
← [Designing High Performance Applications][prev]
|
| [Top](#maincontent)
|
| [CppCMS Template System][next_bis] →
|
|
---
|
|
External link: [CPPCMS API Reference][next]
|
|
[prev]: /wikipp/en/page/cppcms_1x_high_performance
|
[next]: /cppcms_ref/latest
|
[next_bis]: /wikipp/en/page/cppcms_1x_templates |
← [Designing High Performance Applications](http://cppcms.com/wikipp/en/page/cppcms_1x_high_performance)
|
[CPPCMS API Reference](http://cppcms.com/cppcms_ref/latest/)→
|
[Templates](http://cppcms.com/wikipp/en/page/cppcms_1x_templates)→ |
## Browse
|
|
[CppCMS 1.x.x - Stable][toc]
|
|
← [Designing High Performance Applications][prev]
|
[CppCMS Template System][next_bis] →
|
External link: [CPPCMS API Reference][next]
|
|
[toc]: /wikipp/en/page/cppcms_1x
|
[prev]: /wikipp/en/page/cppcms_1x_high_performance
|
[next]: /cppcms_ref/latest
|
[next_bis]: /wikipp/en/page/cppcms_1x_templates |