diff --git a/README b/README deleted file mode 100644 index 05cddc2..0000000 --- a/README +++ /dev/null @@ -1,45 +0,0 @@ -Nginx HTTP Set Lang Module --------------------------- - -Description ------------ - - An Nginx module that provides a variety of ways for setting a variable denoting the - langauge that content should be returned in. - - -Methods for setting language variable -------------------------------------- - - - cookie - - URL arguments - - Accept-Language header - - geoip - - host - - referer - - POST variables (todo) - - -Usage ------ - - TODO - - -Installation ------------- - - ./configure --add-module=/path/to/ngx_devel_kit --add-module=/path/to/ngx_http_set_lang - - - -Copyright ---------- - - Marcus Clyne (c) 2010 - - -License -------- - - BSD diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..2717d59 --- /dev/null +++ b/README.rst @@ -0,0 +1,69 @@ +Nginx HTTP Set Lang Module +-------------------------- + +Description +----------- + + An Nginx module that provides a variety of ways for setting a variable denoting the + langauge that content should be returned in. + + +Methods for setting language variable +------------------------------------- + + - cookie + - URL arguments + - Accept-Language header + - geoip + - host + - referer + - POST variables (todo) + + +Usage +----- + +List the supported locales:: + + lang_list en nl fr; + +If you want to read from and write to cookies (``lang`` is the cookie name):: + + lang_cookie lang; + +To make a (top-level) domain map to a certain locale:: + + lang_host com en; + +And to read the language from the user and put it in a variable:: + + set_lang '$lang' accept_lang get post cookie geoip host referer default; + + +Working example:: + + lang_list en pt_BR; + lang_cookie lang; + set_lang '$lang' cookie accept_lang default; + +The example above uses accept-language to give you any supported language. +If no supported language is found than the ``$lang`` variable will be set to the first language in ``lang_list`` (i.e. ``en``). + + +Installation +------------ + + ./configure --add-module=/path/to/ngx_devel_kit --add-module=/path/to/ngx_http_set_lang + + + +Copyright +--------- + + - Marcus Clyne (c) 2010 + - Rick van Hattem (c) 2011 + +License +------- + + BSD diff --git a/ngx_http_set_lang_module.c b/ngx_http_set_lang_module.c index b39ad5c..64fa42a 100644 --- a/ngx_http_set_lang_module.c +++ b/ngx_http_set_lang_module.c @@ -1,4 +1,3 @@ - /* * Copyright (c) 2009 Marcus Clyne */ @@ -6,6 +5,11 @@ #include +#define MINUTE 60 +#define HOUR 60 * MINUTE +#define DAY 24 * MINUTE +#define YEAR 365 * DAY +#define COOKIE_PARAM_BUFFER 40 // TODO : add setting a variable that dictates the method - $set_lang_method @@ -24,6 +28,7 @@ static ngx_int_t ngx_http_set_lang_from_geoip (ngx_http_request_t *r, static ngx_int_t ngx_http_set_lang_from_host (ngx_http_request_t *r, ngx_http_set_lang_loc_conf_t *conf, ngx_str_t *v); static ngx_int_t ngx_http_set_lang_from_referer (ngx_http_request_t *r, ngx_http_set_lang_loc_conf_t *conf, ngx_str_t *v); static ngx_int_t ngx_http_set_lang_from_var (ngx_http_request_t *r, ngx_http_set_lang_loc_conf_t *conf, ngx_str_t *v); +static ngx_int_t ngx_http_set_lang_from_default (ngx_http_request_t *r, ngx_http_set_lang_loc_conf_t *conf, ngx_str_t *v); static char * ngx_http_set_lang (ngx_conf_t *cf, ngx_command_t *cmd, void *cnf); static ngx_int_t ngx_http_set_lang_from_methods (ngx_http_request_t *r, ngx_str_t *v); @@ -79,6 +84,7 @@ static ngx_http_set_lang_method_t ngx_http_set_lang_methods [] = { {ngx_http_set_lang_from_geoip, ngx_string ("geoip")}, {ngx_http_set_lang_from_host, ngx_string ("host")}, {ngx_http_set_lang_from_referer, ngx_string ("referer")}, + {ngx_http_set_lang_from_default, ngx_string ("default")}, {NULL, ngx_null_string} }; @@ -197,6 +203,27 @@ ngx_http_set_lang_from_methods (ngx_http_request_t *r, ngx_str_t *v) ngx_http_variable_value_t *mv; ngx_http_set_lang_func_pt func; + // Generate the extra cookie params (path + expires) + static char cookie_params[COOKIE_PARAM_BUFFER]; + struct tm timestruct; + time_t now; + + // Fetch the current time + time(&now); + + // Default the expires date to 1 year in the future + now += YEAR; + + // Format the string as RFC 2616 specifies + gmtime_r(&now, ×truct); + + strftime( + cookie_params, + COOKIE_PARAM_BUFFER, + "; path=/; expires=%a, %d %b %Y %H:%M:%S GMT", + ×truct + ); + llcf = ngx_http_get_module_loc_conf (r, ngx_http_set_lang_module); if (!llcf->enable) @@ -224,7 +251,7 @@ ngx_http_set_lang_from_methods (ngx_http_request_t *r, ngx_str_t *v) // create lang cookie - len = llcf->cookie.len + v->len + sizeof ("; path=/"); + len = llcf->cookie.len + v->len + sizeof (cookie_params); cookie = ngx_pnalloc (r->pool, len + 1); if (cookie == NULL) { @@ -235,7 +262,7 @@ ngx_http_set_lang_from_methods (ngx_http_request_t *r, ngx_str_t *v) *p++ = '='; p = ngx_copy (p, v->data, v->len); - p = ngx_copy (p, "; path=/", sizeof ("; path=/")); + p = ngx_copy (p, cookie_params, sizeof (cookie_params)); // add lang cookie to main response @@ -375,15 +402,28 @@ ngx_http_set_lang_from_post (ngx_http_request_t *r, ngx_http_set_lang_loc_conf_t static ngx_int_t ngx_http_set_lang_from_cookie (ngx_http_request_t *r, ngx_http_set_lang_loc_conf_t *conf, ngx_str_t *v) { - ngx_str_t cookie; + ngx_str_t cookie, *lang; + ngx_uint_t i; if (ngx_http_parse_multi_header_lines (&r->headers_in.cookies, &conf->cookie, &cookie) == NGX_DECLINED) return NGX_DECLINED; - v->data = cookie.data; - v->len = cookie.len; + // compare to lang list - return NGX_OK; + lang = conf->langs->elts; + + for (i=conf->langs->nelts; i; i--,lang++) { + + if (cookie.len == lang->len && !ngx_strncasecmp (cookie.data, lang->data, cookie.len)) { + + v->data = cookie.data; + v->len = cookie.len; + + return NGX_OK; + } + } + + return NGX_DECLINED; } @@ -399,6 +439,22 @@ ngx_http_set_lang_from_geoip (ngx_http_request_t *r, ngx_http_set_lang_loc_conf_ +static ngx_int_t +ngx_http_set_lang_from_default (ngx_http_request_t *r, ngx_http_set_lang_loc_conf_t *conf, ngx_str_t *v) +{ + // Default to the first language in the lang_list + ngx_str_t *lang; + + lang = ((ngx_str_t *)conf->langs->elts) + (conf->langs->nelts - 1); + + v->data = lang->data; + v->len = lang->len; + + return NGX_OK; +} + + + static ngx_int_t ngx_http_set_lang_from_host (ngx_http_request_t *r, ngx_http_set_lang_loc_conf_t *conf, ngx_str_t *v) {