Content-Disposition - Forced file downloads via HTTP

One of the many things that makes iRules so powerful is the amazing amount of flexibility that it gives you with which you can manage the user experience of your application, improve security, performance and reliability, and much more. This fine grained amount of control ensures that you are able to look out for the best interest of those accessing your application and see to it that they are getting the very best experience they can. It also gives you the control to customize that experience at times if it could lead to increased performance or security, if you see fit.

There are many times that you may want to change the "normal" behavior that a user will experience when accessing your application. Perhaps you require a custom login sequence or certain options to be enabled/disabled in a browser. In the example below we look at a case where there are files being served that the browser will often try to interpret itself, such as PDF files or even Microsoft Office files if you have that software installed. Whether it's because the data being transferred is sensitive, you want to perform on-disk virus checking, or you just want to avoid forcing file re-naming while allowing downloads of files that would otherwise be browser interpreted, there are times that you'll want to change this behavior.

Lucky for you there is a common header that allows us to specify the action to be taken by the client when receiving a file. This is the Content-Disposition header which, while not technically part of the HTTP standard, is often implemented to allow us to achieve the behavior outlined above. By inspecting and defining the value of this header we are able to decide whether a file will be viewed "in-line" or as an attachment.

The below example compares the file extension of the incoming HTTP request to a class of known file extension that we want to force the user to download. In this case we're assuming that we want to force them to download executables, pdf files and vb scripts, just a few of the possible candidates in many deployments today. Once we identify that there is indeed a file being requested that we want to ensure is downloaded, not rendered in the browser, we then set a variable to let the HTTP Response event's logic fire when that event is called. This is where we check to see if the Content-Disposition header exists. If so, we simply replace it with our own, custom string signifying that this file should be treated as an attachment.

Now when the user gets this response, their browser will automatically attempt to download the file, rather than displaying it real-time, ensuring that the sensitive data inside isn't displayed, or a more in-depth virus check can be completed, or whatever other action you desire can be taken.

class dlFiles {
  ".exe"
  ".pdf"
  ".vb"
}

when HTTP_REQUEST {
  # Compare the file extension to the list you wish to force downloads for
  if { [matchclass [string tolower [HTTP::uri]] ends_with $::dlFiles] } {
    set forceDownload 1
  }
}
 
when HTTP_RESPONSE {  
  if { $forceDownload == 1 } {
    # Check if the response has a Content-Disposition header  
    if {[HTTP::header exists Content-Disposition]}{  
      # Replace the existing Content-Disposition header  
      # with one that prompts the user to download the content  
      HTTP::header replace Content-Disposition "attachment; filename="  
    }
    set forceDownload 0  
  }
}
Published Jun 09, 2008
Version 1.0

Was this article helpful?

No CommentsBe the first to comment