Commit 52e9c1aca08d09df3562d22ad4eb692293168f11
1 parent
91ecca1a
Exists in
master
and in
28 other branches
Documenting Varnish usage
(ActionItem1608)
Showing
2 changed files
with
253 additions
and
0 deletions
Show diff stats
| ... | ... | @@ -0,0 +1,67 @@ |
| 1 | += Setting up Varnish for your Noosfero site | |
| 2 | + | |
| 3 | +Varnish is a HTTP caching server, and using it together with Noosfero is highly | |
| 4 | +recommended. See http://www.varnish-cache.org/ for more information on Varnish. | |
| 5 | + | |
| 6 | +Varnish can be set up to use with Noosfero with the following steps: | |
| 7 | + | |
| 8 | +1) setup Noosfero with apache according to the INSTALL file. | |
| 9 | + | |
| 10 | +2) install Varnish | |
| 11 | + | |
| 12 | + # apt-get install varnish | |
| 13 | + | |
| 14 | +Noosfero was tested with Varnish 2.x. If you are using a Debian Lenny (and you | |
| 15 | +should, unless Debian already released Squeeze by now), make sure you install | |
| 16 | +varnish from the lenny-backports suite. | |
| 17 | + | |
| 18 | +3) Enable varnish logging: | |
| 19 | + | |
| 20 | +3a) Edit /etc/default/varnishncsa and uncomment the line that contains: | |
| 21 | + | |
| 22 | +VARNISHNCSA_ENABLED=1 | |
| 23 | + | |
| 24 | +The varnish log will be written to /var/log/varnish/varnishncsa.log in an | |
| 25 | +apache-compatible format. You should change your statistics generation software | |
| 26 | +(e.g. awstats) to use that instead of apache logs. | |
| 27 | + | |
| 28 | +3b) Restart Varnish Logging service | |
| 29 | + | |
| 30 | + # invoke-rc.d varnishncsa start | |
| 31 | + | |
| 32 | +4) Change Apache to listen on port 8080 instead of 80 | |
| 33 | + | |
| 34 | +4a) Edit /etc/apache2/ports.conf, and: | |
| 35 | + | |
| 36 | + * change 'Listen 80' to 'Listen 127.0.0.1:8080' | |
| 37 | + * change 'NameVirtualHost *:80' to 'NameVirtualHost *:8080' | |
| 38 | + | |
| 39 | +4b) Edit /etc/apache2/sites-enabled/*, and change '<VirtualHost *:80>' to '<VirtualHost *:8080>' | |
| 40 | + | |
| 41 | +4c) Restart apache | |
| 42 | + | |
| 43 | + # invoke-rc.d apache2 restart | |
| 44 | + | |
| 45 | +5) Change Varnish to listen on port 80 | |
| 46 | + | |
| 47 | +5a) Edit /etc/default/varnish and change '-a :6081' to '-a :80' | |
| 48 | + | |
| 49 | +5b) Restart Varnish | |
| 50 | + | |
| 51 | + # invoke-rc.d varnish restart | |
| 52 | + | |
| 53 | +6) Configure varnish to store separate caches for each language | |
| 54 | + | |
| 55 | +6a) Add the following line to your /etc/varnish/default.vcl file (assuming | |
| 56 | +Noosfero is installed in /var/lib/noosfero): | |
| 57 | + | |
| 58 | + include "/var/lib/noosfero/etc/noosfero/varnish-accept-language.vcl"; | |
| 59 | + | |
| 60 | +6b) Restart Varnish | |
| 61 | + | |
| 62 | + # invoke-rc.d varnish restart | |
| 63 | + | |
| 64 | +Thanks to Cosimo Streppone for varnish-accept-language. See | |
| 65 | +http://github.com/cosimo/varnish-accept-language for more information. | |
| 66 | + | |
| 67 | + -- Antonio Terceiro <terceiro@colivre.coop.br> Sat, 04 Sep 2010 17:29:27 -0300 | ... | ... |
| ... | ... | @@ -0,0 +1,186 @@ |
| 1 | +C{ | |
| 2 | + | |
| 3 | +/* ------------------------------------------------------------------ */ | |
| 4 | +/* THIS FILE IS AUTOMATICALLY GENERATED BY ./gen_vcl.pl. DO NOT EDIT. */ | |
| 5 | + | |
| 6 | +/* | |
| 7 | + * Accept-language header normalization | |
| 8 | + * | |
| 9 | + * Cosimo, 21/01/2010 | |
| 10 | + * | |
| 11 | + */ | |
| 12 | + | |
| 13 | +#include <ctype.h> /* isupper */ | |
| 14 | +#include <stdio.h> | |
| 15 | +#include <stdlib.h> /* qsort */ | |
| 16 | +#include <string.h> | |
| 17 | + | |
| 18 | +#define DEFAULT_LANGUAGE "en" | |
| 19 | +#define SUPPORTED_LANGUAGES ":de:fr:es:ru:pt:hy:en:" | |
| 20 | + | |
| 21 | +#define vcl_string char | |
| 22 | +#define LANG_LIST_SIZE 16 | |
| 23 | +#define LANG_MAXLEN 16 | |
| 24 | +#define RETURN_LANG(x) { \ | |
| 25 | + strncpy(lang, x, LANG_MAXLEN); \ | |
| 26 | + return; \ | |
| 27 | +} | |
| 28 | +#define RETURN_DEFAULT_LANG RETURN_LANG(DEFAULT_LANGUAGE) | |
| 29 | +#define PUSH_LANG(x,y) { \ | |
| 30 | + /* fprintf(stderr, "Pushing lang [%d] %s %.4f\n", curr_lang, x, y); */ \ | |
| 31 | + /* We have to copy, otherwise root_lang will be the same every time */ \ | |
| 32 | + strncpy(pl[curr_lang].lang, x, LANG_MAXLEN); \ | |
| 33 | + pl[curr_lang].q = y; \ | |
| 34 | + curr_lang++; \ | |
| 35 | +} | |
| 36 | + | |
| 37 | +struct lang_list { | |
| 38 | + vcl_string lang[LANG_MAXLEN]; | |
| 39 | + float q; | |
| 40 | +}; | |
| 41 | + | |
| 42 | +/* In-place lowercase of a string */ | |
| 43 | +static void strtolower(char *s) { | |
| 44 | + register char *c; | |
| 45 | + for (c=s; *c; c++) { | |
| 46 | + if (isupper(*c)) { | |
| 47 | + *c = tolower(*c); | |
| 48 | + } | |
| 49 | + } | |
| 50 | + return; | |
| 51 | +} | |
| 52 | + | |
| 53 | +/* Checks if a given language is in the static list of the ones we support */ | |
| 54 | +int is_supported(vcl_string *lang) { | |
| 55 | + vcl_string *supported_languages = SUPPORTED_LANGUAGES; | |
| 56 | + vcl_string match_str[LANG_MAXLEN + 3] = ""; /* :, :, \0 = 3 */ | |
| 57 | + int is_supported = 0; | |
| 58 | + | |
| 59 | + /* We want to match 'zh-cn' and 'zh-CN' too */ | |
| 60 | + strtolower(lang); | |
| 61 | + | |
| 62 | + /* Search ":<lang>:" in supported languages string */ | |
| 63 | + strncpy(match_str, ":", 1); | |
| 64 | + strncat(match_str, lang, LANG_MAXLEN); | |
| 65 | + strncat(match_str, ":\0", 2); | |
| 66 | + | |
| 67 | + if (strstr(supported_languages, match_str)) { | |
| 68 | + is_supported = 1; | |
| 69 | + } | |
| 70 | + | |
| 71 | + return is_supported; | |
| 72 | +} | |
| 73 | + | |
| 74 | +/* Used by qsort() below */ | |
| 75 | +int sort_by_q(const void *x, const void *y) { | |
| 76 | + struct lang_list *a = (struct lang_list *)x; | |
| 77 | + struct lang_list *b = (struct lang_list *)y; | |
| 78 | + if (a->q > b->q) return -1; | |
| 79 | + if (a->q < b->q) return 1; | |
| 80 | + return 0; | |
| 81 | +} | |
| 82 | + | |
| 83 | +/* Reads Accept-Language, parses it, and finds the first match | |
| 84 | + among the supported languages. In case of no match, | |
| 85 | + returns the default language. | |
| 86 | +*/ | |
| 87 | +void select_language(const vcl_string *incoming_header, char *lang) { | |
| 88 | + | |
| 89 | + struct lang_list pl[LANG_LIST_SIZE]; | |
| 90 | + vcl_string *lang_tok = NULL; | |
| 91 | + vcl_string root_lang[3]; | |
| 92 | + vcl_string *header; | |
| 93 | + vcl_string *pos = NULL; | |
| 94 | + vcl_string *q_spec = NULL; | |
| 95 | + unsigned int curr_lang = 0, i = 0; | |
| 96 | + float q; | |
| 97 | + | |
| 98 | + /* Empty or default string, return default language immediately */ | |
| 99 | + if ( | |
| 100 | + !incoming_header | |
| 101 | + || (0 == strcmp(incoming_header, "en-US")) | |
| 102 | + || (0 == strcmp(incoming_header, "en-GB")) | |
| 103 | + || (0 == strcmp(incoming_header, DEFAULT_LANGUAGE)) | |
| 104 | + || (0 == strcmp(incoming_header, "")) | |
| 105 | + ) | |
| 106 | + RETURN_DEFAULT_LANG; | |
| 107 | + | |
| 108 | + /* Tokenize Accept-Language */ | |
| 109 | + header = (vcl_string *) incoming_header; | |
| 110 | + | |
| 111 | + while ((lang_tok = strtok_r(header, " ,", &pos))) { | |
| 112 | + | |
| 113 | + q = 1.0; | |
| 114 | + | |
| 115 | + if ((q_spec = strstr(lang_tok, ";q="))) { | |
| 116 | + /* Truncate language name before ';' */ | |
| 117 | + *q_spec = '\0'; | |
| 118 | + /* Get q value */ | |
| 119 | + sscanf(q_spec + 3, "%f", &q); | |
| 120 | + } | |
| 121 | + | |
| 122 | + /* Wildcard language '*' should be last in list */ | |
| 123 | + if ((*lang_tok) == '*') q = 0.0; | |
| 124 | + | |
| 125 | + /* Push in the prioritized list */ | |
| 126 | + PUSH_LANG(lang_tok, q); | |
| 127 | + | |
| 128 | + /* For cases like 'en-GB', we also want the root language in the final list */ | |
| 129 | + if ('-' == lang_tok[2]) { | |
| 130 | + root_lang[0] = lang_tok[0]; | |
| 131 | + root_lang[1] = lang_tok[1]; | |
| 132 | + root_lang[2] = '\0'; | |
| 133 | + PUSH_LANG(root_lang, q - 0.001); | |
| 134 | + } | |
| 135 | + | |
| 136 | + /* For strtok_r() to proceed from where it left off */ | |
| 137 | + header = NULL; | |
| 138 | + | |
| 139 | + /* Break out if stored max no. of languages */ | |
| 140 | + if (curr_lang >= LANG_MAXLEN) break; | |
| 141 | + } | |
| 142 | + | |
| 143 | + /* Sort by priority */ | |
| 144 | + qsort(pl, curr_lang, sizeof(struct lang_list), &sort_by_q); | |
| 145 | + | |
| 146 | + /* Match with supported languages */ | |
| 147 | + for (i = 0; i < curr_lang; i++) { | |
| 148 | + if (is_supported(pl[i].lang)) | |
| 149 | + RETURN_LANG(pl[i].lang); | |
| 150 | + } | |
| 151 | + | |
| 152 | + RETURN_DEFAULT_LANG; | |
| 153 | +} | |
| 154 | + | |
| 155 | +/* Reads req.http.Accept-Language and writes X-Varnish-Accept-Language */ | |
| 156 | +void vcl_rewrite_accept_language(const struct sess *sp) { | |
| 157 | + vcl_string *in_hdr; | |
| 158 | + vcl_string lang[LANG_MAXLEN]; | |
| 159 | + | |
| 160 | + memset(lang, 0, LANG_MAXLEN); | |
| 161 | + | |
| 162 | + /* Get Accept-Language header from client */ | |
| 163 | + in_hdr = VRT_GetHdr(sp, HDR_REQ, "\020Accept-Language:"); | |
| 164 | + | |
| 165 | + /* Normalize and filter out by list of supported languages */ | |
| 166 | + select_language(in_hdr, lang); | |
| 167 | + | |
| 168 | + /* By default, use a different header name: don't mess with backend logic */ | |
| 169 | + VRT_SetHdr(sp, HDR_REQ, "\032X-Varnish-Accept-Language:", lang, vrt_magic_string_end); | |
| 170 | + | |
| 171 | + return; | |
| 172 | +} | |
| 173 | + | |
| 174 | +/* vim: syn=c ts=4 et sts=4 sw=4 tw=0 | |
| 175 | +*/ | |
| 176 | + | |
| 177 | +/* THIS FILE IS AUTOMATICALLY GENERATED BY ./gen_vcl.pl. DO NOT EDIT. */ | |
| 178 | +/* ------------------------------------------------------------------ */ | |
| 179 | +}C | |
| 180 | + | |
| 181 | +sub vcl_recv { | |
| 182 | + C{ | |
| 183 | + vcl_rewrite_accept_language(sp); | |
| 184 | + }C | |
| 185 | + return(pass); | |
| 186 | +} | ... | ... |