Upload validation HOWTO

In the introductory document I’ve mentioned that this module can be used to validate users’ uploads, and do it before the whole file is sent. I’ve also given good reasons why using Ticketed-Upload module might be better than other solutions. If you haven’t read it yet, I encourage you to do so – you will probably return more motivated to read this document.

I will also cover some other things here.

Validation logic will be written in PHP, though you can use any method, the only requirement is that it must be able to set HTTP headers.

Let’s configure an Nginx location to serve the tickets, and make it internal (I will skip typical configuration entries):

# Server will accept uploads up to 1GB
client_max_body_size 1G;

# We will allocate 1MB for the memory that will contain tickets and uploads’ statuses,
# if it is exceeded, an error will be returned (though you can easily track it in the error
# log and increase this value).

ticketed_upload uploadZoneName 1m;

# Ticket format.
ticket_format HelloWorld%server_id.%random.;

# Ticket will be encoded with Base64.
ticket_base64_encode on;

# Tickets will expire after 2 minutes.
ticket_timeout 2m;

# Length of the random part of ticket format.
ticket_random_len 4;

# Tickets will be signed with salted MD5.
ticket_md5 someSalt123;

location ^~ /ticketer {

# This location will serve tickets from this zone (see upload_progress a few lines above).
sell_tickets uploadZoneName;

# Server’s ID. If you are using this module for distributed upload farm,
# put server’s external hostname here (it will be served in JSON with the ticket).

ticket_server_id someServer;

# This is an internal location. It means that you can’t just fetch it by connecting
# to http://yourserver/ticketer



location ~ /upload.* {

# Uploads will finish in this location, so you should add something here to handle them
# (FastCGI pass would be okay, Nginx upload module works as well).

# Information about upload will bee kept in the memory for this period of time after it’s finished.
track_uploads uploadZoneName 30s;

# See ticket_server_id and upload_progress above.
ticket_server_id someServer;


Now we have this PHP script:

if ($_GET['pass'] == ‘flowerpower’) {

header(’X-Accel-Redirect: /ticketer’);

} else {

echo ‘Wrong password.’;


Nginx sees X-Accel-Redirect header in a special way. If Nginx finds it in a response that an backend app has generated, then it does an internal redirect to this location. It’s internal, so it might be /ticketer, and it will work – ticket will be generated.