Re: [Cppcms-users] serving static files best practices
Brought to you by:
artyom-beilis
From: Artyom B. <art...@ya...> - 2012-03-07 09:29:20
|
> >Hi, > >Does cppcms provide any help serving static files? Any tutorial? For serving static files the web server it the best option... :-) > >I would like to use cppcms to serve static files so that I can >implement the same permission logic as dynamic contents. > Since it was asked more then once. -------------------------------- This is quite different. To handle this kind of situation 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 allows. Things you DO NOT EVER-EVER-EVER 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 cat 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 representation and save files using cryptographic hash. Like: 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) More then that X-SendFile usually much more effective as it allows to the web server not to transfer buffers to the memory. ---------------- Now, please be so kind and put this to the wiki under the tutorial section :-) Artyom Beilis. |