Skip to content

Commit

Permalink
Updated sample VCL file
Browse files Browse the repository at this point in the history
  • Loading branch information
cosimo committed May 6, 2010
1 parent 04f9a63 commit 7e1fa56
Showing 1 changed file with 51 additions and 12 deletions.
63 changes: 51 additions & 12 deletions examples/accept-language.vcl
Original file line number Diff line number Diff line change
Expand Up @@ -10,38 +10,55 @@ C{
*
*/

#include <ctype.h> /* isupper */
#include <stdio.h>
#include <stdlib.h> /* qsort */
#include <string.h>

#define DEFAULT_LANGUAGE "en"
#define SUPPORTED_LANGUAGES ":en:es:it:ja:ru:zh-cn:"
#define SUPPORTED_LANGUAGES ":bg:cs:da:de:en:es:fi:fy:hu:it:ja:no:pl:ru:sq:sk:tr:uk:vn:xx-lol:zh-cn:"

#define vcl_string char
#define LANG_LIST_SIZE 10
#define LANG_MAXLEN 10
#define LANG_LIST_SIZE 16
#define LANG_MAXLEN 16
#define RETURN_LANG(x) { \
strncpy(lang, x, LANG_MAXLEN); \
return; \
}
#define RETURN_DEFAULT_LANG RETURN_LANG(DEFAULT_LANGUAGE)
#define PUSH_LANG(x,y) { \
pl[curr_lang].lang = x; \
/* fprintf(stderr, "Pushing lang [%d] %s %.4f\n", curr_lang, x, y); */ \
/* We have to copy, otherwise root_lang will be the same every time */ \
strncpy(pl[curr_lang].lang, x, LANG_MAXLEN); \
pl[curr_lang].q = y; \
curr_lang++; \
}

struct lang_list {
vcl_string *lang;
vcl_string lang[LANG_MAXLEN];
float q;
};

/* In-place lowercase of a string */
static void strtolower(char *s) {
register char *c;
for (c=s; *c; c++) {
if (isupper(*c)) {
*c = tolower(*c);
}
}
return;
}

/* Checks if a given language is in the static list of the ones we support */
int is_supported(vcl_string *lang) {
vcl_string *supported_languages = SUPPORTED_LANGUAGES;
vcl_string match_str[LANG_MAXLEN + 3] = ""; /* :, :, \0 = 3 */
int is_supported = 0;

/* We want to match 'zh-cn' and 'zh-CN' too */
strtolower(lang);

/* Search ":<lang>:" in supported languages string */
strncpy(match_str, ":", 1);
strncat(match_str, lang, LANG_MAXLEN);
Expand Down Expand Up @@ -71,34 +88,54 @@ void select_language(const vcl_string *incoming_header, char *lang) {

struct lang_list pl[LANG_LIST_SIZE];
vcl_string *lang_tok = NULL;
vcl_string root_lang[3];
vcl_string *header;
vcl_string *pos = NULL;
vcl_string *q_spec = NULL;
unsigned int curr_lang = 0, i = 0;
float q;

/* Empty string, return default language immediately */
if (! incoming_header || (0 == strcmp(incoming_header, ""))) {
/* Empty or default string, return default language immediately */
if (
!incoming_header
|| (0 == strcmp(incoming_header, "en-US"))
|| (0 == strcmp(incoming_header, "en-GB"))
|| (0 == strcmp(incoming_header, DEFAULT_LANGUAGE))
|| (0 == strcmp(incoming_header, ""))
)
RETURN_DEFAULT_LANG;
}

/* Tokenize Accept-Language */
header = (vcl_string *) incoming_header;

while ((lang_tok = strtok_r(header, " ,", &pos))) {

q = 1.0;

if ((q_spec = strstr(lang_tok, ";q="))) {
/* Truncate language name before ';' */
*q_spec = '\0';
/* Get q value */
sscanf(q_spec + 3, "%f", &q);
}

/* Wildcard language '*' should be last in list */
if ((*lang_tok) == '*') q = 0.0;

/* Push in the prioritized list */
PUSH_LANG(lang_tok, q);

/* For cases like 'en-GB', we also want the root language in the final list */
if ('-' == lang_tok[2]) {
root_lang[0] = lang_tok[0];
root_lang[1] = lang_tok[1];
root_lang[2] = '\0';
PUSH_LANG(root_lang, q - 0.001);
}

/* For strtok_r() to proceed from where it left off */
header = NULL;

/* Break out if stored max no. of languages */
if (curr_lang >= LANG_MAXLEN) break;
}
Expand All @@ -108,8 +145,8 @@ void select_language(const vcl_string *incoming_header, char *lang) {

/* Match with supported languages */
for (i = 0; i < curr_lang; i++) {
if (! is_supported(pl[i].lang)) continue;
RETURN_LANG(pl[i].lang);
if (is_supported(pl[i].lang))
RETURN_LANG(pl[i].lang);
}

RETURN_DEFAULT_LANG;
Expand All @@ -118,7 +155,9 @@ void select_language(const vcl_string *incoming_header, char *lang) {
/* Reads req.http.Accept-Language and writes X-Varnish-Accept-Language */
void vcl_rewrite_accept_language(const struct sess *sp) {
vcl_string *in_hdr;
vcl_string lang[LANG_MAXLEN] = "";
vcl_string lang[LANG_MAXLEN];

memset(lang, 0, LANG_MAXLEN);

/* Get Accept-Language header from client */
in_hdr = VRT_GetHdr(sp, HDR_REQ, "\020Accept-Language:");
Expand All @@ -127,7 +166,7 @@ void vcl_rewrite_accept_language(const struct sess *sp) {
select_language(in_hdr, lang);

/* By default, use a different header name: don't mess with backend logic */
VRT_SetHdr(sp, HDR_REQ, "\032X-Varnish-Accept-Language:", lang);
VRT_SetHdr(sp, HDR_REQ, "\032X-Varnish-Accept-Language:", lang, vrt_magic_string_end);

return;
}
Expand Down

0 comments on commit 7e1fa56

Please sign in to comment.