Setting media type headers on your Web site
On the Web, no one knows you're a dog
... unless you are served with the proper HTTP headers.
What makes a CSS stylesheet a CSS stylesheet, and not just a text file that happens to look a lot like CSS? What may sound like an abstract philosophical reflection on the ontological nature of Web resources, became a very practical issue around 2002, when one of the major Web Browsers was patched to take HTTP information seriously, and would ignore stylesheets unless they were properly served as such by the web servers.
To understand what happens, one needs to look into the process of delivering resources on the Web: whenever a resource is requested, and served, by a Web server, it isn't sent on its own: the server prepends a lot of important information in the HTTP Headers. That information can be about the size of the representation served, caching directives, character encoding. And, among the most important: the media type. This is where the server tells the client "please treat this as a jpeg image/css stylesheet/xml document". That information is authoritative, and if a server declares "this is text/plain", clients have to treat content as plain text, even if it happens to look like HTML, CSS, or a PNG image. Guessing against this information is considered a bad idea.
The importance of this information provided by the Content-Type
HTTP header means that one may sometimes want to set, or force, the served media type for a resource, or many. Let's look at a few techniques for a number of practical cases.
Static resources: set up a web server, leverage its defaults
Many resources on the web are "static", that is, they are equivalent to files sitting on, and served by the Web server.
For those, the most simple way to set up the media type served by the server is to use a recognized file extension. For instance, a file with extension .css will automatically be served as text/css
, files with extension .html and .xhtml will automatically trigger content-types text/html
and application/xhtml+xml
, etc.
Sometimes, however, one may want to force a specific mime type for a resource, regardless of what the static file is, or add a media type to the configuration of the Web server. For instance, we recommended in the Web Standards Do that one may want to server XHTML files as text/html
for public consumption (at least for as long as XML support in generic browser remains weak), but use the stricter parsing of application/xhtml+xml
for testing purposes. For such cases, each Web server has a different way of configuring the media types:
- the Apache web server has the
AddType
directive to set up a new recognized media type for a given file extension, and theForceType
directive to force the determined media type of a given resource. - Microsoft IIS server can also be configured to serve specific mime types. This technet note describes the procedure, and lists the known media types, and the file extensions that will trigger their recognition.
- this tutorial has info on Tomcat (among others).
Dynamic Scripting Languages
Not all Web resources are static, and a growing number of them are actually generated by "CGI" or dynamic scripting engines. Below are examples of setting the Content-Type
header with such languages.
- Perl programmers on the web are often familiar with the
print "Content-type: text/htmlnn";
statement. Object-oriented code can also use theHTTP::Headers
module to set this HTTP header and others. - PHP has a
header()
function for this purpose. - Python has
print "Content-Type: text/html"
. the WSGI module also hasstart_response()
. - for ASP and ASP.NET, use: Response.ContentType = "text/html" — If you're using C# in ASP.NET, just add a semicolon at the end of the statement. (Hat tip: Asbjørn Ulsberg)
If your favorite language is not listed, feel free to share your techniques in the comments below.
Trying to sign in via OpenID yields the following error: "Can't locate XML/Parser.pm in @INC". Anyway, I just wanted to share how to set the content type in ASP and ASP.NET:
Response.ContentType = "text/html"
If you're using C# in ASP.NET, just add a semicolon at the end of the statement. For a reference, http://msdn2.microsoft.com/en-us/library/system.web.httpresponse.contenttype.aspx will do.
Thank you Asbjørn, I am bumping your notes up into the article.
And apologies indeed for the issues with openid signup. I did fix the perl library issue you ran into, but the system remains flaky...
Now, when I sign in with OpenID, I'm just redirected back here like nothing happened. E.g. I don't look signed in and still have to use the "comment anonymously" option. Thanks for the bump, by the way.
I found several cases in the last few years where the content-type in the html doc did not override the content-type in the header.
This was with charset specifically.
@Anthony: this is because information carried by HTTP will always have precedence over information embedded in the document (with e.g <meta>)
@Antony: if you want to see how it is working and if you are using Apache for your own server, you can do this. In a .htaccess file, you can ask the server to not send any type information for the file foo.html
<Files foo.html>
ForceType None
</Files>
Then the meta will take over, because the http header information will be empty.