diff options
Diffstat (limited to 'guide')
-rw-r--r-- | guide/static_handlers.md | 202 | ||||
-rw-r--r-- | guide/toc.md | 3 |
2 files changed, 158 insertions, 47 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}]}} +``` diff --git a/guide/toc.md b/guide/toc.md index 315dfac..a0c9a8c 100644 --- a/guide/toc.md +++ b/guide/toc.md @@ -27,8 +27,9 @@ HTTP Static files ------------ - * [Static handlers](static_handlers.md) + * [Static handler](static_handlers.md) * Distributed CDN solutions + * Efficiently serving files REST ---- |