# Type{} directive

**URL:** <https://www.ruby-forum.com/t/type-directive/193485>\
**Category:** NGINX\
**Created:** [August 18, 2010, 4:20pm UTC](https://www.ruby-forum.com/t/type-directive/193485 "2010-08-18T16:20:08Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![gnosek](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/edb3f5/32.png) [@gnosek](https://www.ruby-forum.com/u/gnosek)\
**Post date:** [August 18, 2010, 4:20pm UTC](https://www.ruby-forum.com/t/type-directive/193485/1 "2010-08-18T16:20:08Z")

</div>

Hi all,

After a recent discussion I decided to whip up a patch implementing the  
type {} directive to route requests according to MIME types of requested  
files.

The main advantage is a clearer config file, as instead of:

| location ~ .(gif|png|jpe?g|tif|ico) {  
| expires max;  
| access\_log off;  
| }

you can now say:

| type image/\* {  
| expires max;  
| access\_log off;  
| }

(foo/\* is the only wildcard type available right now, so e.g. text/_ml  
or application/vnd._ won’t work).

A particularly nice aspect of this is that type{}s are looked up  
independently from location{}s, so the config below sets “expires max”  
both on /foo.txt and on /foo/foo.txt:

| location / {  
| allow all;  
| }  
|  
| location /foo {  
| allow 127.0.0.1;  
| deny all;  
| }  
|  
| type text/plain {  
| expires max;  
| }

The catch is that it only works on static files, as processed by the  
ngx\_http\_static\_module, not on e.g. proxied responses (sorry Mike!)

There’s another use case, but Igor said he doesn’t like it, so pretend  
you haven’t seen it 😉

| types {  
| application/x-httpd-php php;  
| }  
|  
| location / {  
| # all the usual stuff  
| }  
|  
| type application/x-httpd-php {  
| fastcgi\_pass … # etc.  
| }

The above config (inside a server{} block, of course) pushes all .php  
files via FastCGI (to php-fpm or something). This happens very late in  
the request processing stage, just before the raw php file would have  
been served to the client.

The patch is based on 0.8.49. I’m sure it has flaws but all comments are  
gladly accepted (both for high-level feature discussion and low-level  
code review).

Best regards,  
Grzegorz N.

* * *

src/http/modules/ngx\_http\_static\_module.c | 30 ++±  
src/http/ngx\_http\_core\_module.c | 351  
+++++++++++++++++++++++++±–  
src/http/ngx\_http\_core\_module.h | 10 +  
3 files changed, 363 insertions(+), 28 deletions(-)

diff --git a/src/http/modules/ngx\_http\_static\_module.c  
b/src/http/modules/ngx\_http\_static\_module.c  
index 57b5130…b30ce8b 100644  
— a/src/http/modules/ngx\_http\_static\_module.c  
+++ b/src/http/modules/ngx\_http\_static\_module.c  
@@ -49,14 +49,15 @@ ngx\_http\_static\_handler(ngx\_http\_request\_t \*r)  
{  
u\_char \*last, \*location;  
size\_t root, len;

- ngx\_str\_t path;

- ngx\_str\_t path, content\_type;  
ngx\_int\_t rc;  
ngx\_uint\_t level;  
ngx\_log\_t \*log;  
ngx\_buf\_t \*b;  
ngx\_chain\_t out;  
ngx\_open\_file\_info\_t of;

- ngx\_http\_core\_loc\_conf\_t \*clcf;

- ngx\_http\_core\_loc\_conf\_t \*clcf, \*sclcf, \*type\_clcf;

- ngx\_http\_core\_srv\_conf\_t \*cscf;

#endif

- content\_type.data = NULL;
- content\_type.len = 0;
- if (!clcf-\>type\_loc) {
- 

```
   /*

```

- 

```
    * try to find a type { } block matching the content type

```

- 

```
    * as determined by file extension

```

- 

```
    */

```

- 

```
   rc = ngx_http_find_content_type(r, &content_type);

```

- 

```
   if (rc == NGX_OK && content_type.data) {

```

- 

```
       /* look in type { } blocks in location { } */

```

- 

```
       type_clcf = ngx_http_core_find_type_location(clcf, 

```

&content\_type, 0);

- 

```
       if (type_clcf) {

```

- 

```
           return ngx_http_use_location(r, type_clcf);

```

- 

```
       }

```

- 
- 

```
       /* look in type { } blocks in server { } */

```

- 

```
       cscf = r->srv_conf[ngx_http_core_module.ctx_index];

```

- 

```
       sclcf = 

```

cscf-\>ctx-\>loc\_conf[ngx\_http\_core\_module.ctx\_index];

- 

```
       type_clcf = ngx_http_core_find_type_location(sclcf, 

```

&content\_type, 0);

- 

```
       if (type_clcf) {

```

- 

```
           return ngx_http_use_location(r, type_clcf);

```

- 

```
       }

```

- 

```
   }

```

- }
- if (r-\>method & NGX\_HTTP\_POST) {  
return NGX\_HTTP\_NOT\_ALLOWED;  
}  
diff --git a/src/http/ngx\_http\_core\_module.c  
b/src/http/ngx\_http\_core\_module.c  
index 6a11a87…9fb54fb 100644  
— a/src/http/ngx\_http\_core\_module.c  
+++ b/src/http/ngx\_http\_core\_module.c  
@@ -15,6 +15,13 @@ typedef struct {  
} ngx\_http\_method\_name\_t;

+#define DEFAULT\_NUM\_TYPES 4  
+typedef struct {

- ngx\_str\_t mime\_type;
- ngx\_http\_core\_loc\_conf\_t \*clcf;  
+} ngx\_http\_type\_conf\_t;
- 
- 

#define NGX\_HTTP\_REQUEST\_BODY\_FILE\_OFF 0  
#define NGX\_HTTP\_REQUEST\_BODY\_FILE\_ON 1  
#define NGX\_HTTP\_REQUEST\_BODY\_FILE\_CLEAN 2  
@@ -77,6 +84,9 @@ static char \*ngx\_http\_gzip\_disable(ngx\_conf\_t \*cf,  
ngx\_command\_t \*cmd,  
static char \*ngx\_http\_core\_lowat\_check(ngx\_conf\_t \*cf, void \*post, void  
\*data);  
static char \*ngx\_http\_core\_pool\_size(ngx\_conf\_t \*cf, void \*post, void  
\*data);

+static char \*ngx\_http\_type(ngx\_conf\_t \*cf, ngx\_command\_t \*cmd,

- void \*conf);
- 

static ngx\_conf\_post\_t ngx\_http\_core\_lowat\_post =  
{ ngx\_http\_core\_lowat\_check };

@@ -724,6 +734,13 @@ static ngx\_command\_t ngx\_http\_core\_commands[] = {

#endif

- { ngx\_string(“type”),
- 

NGX\_HTTP\_SRV\_CONF|NGX\_HTTP\_LOC\_CONF|NGX\_CONF\_BLOCK|NGX\_CONF\_TAKE1,

- 

```
 ngx_http_type,

```

- 

```
 NGX_HTTP_LOC_CONF_OFFSET,

```

- 

```
 0,

```

- 

```
 NULL },

```

- 

```
 ngx_null_command

```

};

@@ -1657,17 +1674,13 @@ ngx\_http\_test\_content\_type(ngx\_http\_request\_t  
\*r, ngx\_hash\_t \*types\_hash)

ngx\_int\_t  
-ngx\_http\_set\_content\_type(ngx\_http\_request\_t \*r)  
+ngx\_http\_find\_content\_type(ngx\_http\_request\_t \*r, ngx\_str\_t \*typeptr)  
{  
u\_char c, \*exten;  
ngx\_str\_t \*type;  
ngx\_uint\_t i, hash;  
ngx\_http\_core\_loc\_conf\_t \*clcf;

- if (r-\>headers\_out.content\_type.len) {

- 

```
   return NGX_OK;

```

- }

- clcf = ngx\_http\_get\_module\_loc\_conf(r, ngx\_http\_core\_module);

- 

```
       r->headers_out.content_type_len = type->len;

```

- 

```
       r->headers_out.content_type = *type;

```

- 

```
       *typeptr = *type;

       return NGX_OK;
   }

```

}

- r-\>headers\_out.content\_type\_len = clcf-\>default\_type.len;
- r-\>headers\_out.content\_type = clcf-\>default\_type;

- \*typeptr = clcf-\>default\_type;
- 
- return NGX\_OK;  
+}
- 
- 

+ngx\_int\_t  
+ngx\_http\_set\_content\_type(ngx\_http\_request\_t \*r)  
+{

- ngx\_str\_t content\_type;

- ngx\_int\_t rv;

- 
- if (r-\>headers\_out.content\_type.len) {

- 

```
   return NGX_OK;

```

- }

- 
- rv = ngx\_http\_find\_content\_type(r, &content\_type);

- 
- if (rv != NGX\_OK)

- 

```
   return rv;

```

- 
- r-\>headers\_out.content\_type\_len = content\_type.len;

- r-\>headers\_out.content\_type = content\_type;

-ngx\_int\_t  
-ngx\_http\_named\_location(ngx\_http\_request\_t \*r, ngx\_str\_t \*name)  
+ngx\_http\_core\_loc\_conf\_t \*  
+ngx\_http\_find\_named\_location(ngx\_http\_request\_t \*r, ngx\_str\_t \*name)  
{  
ngx\_http\_core\_srv\_conf\_t \*cscf;  
ngx\_http\_core\_loc\_conf\_t \*\*clcfp;

- ngx\_http\_core\_main\_conf\_t \*cmcf;

- 
- r-\>main-\>count++;

@@ -2356,24 +2386,48 @@ ngx\_http\_named\_location(ngx\_http\_request\_t \*r,  
ngx\_str\_t \*name)  
continue;  
}

- 

```
       ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,

```

- 

```
                      "using location: %V \"%V?%V\"",

```

- 

```
                      name, &r->uri, &r->args);

```

- 

```
       return *clcfp;

```

- 

```
   }

```

- }
- 
- return NULL;  
+}
- 

- 

```
       r->internal = 1;

```

- 

```
       r->content_handler = NULL;

```

- 

```
       r->loc_conf = (*clcfp)->loc_conf;

```

+ngx\_int\_t  
+ngx\_http\_use\_location(ngx\_http\_request\_t \*r, ngx\_http\_core\_loc\_conf\_t  
\*clcf)  
+{

- ngx\_http\_core\_main\_conf\_t \*cmcf;

- 

```
       ngx_http_update_location_config(r);

```

- r-\>main-\>count++;

- 

```
       cmcf = ngx_http_get_module_main_conf(r, 

```

ngx\_http\_core\_module);

- ngx\_log\_debug3(NGX\_LOG\_DEBUG\_HTTP, r-\>connection-\>log, 0,
- 

```
              "using location: %V \"%V?%V\"",

```

- 

```
              name, &r->uri, &r->args);

```

- 

```
       r->phase_handler = 

```

cmcf-\>phase\_engine.location\_rewrite\_index;

- r-\>internal = 1;
- r-\>content\_handler = NULL;
- r-\>loc\_conf = clcf-\>loc\_conf;

- 

```
       ngx_http_core_run_phases(r);

```

- ngx\_http\_update\_location\_config®;

- 

```
       return NGX_DONE;

```

- 

```
   }

```

- cmcf = ngx\_http\_get\_module\_main\_conf(r, ngx\_http\_core\_module);
- 
- r-\>phase\_handler = cmcf-\>phase\_engine.location\_rewrite\_index;
- 
- ngx\_http\_core\_run\_phases®;
- 
- return NGX\_DONE;  
+}
- 

+ngx\_int\_t  
+ngx\_http\_named\_location(ngx\_http\_request\_t \*r, ngx\_str\_t \*name)  
+{

- ngx\_http\_core\_loc\_conf\_t \*clcf;

- 
- clcf = ngx\_http\_find\_named\_location(r, name);

- if (clcf) {

- 

```
   return ngx_http_use_location(r, clcf);

```

}

ngx\_log\_error(NGX\_LOG\_ERR, r-\>connection-\>log, 0,  
@@ -3375,6 +3429,9 @@ ngx\_http\_core\_merge\_loc\_conf(ngx\_conf\_t \*cf, void  
\*parent, void \*child)

#endif

- ngx\_conf\_merge\_ptr\_value(conf-\>type\_locations,
- 

```
                         prev->type_locations, NULL);

```

- return NGX\_CONF\_OK;  
}

@@ -4479,3 +4536,245 @@ ngx\_http\_core\_pool\_size(ngx\_conf\_t \*cf, void  
\*post, void \*data)

```
 return NGX_CONF_OK;

```

}  
+  
+  
+static char \*  
+ngx\_http\_add\_type\_location(ngx\_conf\_t \*cf, ngx\_str\_t \*mime\_type,

- ngx\_http\_core\_loc\_conf\_t \*pclcf, ngx\_http\_core\_loc\_conf\_t \*clcf)  
+{
- ngx\_http\_type\_conf\_t \*tcf;
- 
- if (!pclcf-\>type\_locations) {
- 

```
   pclcf->type_locations = ngx_list_create(cf->pool, 

```

DEFAULT\_NUM\_TYPES,

- 

```
       sizeof(ngx_http_type_conf_t));

```

- 
- 

```
   if (!pclcf->type_locations) {

```

- 

```
       ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,

```

- 

```
                          "failed to allocate memory for mime type 

```

list");

- 

```
       return NGX_CONF_ERROR;

```

- 

```
   }

```

- }
- 
- tcf = ngx\_list\_push(pclcf-\>type\_locations);
- if (!tcf) {
- 

```
   ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,

```

- 

```
                      "failed to allocate memory for mime type 

```

data");

- 

```
   return NGX_CONF_ERROR;

```

- }
- 
- tcf-\>mime\_type = \*mime\_type;
- tcf-\>clcf = clcf;
- 
- return NGX\_CONF\_OK;  
+}
- 
- 

+static inline ngx\_int\_t  
+ngx\_str\_equal(ngx\_str\_t \*a, ngx\_str\_t \*b)  
+{

- if (a-\>len != b-\>len) {
- 

```
   return 0;

```

- }
- 
- return !ngx\_strncmp(a-\>data, b-\>data, a-\>len);  
+}
- 
- 

+static inline ngx\_int\_t  
+ngx\_mimetype\_equal(ngx\_str\_t \*a, ngx\_str\_t \*b)  
+{

- size\_t pos;
- const u\_char \*p;
- 
- p = memchr(a-\>data, ‘/’, a-\>len);
- if (!p)
- 

```
   return 0;

```

- 
- pos = p - a-\>data;
- 
- if (pos \>= b-\>len || pos == a-\>len || b-\>data[pos] != ‘/’) {
- 

```
   return 0;

```

- }
- 
- if ((char)a-\>data[pos + 1] == ‘\*’) {
- 

```
   return !memcmp(a->data, b->data, pos);

```

- }
- 
- return ngx\_str\_equal(a, b);  
+}
- 
- 

+static inline ngx\_int\_t  
+ngx\_is\_mimetype\_valid(ngx\_str\_t \*type)  
+{

- size\_t pos;
- const u\_char \*p;
- 
- p = memchr(type-\>data, ‘/’, type-\>len);
- if (!p) {
- 

```
   return 0;

```

- }
- pos = p - type-\>data;
- if (pos == 0 || pos == type-\>len - 1) {
- 

```
   return 0;

```

- }
- 
- if (pos == type-\>len - 2 && p[1] == ‘\*’) {
- 

```
   /* a lone asterisk is allowed after the slash... */

```

- 

```
   return 1;

```

- }
- 
- if (memchr(p+1, ‘/’, type-\>len - pos - 2) != NULL)
- 

```
   return 0;

```

- 
- /\* … but nowhere else \*/
- p = memchr(type-\>data, ‘\*’, type-\>len);
- return (p == NULL);  
+}
- 
- 

+ngx\_http\_core\_loc\_conf\_t \*  
+ngx\_http\_core\_find\_type\_location(ngx\_http\_core\_loc\_conf\_t \*pclcf,

- ngx\_str\_t \*mime\_type, ngx\_int\_t exact)  
+{
- ngx\_list\_part\_t \*part;
- ngx\_http\_type\_conf\_t \*data;
- ngx\_http\_core\_loc\_conf\_t \*clcf;
- ngx\_uint\_t i;
- 
- if (!pclcf-\>type\_locations) {
- 

```
   return NULL;

```

- }
- 
- part = &pclcf-\>type\_locations-\>part;
- data = part-\>elts;
- clcf = NULL;
- 
- for (i = 0 ;; i++) {
- 

```
   if (i >= part->nelts) {

```

- 

```
       if (part->next == NULL) {

```

- 

```
           break;

```

- 

```
       }

```

- 
- 

```
       part = part->next;

```

- 

```
       data = part->elts;

```

- 

```
       i = 0;

```

- 

```
   }

```

- 
- 

```
   if (exact) {

```

- 

```
       if (ngx_str_equal(&data[i].mime_type, mime_type)) {

```

- 

```
           clcf = data[i].clcf;

```

- 

```
           break;

```

- 

```
       }

```

- 

```
   } else {

```

- 

```
       if (ngx_mimetype_equal(&data[i].mime_type, mime_type)) {

```

- 

```
           clcf = data[i].clcf;

```

- 

```
           break;

```

- 

```
       }

```

- 

```
   }

```

- }
- 
- return clcf;  
+}
- 

+static char \*  
+ngx\_http\_type(ngx\_conf\_t \*cf, ngx\_command\_t \*cmd, void \*conf)  
+{

- void \*mconf;

- char \*rv;

- ngx\_str\_t \*value, mime\_type;

- ngx\_uint\_t i, ctx\_index;

- ngx\_conf\_t save;

- ngx\_http\_module\_t \*module;

- ngx\_http\_conf\_ctx\_t \*ctx, \*pctx;

- ngx\_http\_core\_loc\_conf\_t \*clcf, \*pclcf;

- 
- ctx = ngx\_pcalloc(cf-\>pool, sizeof(ngx\_http\_conf\_ctx\_t));

- if (ctx == NULL) {

- 

```
   return NGX_CONF_ERROR;

```

- }

- 
- value = cf-\>args-\>elts;

- mime\_type = value[1];

- 
- if (!ngx\_is\_mimetype\_valid(&mime\_type)) {

- 

```
   ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,

```

- 

```
                      "invalid mime type %V", &mime_type);

```

- 

```
   return NGX_CONF_ERROR;

```

- }

- 
- pctx = cf-\>ctx;

- pclcf = pctx-\>loc\_conf[ngx\_http\_core\_module.ctx\_index];

- 
- if (ngx\_http\_core\_find\_type\_location(pclcf, &mime\_type, 1)) {

- 

```
   ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,

```

- 

```
                      "duplicate mime type %V", &mime_type);

```

- 

```
   return NGX_CONF_ERROR;

```

- }

- 
- ctx-\>main\_conf = pctx-\>main\_conf;

- ctx-\>srv\_conf = pctx-\>srv\_conf;

- 
- ctx-\>loc\_conf = ngx\_pcalloc(cf-\>pool, sizeof(void \*) \*  
ngx\_http\_max\_module);

- if (ctx-\>loc\_conf == NULL) {

- 

```
   return NGX_CONF_ERROR;

```

- }

- 
- for (i = 0; ngx\_modules[i]; i++) {

- 

```
   if (ngx_modules[i]->type != NGX_HTTP_MODULE) {

```

- 

```
       continue;

```

- 

```
   }

```

- 
- 

```
   module = ngx_modules[i]->ctx;

```

- 
- 

```
   if (module->create_loc_conf) {

```

- 
- 

```
       mconf = module->create_loc_conf(cf);

```

- 

```
       if (mconf == NULL) {

```

- 

```
            return NGX_CONF_ERROR;

```

- 

```
       }

```

- 
- 

```
       ctx->loc_conf[ngx_modules[i]->ctx_index] = mconf;

```

- 

```
   }

```

- }

- 
- clcf = ctx-\>loc\_conf[ngx\_http\_core\_module.ctx\_index];

- clcf-\>loc\_conf = ctx-\>loc\_conf;

- clcf-\>name = mime\_type;

- clcf-\>noname = 1;

- clcf-\>type\_loc = 1;

- 
- save = \*cf;

- cf-\>ctx = ctx;

- cf-\>cmd\_type = NGX\_HTTP\_LOC\_CONF;

- 
- rv = ngx\_conf\_parse(cf, NULL);

- 
- for (i = 0; ngx\_modules[i]; i++) {

- 

```
   if (ngx_modules[i]->type != NGX_HTTP_MODULE) {

```

- 

```
       continue;

```

- 

```
   }

```

- 
- 

```
   module = ngx_modules[i]->ctx;

```

- 

```
   ctx_index = ngx_modules[i]->ctx_index;

```

- 
- 

```
   if (module->merge_loc_conf) {

```

- 

```
       rv = module->merge_loc_conf(cf,

```

- 

```
                   pctx->loc_conf[ctx_index],

```

- 

```
                   ctx->loc_conf[ctx_index]);

```

- 

```
       if (rv != NGX_CONF_OK) {

```

- 

```
            break;

```

- 

```
       }

```

- 

```
   }

```

- }

- 
- \*cf = save;

- 
- if (rv != NGX\_CONF\_OK) {

- 

```
   return rv;

```

- }

- 
- rv = ngx\_http\_add\_type\_location(cf, &mime\_type, pclcf, clcf);

- 
- return rv;  
+}  
diff --git a/src/http/ngx\_http\_core\_module.h  
b/src/http/ngx\_http\_core\_module.h  
index f163e9a…982db27 100644  
— a/src/http/ngx\_http\_core\_module.h  
+++ b/src/http/ngx\_http\_core\_module.h  
@@ -288,6 +288,7 @@ struct ngx\_http\_core\_loc\_conf\_s {  
unsigned noname:1; /\* “if () {}” block or limit\_except \*/  
unsigned lmt\_excpt:1;  
unsigned named:1;

- unsigned type\_loc:1;

- ngx\_list\_t \*type\_locations;

#if 0  
ngx\_http\_core\_loc\_conf\_t \*prev\_location;  
@@ -450,6 +452,7 @@ ngx\_int\_t  
ngx\_http\_core\_content\_phase(ngx\_http\_request\_t \*r,

void \*ngx\_http\_test\_content\_type(ngx\_http\_request\_t \*r, ngx\_hash\_t  
\*types\_hash);  
+ngx\_int\_t ngx\_http\_find\_content\_type(ngx\_http\_request\_t \*r, ngx\_str\_t  
\*typeptr);  
ngx\_int\_t ngx\_http\_set\_content\_type(ngx\_http\_request\_t \*r);  
void ngx\_http\_set\_exten(ngx\_http\_request\_t \*r);  
ngx\_int\_t ngx\_http\_send\_response(ngx\_http\_request\_t \*r, ngx\_uint\_t  
status,  
@@ -467,6 +470,10 @@ ngx\_int\_t ngx\_http\_subrequest(ngx\_http\_request\_t  
\*r,  
ngx\_http\_post\_subrequest\_t \*psr, ngx\_uint\_t flags);  
ngx\_int\_t ngx\_http\_internal\_redirect(ngx\_http\_request\_t \*r,  
ngx\_str\_t \*uri, ngx\_str\_t \*args);  
+ngx\_http\_core\_loc\_conf\_t  
\*ngx\_http\_find\_named\_location(ngx\_http\_request\_t \*r,

- ngx\_str\_t \*name);  
+ngx\_int\_t ngx\_http\_use\_location(ngx\_http\_request\_t \*r,
- ngx\_http\_core\_loc\_conf\_t \*clcf);  
ngx\_int\_t ngx\_http\_named\_location(ngx\_http\_request\_t \*r, ngx\_str\_t  
\*name);

@@ -482,6 +489,9 @@ ngx\_int\_t ngx\_http\_output\_filter(ngx\_http\_request\_t  
\*r, ngx\_chain\_t \*chain);  
ngx\_int\_t ngx\_http\_write\_filter(ngx\_http\_request\_t \*r, ngx\_chain\_t  
\*chain);

+ngx\_http\_core\_loc\_conf\_t \*ngx\_http\_core\_find\_type\_location(

- ngx\_http\_core\_loc\_conf\_t \*pclcf, ngx\_str\_t \*mime\_type, ngx\_int\_t  
exact);
- 

extern ngx\_module\_t ngx\_http\_core\_module;

## extern ngx\_uint\_t ngx\_http\_max\_module;

1.6.2.4

---

<div class="post-metadata">

**Author:** ![gnosek](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/edb3f5/32.png) [@gnosek](https://www.ruby-forum.com/u/gnosek)\
**Post date:** [August 18, 2010, 4:52pm UTC](https://www.ruby-forum.com/t/type-directive/193485/2 "2010-08-18T16:52:20Z")

</div>

On Wed, Aug 18, 2010 at 04:19:08PM +0200, Grzegorz N. wrote:

> | access\_log off;  
> | }
> 
> you can now say:
> 
> | type image/\* {  
> | expires max;  
> | access\_log off;  
> | }

I forgot to say that the type{} directive works inside location{} blocks  
too:

| location /dev/ {  
| root /www/dev;  
|  
| type text/\* {  
| expires epoch;  
| }  
| }  
|  
| location /prod/ {  
| root /www/prod;  
|  
| type text/\* {  
| expires max;  
| }  
| }

Although if you put a text{} block inside a location{}, this location no  
longer interprets e.g. server{}-level types. We’ll see if this is a  
problem by popular demand 🙂

Best regards,  
Grzegorz N.
