Main  /  Edit  /  History  /   /  Users Area

Serving Static Files

Introduction

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 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 | Top | CppCMS Template System


External link: CPPCMS API Reference

About

CppCMS is a web development framework for performance demanding applications.

Support This Project

SourceForge.net Logo

Поддержать проект

CppCMS needs You


Navigation

Main Page



Valid CSS | Valid XHTML 1.0