aboutsummaryrefslogtreecommitdiffstats
path: root/guide/static_handlers.md
diff options
context:
space:
mode:
authorLoïc Hoguin <[email protected]>2013-11-02 14:41:46 +0100
committerLoïc Hoguin <[email protected]>2013-11-02 14:41:46 +0100
commit6672ea04155a075e60381413bf9b65b3974b7d57 (patch)
tree8b708354f28335cb8f89fdf222dff0fc676ce22a /guide/static_handlers.md
parentfaf64524c6758ae1e27404d2ae1383a23538c538 (diff)
downloadcowboy-6672ea04155a075e60381413bf9b65b3974b7d57.tar.gz
cowboy-6672ea04155a075e60381413bf9b65b3974b7d57.tar.bz2
cowboy-6672ea04155a075e60381413bf9b65b3974b7d57.zip
Review, improve and document the static files handler
Changes include: * Much simplified route configuration. * Etag generation is now enabled by default. * Web mimetypes are now detected by default. A bigger list of mimetypes can be detected without any additional library. * Mimetypes can no longer be specified as a list. Copying this list for new connections is too costy. You can easily convert it into a function and pass that function to the handler instead. * You can however specify a single hardcoded mimetype. Mostly useful when serving a single file, like an index.html file, to avoid extra operations. * Specifying a path as a list of tokens is not possible anymore. Use either a binary or a string. * Using a private directory will not work if the application was not started properly. Cowboy will not attempt to find the location of this directory if the VM doesn't know it, as this caused issues in some setups. * Overall the code has been much simplified and clarified, and of course has now been documented.
Diffstat (limited to 'guide/static_handlers.md')
-rw-r--r--guide/static_handlers.md202
1 files changed, 156 insertions, 46 deletions
diff --git a/guide/static_handlers.md b/guide/static_handlers.md
index d6347f0..4e0bcfc 100644
--- a/guide/static_handlers.md
+++ b/guide/static_handlers.md
@@ -1,62 +1,172 @@
-Static handlers
-===============
+Static handler
+==============
-Purpose
--------
+The static handler is a built-in REST handler for serving files.
+It is available as a convenience and provides a quick solution
+for serving files during development.
-Static handlers are a built-in REST handler for serving files. They
-are available as a convenience and provide fast file serving with
-proper cache handling.
+For systems in production, consider using one of the many
+Content Distribution Network (CDN) available on the market,
+as they are the best solution for serving files. They are
+covered in the next chapter. If you decide against using a
+CDN solution, then please look at the chapter after that,
+as it explains how to efficiently serve static files on
+your own.
-It is recommended to use a Content Distribution Network (CDN) or at
-least a dedicated file server running on a dedicated cookie-less
-hostname for serving your application's static files in production.
+The static handler can serve either one file or all files
+from a given directory. It can also send etag headers for
+client-side caching.
-Usage
------
+To use the static file handler, simply add routes for it
+with the appropriate options.
-Static handlers are pre-written REST handlers. They only need
-to be specified in the routing information with the proper options.
+Serve one file
+--------------
-The following example routing serves all files found in the
-`priv_dir/static/` directory of the application `my_app`.
+You can use the static handler to serve one specific file
+from an application's private directory. This is particularly
+useful to serve an `index.html` file when the client requests
+the `/` path, for example. The path configured is relative
+to the given application's private directory.
+
+The following rule will serve the file `static/index.html`
+from the application `my_app`'s priv directory whenever the
+path `/` is accessed.
+
+``` erlang
+{"/", cowboy_static, {priv_file, my_app, "static/index.html"}}
+```
+
+You can also specify the absolute path to a file, or the
+path to the file relative to the current directory.
+
+``` erlang
+{"/", cowboy_static, {file, "/var/www/index.html"}}
+```
+
+Serve all files from a directory
+--------------------------------
+
+You can also use the static handler to serve all files that
+can be found in the configured directory. The handler will
+use the `path_info` information to resolve the file location,
+which means that your route must end with a `[...]` pattern
+for it to work. All files are served, including the ones that
+may be found in subfolders.
+
+You can specify the directory relative to an application's
+private directory.
+
+The following rule will serve any file found in the application
+`my_app`'s priv directory inside the `static/assets` folder
+whenever the requested path begins with `/assets/`.
``` erlang
-Dispatch = [
- {'_', [
- {"/[...]", cowboy_static, [
- {directory, {priv_dir, my_app, [<<"static">>]}},
- {mimetypes, {fun mimetypes:path_to_mimes/2, default}}
- ]}
- ]}
-].
+{"/assets/[...]", cowboy_static, {priv_dir, my_app, "static/assets"}}
```
-You can also serve a single file specifically. A common example
-would be an `index.html` file to be served when the path `/`
-is requested. The following example will serve the `priv/index.html`
-file from the application `my_app`.
+You can also specify the absolute path to the directory or
+set it relative to the current directory.
``` erlang
-Dispatch = [
- {'_', [
- {"/", cowboy_static, [
- {directory, {priv_dir, my_app, []}},
- {file, "index.html"},
- {mimetypes, {fun mimetypes:path_to_mimes/2, default}}
- ]}
- ]}
-].
+{"/assets/[...]", cowboy_static, {dir, "/var/www/assets"}}
```
-MIME type
----------
+Customize the mimetype detection
+--------------------------------
+
+By default, Cowboy will attempt to recognize the mimetype
+of your static files by looking at the extension.
+
+You can override the function that figures out the mimetype
+of the static files. It can be useful when Cowboy is missing
+a mimetype you need to handle, or when you want to reduce
+the list to make lookups faster. You can also give a
+hard-coded mimetype that will be used unconditionally.
-Cowboy does not provide any default for MIME types. This means
-that unless you specify the `mimetypes` option, all files will
-be sent as `application/octet-stream`, which the browser will
-not try to interpret, instead trying to make you download it.
+Cowboy comes with two functions built-in. The default
+function only handles common file types used when building
+Web applications. The other function is an extensive list
+of hundreds of mimetypes that should cover almost any need
+you may have. You can of course create your own function.
-In the examples above we used the
-[mimetypes application](https://github.com/spawngrid/mimetypes)
-to find the MIME type from the file's extension.
+To use the default function, you should not have to configure
+anything, as it is the default. If you insist, though, the
+following will do the job.
+
+``` erlang
+{"/assets/[...]", cowboy_static, {priv_dir, my_app, "static/assets",
+ [{mimetypes, cow_mimetypes, web}]}}
+```
+
+As you can see, there is an optional field that may contain
+a list of less used options, like mimetypes or etag. All option
+types have this optional field.
+
+To use the function that will detect almost any mimetype,
+the following configuration will do.
+
+``` erlang
+{"/assets/[...]", cowboy_static, {priv_dir, my_app, "static/assets",
+ [{mimetypes, cow_mimetypes, all}]}}
+```
+
+You probably noticed the pattern by now. The configuration
+expects a module and a function name, so you can use any
+of your own functions instead.
+
+``` erlang
+{"/assets/[...]", cowboy_static, {priv_dir, my_app, "static/assets",
+ [{mimetypes, Module, Function}]}}
+```
+
+The function that performs the mimetype detection receives
+a single argument that is the path to the file on disk. It
+is recommended to return the mimetype in tuple form, although
+a binary string is also allowed (but will require extra
+processing). If the function can't figure out the mimetype,
+then it should return `{<<"application">>, <<"octet-stream">>, []}`.
+
+When the static handler fails to find the extension in the
+list, it will send the file as `application/octet-stream`.
+A browser receiving such file will attempt to download it
+directly to disk.
+
+Finally, the mimetype can be hard-coded for all files.
+This is especially useful in combination with the `file`
+and `priv_file` options as it avoids needless computation.
+
+``` erlang
+{"/", cowboy_static, {priv_file, my_app, "static/index.html",
+ [{mimetypes, {<<"text">>, <<"html">>, []}}]}}
+```
+
+Generate an etag
+----------------
+
+By default, the static handler will generate an etag header
+value based on the size and modified time. This solution
+can not be applied to all systems though. It would perform
+rather poorly over a cluster of nodes, for example, as the
+file metadata will vary from server to server, giving a
+different etag on each server.
+
+You can however change the way the etag is calculated.
+
+``` erlang
+{"/assets/[...]", cowboy_static, {priv_dir, my_app, "static/assets",
+ [{etag, Module, Function}]}}
+```
+
+This function will receive three arguments: the path to the
+file on disk, the size of the file and the last modification
+time. In a distributed setup, you would typically use the
+file path to retrieve an etag value that is identical across
+all your servers.
+
+You can also completely disable etag handling.
+
+``` erlang
+{"/assets/[...]", cowboy_static, {priv_dir, my_app, "static/assets",
+ [{etag, false}]}}
+```