comparison src/http/modules/ngx_http_geoip_module.c @ 665:0b460e61bdcd default tip

Merge with nginx 1.0.0.
author Maxim Dounin <mdounin@mdounin.ru>
date Mon, 25 Apr 2011 04:22:17 +0400
parents bb20316269e4
children
comparison
equal deleted inserted replaced
572:06419a2298a9 665:0b460e61bdcd
28 28
29 static ngx_int_t ngx_http_geoip_country_variable(ngx_http_request_t *r, 29 static ngx_int_t ngx_http_geoip_country_variable(ngx_http_request_t *r,
30 ngx_http_variable_value_t *v, uintptr_t data); 30 ngx_http_variable_value_t *v, uintptr_t data);
31 static ngx_int_t ngx_http_geoip_city_variable(ngx_http_request_t *r, 31 static ngx_int_t ngx_http_geoip_city_variable(ngx_http_request_t *r,
32 ngx_http_variable_value_t *v, uintptr_t data); 32 ngx_http_variable_value_t *v, uintptr_t data);
33 static ngx_int_t ngx_http_geoip_region_name_variable(ngx_http_request_t *r,
34 ngx_http_variable_value_t *v, uintptr_t data);
35 static ngx_int_t ngx_http_geoip_city_float_variable(ngx_http_request_t *r,
36 ngx_http_variable_value_t *v, uintptr_t data);
37 static ngx_int_t ngx_http_geoip_city_int_variable(ngx_http_request_t *r,
38 ngx_http_variable_value_t *v, uintptr_t data);
39 static GeoIPRecord *ngx_http_geoip_get_city_record(ngx_http_request_t *r);
33 40
34 static ngx_int_t ngx_http_geoip_add_variables(ngx_conf_t *cf); 41 static ngx_int_t ngx_http_geoip_add_variables(ngx_conf_t *cf);
35 static void *ngx_http_geoip_create_conf(ngx_conf_t *cf); 42 static void *ngx_http_geoip_create_conf(ngx_conf_t *cf);
36 static char *ngx_http_geoip_country(ngx_conf_t *cf, ngx_command_t *cmd, 43 static char *ngx_http_geoip_country(ngx_conf_t *cf, ngx_command_t *cmd,
37 void *conf); 44 void *conf);
41 48
42 49
43 static ngx_command_t ngx_http_geoip_commands[] = { 50 static ngx_command_t ngx_http_geoip_commands[] = {
44 51
45 { ngx_string("geoip_country"), 52 { ngx_string("geoip_country"),
46 NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, 53 NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE12,
47 ngx_http_geoip_country, 54 ngx_http_geoip_country,
48 NGX_HTTP_MAIN_CONF_OFFSET, 55 NGX_HTTP_MAIN_CONF_OFFSET,
49 0, 56 0,
50 NULL }, 57 NULL },
51 58
52 { ngx_string("geoip_city"), 59 { ngx_string("geoip_city"),
53 NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, 60 NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE12,
54 ngx_http_geoip_city, 61 ngx_http_geoip_city,
55 NGX_HTTP_MAIN_CONF_OFFSET, 62 NGX_HTTP_MAIN_CONF_OFFSET,
56 0, 63 0,
57 NULL }, 64 NULL },
58 65
91 }; 98 };
92 99
93 100
94 static ngx_http_variable_t ngx_http_geoip_vars[] = { 101 static ngx_http_variable_t ngx_http_geoip_vars[] = {
95 102
96 { ngx_string("geoip_country_code"), NULL, ngx_http_geoip_country_variable, 103 { ngx_string("geoip_country_code"), NULL,
104 ngx_http_geoip_country_variable,
97 (uintptr_t) GeoIP_country_code_by_ipnum, 0, 0 }, 105 (uintptr_t) GeoIP_country_code_by_ipnum, 0, 0 },
98 106
99 { ngx_string("geoip_country_code3"), NULL, ngx_http_geoip_country_variable, 107 { ngx_string("geoip_country_code3"), NULL,
108 ngx_http_geoip_country_variable,
100 (uintptr_t) GeoIP_country_code3_by_ipnum, 0, 0 }, 109 (uintptr_t) GeoIP_country_code3_by_ipnum, 0, 0 },
101 110
102 { ngx_string("geoip_country_name"), NULL, ngx_http_geoip_country_variable, 111 { ngx_string("geoip_country_name"), NULL,
112 ngx_http_geoip_country_variable,
103 (uintptr_t) GeoIP_country_name_by_ipnum, 0, 0 }, 113 (uintptr_t) GeoIP_country_name_by_ipnum, 0, 0 },
104 114
105 { ngx_string("geoip_city_country_code"), NULL, ngx_http_geoip_city_variable, 115 { ngx_string("geoip_city_continent_code"), NULL,
116 ngx_http_geoip_city_variable,
117 offsetof(GeoIPRecord, continent_code), 0, 0 },
118
119 { ngx_string("geoip_city_country_code"), NULL,
120 ngx_http_geoip_city_variable,
106 offsetof(GeoIPRecord, country_code), 0, 0 }, 121 offsetof(GeoIPRecord, country_code), 0, 0 },
107 122
108 { ngx_string("geoip_city_country_code3"), NULL, 123 { ngx_string("geoip_city_country_code3"), NULL,
109 ngx_http_geoip_city_variable, 124 ngx_http_geoip_city_variable,
110 offsetof(GeoIPRecord, country_code3), 0, 0 }, 125 offsetof(GeoIPRecord, country_code3), 0, 0 },
111 126
112 { ngx_string("geoip_city_country_name"), NULL, ngx_http_geoip_city_variable, 127 { ngx_string("geoip_city_country_name"), NULL,
128 ngx_http_geoip_city_variable,
113 offsetof(GeoIPRecord, country_name), 0, 0 }, 129 offsetof(GeoIPRecord, country_name), 0, 0 },
114 130
115 { ngx_string("geoip_region"), NULL, 131 { ngx_string("geoip_region"), NULL,
116 ngx_http_geoip_city_variable, 132 ngx_http_geoip_city_variable,
117 offsetof(GeoIPRecord, region), 0, 0 }, 133 offsetof(GeoIPRecord, region), 0, 0 },
118 134
135 { ngx_string("geoip_region_name"), NULL,
136 ngx_http_geoip_region_name_variable,
137 0, 0, 0 },
138
119 { ngx_string("geoip_city"), NULL, 139 { ngx_string("geoip_city"), NULL,
120 ngx_http_geoip_city_variable, 140 ngx_http_geoip_city_variable,
121 offsetof(GeoIPRecord, city), 0, 0 }, 141 offsetof(GeoIPRecord, city), 0, 0 },
122 142
123 { ngx_string("geoip_postal_code"), NULL, 143 { ngx_string("geoip_postal_code"), NULL,
124 ngx_http_geoip_city_variable, 144 ngx_http_geoip_city_variable,
125 offsetof(GeoIPRecord, postal_code), 0, 0 }, 145 offsetof(GeoIPRecord, postal_code), 0, 0 },
146
147 { ngx_string("geoip_latitude"), NULL,
148 ngx_http_geoip_city_float_variable,
149 offsetof(GeoIPRecord, latitude), 0, 0 },
150
151 { ngx_string("geoip_longitude"), NULL,
152 ngx_http_geoip_city_float_variable,
153 offsetof(GeoIPRecord, longitude), 0, 0 },
154
155 { ngx_string("geoip_dma_code"), NULL,
156 ngx_http_geoip_city_int_variable,
157 offsetof(GeoIPRecord, dma_code), 0, 0 },
158
159 { ngx_string("geoip_area_code"), NULL,
160 ngx_http_geoip_city_int_variable,
161 offsetof(GeoIPRecord, area_code), 0, 0 },
126 162
127 { ngx_null_string, NULL, NULL, 0, 0, 0 } 163 { ngx_null_string, NULL, NULL, 0, 0, 0 }
128 }; 164 };
129 165
130 166
177 213
178 static ngx_int_t 214 static ngx_int_t
179 ngx_http_geoip_city_variable(ngx_http_request_t *r, 215 ngx_http_geoip_city_variable(ngx_http_request_t *r,
180 ngx_http_variable_value_t *v, uintptr_t data) 216 ngx_http_variable_value_t *v, uintptr_t data)
181 { 217 {
182 u_long addr; 218 char *val;
183 char *val; 219 size_t len;
184 size_t len; 220 GeoIPRecord *gr;
185 GeoIPRecord *gr; 221
186 struct sockaddr_in *sin; 222 gr = ngx_http_geoip_get_city_record(r);
187 ngx_http_geoip_conf_t *gcf;
188
189 gcf = ngx_http_get_module_main_conf(r, ngx_http_geoip_module);
190
191 if (gcf->city == NULL) {
192 goto not_found;
193 }
194
195 if (r->connection->sockaddr->sa_family != AF_INET) {
196 goto not_found;
197 }
198
199 sin = (struct sockaddr_in *) r->connection->sockaddr;
200 addr = ntohl(sin->sin_addr.s_addr);
201
202 gr = GeoIP_record_by_ipnum(gcf->city, addr);
203
204 if (gr == NULL) { 223 if (gr == NULL) {
205 goto not_found; 224 goto not_found;
206 } 225 }
207 226
208 val = *(char **) ((char *) gr + data); 227 val = *(char **) ((char *) gr + data);
209
210 if (val == NULL) { 228 if (val == NULL) {
211 goto no_value; 229 goto no_value;
212 } 230 }
213 231
214 len = ngx_strlen(val); 232 len = ngx_strlen(val);
215 v->data = ngx_pnalloc(r->pool, len); 233 v->data = ngx_pnalloc(r->pool, len);
216
217 if (v->data == NULL) { 234 if (v->data == NULL) {
218 GeoIPRecord_delete(gr); 235 GeoIPRecord_delete(gr);
219 return NGX_ERROR; 236 return NGX_ERROR;
220 } 237 }
221 238
237 not_found: 254 not_found:
238 255
239 v->not_found = 1; 256 v->not_found = 1;
240 257
241 return NGX_OK; 258 return NGX_OK;
259 }
260
261
262 static ngx_int_t
263 ngx_http_geoip_region_name_variable(ngx_http_request_t *r,
264 ngx_http_variable_value_t *v, uintptr_t data)
265 {
266 size_t len;
267 const char *val;
268 GeoIPRecord *gr;
269
270 gr = ngx_http_geoip_get_city_record(r);
271 if (gr == NULL) {
272 goto not_found;
273 }
274
275 val = GeoIP_region_name_by_code(gr->country_code, gr->region);
276
277 GeoIPRecord_delete(gr);
278
279 if (val == NULL) {
280 goto not_found;
281 }
282
283 len = ngx_strlen(val);
284 v->data = ngx_pnalloc(r->pool, len);
285 if (v->data == NULL) {
286 return NGX_ERROR;
287 }
288
289 ngx_memcpy(v->data, val, len);
290
291 v->len = len;
292 v->valid = 1;
293 v->no_cacheable = 0;
294 v->not_found = 0;
295
296 return NGX_OK;
297
298 not_found:
299
300 v->not_found = 1;
301
302 return NGX_OK;
303 }
304
305
306 static ngx_int_t
307 ngx_http_geoip_city_float_variable(ngx_http_request_t *r,
308 ngx_http_variable_value_t *v, uintptr_t data)
309 {
310 float val;
311 GeoIPRecord *gr;
312
313 gr = ngx_http_geoip_get_city_record(r);
314 if (gr == NULL) {
315 v->not_found = 1;
316 return NGX_OK;
317 }
318
319 v->data = ngx_pnalloc(r->pool, NGX_INT64_LEN + 5);
320 if (v->data == NULL) {
321 GeoIPRecord_delete(gr);
322 return NGX_ERROR;
323 }
324
325 val = *(float *) ((char *) gr + data);
326
327 v->len = ngx_sprintf(v->data, "%.4f", val) - v->data;
328
329 GeoIPRecord_delete(gr);
330
331 return NGX_OK;
332 }
333
334
335 static ngx_int_t
336 ngx_http_geoip_city_int_variable(ngx_http_request_t *r,
337 ngx_http_variable_value_t *v, uintptr_t data)
338 {
339 int val;
340 GeoIPRecord *gr;
341
342 gr = ngx_http_geoip_get_city_record(r);
343 if (gr == NULL) {
344 v->not_found = 1;
345 return NGX_OK;
346 }
347
348 v->data = ngx_pnalloc(r->pool, NGX_INT64_LEN);
349 if (v->data == NULL) {
350 GeoIPRecord_delete(gr);
351 return NGX_ERROR;
352 }
353
354 val = *(int *) ((char *) gr + data);
355
356 v->len = ngx_sprintf(v->data, "%d", val) - v->data;
357
358 GeoIPRecord_delete(gr);
359
360 return NGX_OK;
361 }
362
363
364 static GeoIPRecord *
365 ngx_http_geoip_get_city_record(ngx_http_request_t *r)
366 {
367 u_long addr;
368 struct sockaddr_in *sin;
369 ngx_http_geoip_conf_t *gcf;
370
371 gcf = ngx_http_get_module_main_conf(r, ngx_http_geoip_module);
372
373 if (gcf->city && r->connection->sockaddr->sa_family == AF_INET) {
374
375 sin = (struct sockaddr_in *) r->connection->sockaddr;
376 addr = ntohl(sin->sin_addr.s_addr);
377
378 return GeoIP_record_by_ipnum(gcf->city, addr);
379 }
380
381 return NULL;
242 } 382 }
243 383
244 384
245 static ngx_int_t 385 static ngx_int_t
246 ngx_http_geoip_add_variables(ngx_conf_t *cf) 386 ngx_http_geoip_add_variables(ngx_conf_t *cf)
304 "GeoIO_open(\"%V\") failed", &value[1]); 444 "GeoIO_open(\"%V\") failed", &value[1]);
305 445
306 return NGX_CONF_ERROR; 446 return NGX_CONF_ERROR;
307 } 447 }
308 448
449 if (cf->args->nelts == 3) {
450 if (ngx_strcmp(value[2].data, "utf8") == 0) {
451 GeoIP_set_charset (gcf->country, GEOIP_CHARSET_UTF8);
452
453 } else {
454 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
455 "invalid parameter \"%V\"", &value[2]);
456 return NGX_CONF_ERROR;
457 }
458 }
459
309 switch (gcf->country->databaseType) { 460 switch (gcf->country->databaseType) {
310 461
311 case GEOIP_COUNTRY_EDITION: 462 case GEOIP_COUNTRY_EDITION:
312 case GEOIP_PROXY_EDITION: 463 case GEOIP_PROXY_EDITION:
313 case GEOIP_NETSPEED_EDITION: 464 case GEOIP_NETSPEED_EDITION:
343 "GeoIO_open(\"%V\") failed", &value[1]); 494 "GeoIO_open(\"%V\") failed", &value[1]);
344 495
345 return NGX_CONF_ERROR; 496 return NGX_CONF_ERROR;
346 } 497 }
347 498
499 if (cf->args->nelts == 3) {
500 if (ngx_strcmp(value[2].data, "utf8") == 0) {
501 GeoIP_set_charset (gcf->city, GEOIP_CHARSET_UTF8);
502
503 } else {
504 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
505 "invalid parameter \"%V\"", &value[2]);
506 return NGX_CONF_ERROR;
507 }
508 }
509
348 switch (gcf->city->databaseType) { 510 switch (gcf->city->databaseType) {
349 511
350 case GEOIP_CITY_EDITION_REV0: 512 case GEOIP_CITY_EDITION_REV0:
351 case GEOIP_CITY_EDITION_REV1: 513 case GEOIP_CITY_EDITION_REV1:
352 514