1
#include <ngx_config.h>
4
#include "../include/mapcache.h"
6
#include <apr_strings.h>
10
apr_pool_t *process_pool = NULL;
11
static char *ngx_http_mapcache(ngx_conf_t *cf, ngx_command_t *cmd,
14
static ngx_command_t ngx_http_mapcache_commands[] = {
17
ngx_string("mapcache"),
18
NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
20
NGX_HTTP_LOC_CONF_OFFSET,
30
ngx_http_request_t *r;
31
} mapcache_ngx_context;
33
static void ngx_mapcache_context_log(mapcache_context *c, mapcache_log_level level, char *message, ...)
35
mapcache_ngx_context *ctx = (mapcache_ngx_context*)c;
37
if(!c->config || level >= c->config->loglevel) {
38
va_start(args,message);
39
ngx_log_error(NGX_LOG_ALERT, ctx->r->connection->log, 0,
40
apr_pvsprintf(c->pool,message,args));
45
static mapcache_context* ngx_mapcache_context_clone(mapcache_context *ctx)
47
mapcache_context *nctx = (mapcache_context*)apr_pcalloc(ctx->pool,
48
sizeof(mapcache_ngx_context));
49
mapcache_context_copy(ctx,nctx);
50
((mapcache_ngx_context*)nctx)->r = ((mapcache_ngx_context*)ctx)->r;
51
apr_pool_create(&nctx->pool,ctx->pool);
57
ngx_http_mapcache_create_conf(ngx_conf_t *cf)
60
atexit(apr_terminate);
61
apr_pool_initialize();
62
apr_pool_create(&process_pool,NULL);
63
mapcache_context *ctx = apr_pcalloc(process_pool, sizeof(mapcache_ngx_context));
64
ctx->pool = process_pool;
65
ctx->process_pool = process_pool;
66
ctx->threadlock = NULL;
67
mapcache_context_init(ctx);
68
ctx->log = ngx_mapcache_context_log;
69
ctx->clone = ngx_mapcache_context_clone;
77
static void ngx_http_mapcache_write_response(mapcache_context *ctx, ngx_http_request_t *r,
78
mapcache_http_response *response)
81
time_t if_modified_since;
82
if(r->headers_in.if_modified_since) {
83
if_modified_since = ngx_http_parse_time(r->headers_in.if_modified_since->value.data,
84
r->headers_in.if_modified_since->value.len);
85
if (if_modified_since != NGX_ERROR) {
86
apr_time_t apr_if_m_s;
87
apr_time_ansi_put ( &apr_if_m_s, if_modified_since);
88
if(apr_if_m_s<response->mtime) {
89
r->headers_out.status = NGX_HTTP_NOT_MODIFIED;
90
ngx_http_send_header(r);
96
datestr = apr_palloc(ctx->pool, APR_RFC822_DATE_LEN);
97
apr_rfc822_date(datestr, response->mtime);
98
apr_table_setn(response->headers,"Last-Modified",datestr);
100
if(response->headers && !apr_is_empty_table(response->headers)) {
101
const apr_array_header_t *elts = apr_table_elts(response->headers);
103
for(i=0; i<elts->nelts; i++) {
104
apr_table_entry_t entry = APR_ARRAY_IDX(elts,i,apr_table_entry_t);
105
if(!strcasecmp(entry.key,"Content-Type")) {
106
r->headers_out.content_type.len = strlen(entry.val);
107
r->headers_out.content_type.data = (u_char*)entry.val;
110
h = ngx_list_push(&r->headers_out.headers);
114
h->key.len = strlen(entry.key) ;
115
h->key.data = (u_char*)entry.key ;
116
h->value.len = strlen(entry.val) ;
117
h->value.data = (u_char*)entry.val ;
123
r->headers_out.content_length_n = response->data->size;
126
r->headers_out.status = response->code;
127
rc = ngx_http_send_header(r);
128
if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
135
b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
137
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
138
"Failed to allocate response buffer.");
142
b->pos = ngx_pcalloc(r->pool,response->data->size);
143
memcpy(b->pos,response->data->buf,response->data->size);
144
b->last = b->pos + response->data->size;
150
ngx_http_output_filter(r, &out);
156
static ngx_http_module_t ngx_http_mapcache_module_ctx = {
157
NULL, /* preconfiguration */
158
NULL, /* postconfiguration */
160
NULL, /* create main configuration */
161
NULL, /* init main configuration */
163
NULL, /* create server configuration */
164
NULL, /* merge server configuration */
166
ngx_http_mapcache_create_conf, /* create location configuration */
167
NULL /* merge location configuration */
170
static ngx_int_t ngx_mapcache_init_process(ngx_cycle_t *cycle)
173
atexit(apr_terminate);
174
apr_pool_initialize();
175
apr_pool_create(&process_pool,NULL);
179
static void ngx_mapcache_exit_process(ngx_cycle_t *cycle)
181
apr_pool_destroy(process_pool);
184
ngx_module_t ngx_http_mapcache_module = {
186
&ngx_http_mapcache_module_ctx, /* module context */
187
ngx_http_mapcache_commands, /* module directives */
188
NGX_HTTP_MODULE, /* module type */
189
NULL, /* init master */
190
NULL, /* init module */
191
ngx_mapcache_init_process,/* init process */
192
NULL, /* init thread */
193
NULL, /* exit thread */
194
ngx_mapcache_exit_process, /* exit process */
195
ngx_mapcache_exit_process, /* exit master */
196
NGX_MODULE_V1_PADDING
199
static ngx_str_t pathinfo_str = ngx_string("path_info");
200
static ngx_int_t pathinfo_index;
201
static ngx_str_t urlprefix_str = ngx_string("url_prefix");
202
static ngx_int_t urlprefix_index;
205
ngx_http_mapcache_handler(ngx_http_request_t *r)
207
int ret = NGX_HTTP_OK;
208
if (!(r->method & (NGX_HTTP_GET))) {
209
return NGX_HTTP_NOT_ALLOWED;
211
mapcache_ngx_context *ngctx = ngx_http_get_module_loc_conf(r, ngx_http_mapcache_module);
212
mapcache_context *ctx = (mapcache_context*)ngctx;
213
apr_pool_create(&(ctx->pool),process_pool);
214
ctx->process_pool = process_pool;
216
mapcache_request *request = NULL;
217
mapcache_http_response *http_response;
219
ngx_http_variable_value_t *pathinfovv = ngx_http_get_indexed_variable(r, pathinfo_index);
221
char* pathInfo = apr_pstrndup(ctx->pool, (char*)pathinfovv->data, pathinfovv->len);
222
char *sparams = apr_pstrndup(ctx->pool, (char*)r->args.data, r->args.len);
223
apr_table_t *params = mapcache_http_parse_param_string(ctx, sparams);
225
mapcache_service_dispatch_request(ctx,&request,pathInfo,params,ctx->config);
226
if(GC_HAS_ERROR(ctx) || !request) {
227
ngx_http_mapcache_write_response(ctx,r, mapcache_core_respond_to_error(ctx));
231
http_response = NULL;
232
if(request->type == MAPCACHE_REQUEST_GET_CAPABILITIES) {
233
mapcache_request_get_capabilities *req = (mapcache_request_get_capabilities*)request;
234
ngx_http_variable_value_t *urlprefixvv = ngx_http_get_indexed_variable(r, urlprefix_index);
235
char *url = apr_pstrcat(ctx->pool,
237
apr_pstrndup(ctx->pool, (char*)r->headers_in.host->value.data, r->headers_in.host->value.len),
238
apr_pstrndup(ctx->pool, (char*)urlprefixvv->data, urlprefixvv->len),
242
http_response = mapcache_core_get_capabilities(ctx,request->service,req,url,pathInfo,ctx->config);
243
} else if( request->type == MAPCACHE_REQUEST_GET_TILE) {
244
mapcache_request_get_tile *req_tile = (mapcache_request_get_tile*)request;
245
http_response = mapcache_core_get_tile(ctx,req_tile);
246
} else if( request->type == MAPCACHE_REQUEST_GET_MAP) {
247
mapcache_request_get_map *req_map = (mapcache_request_get_map*)request;
248
http_response = mapcache_core_get_map(ctx,req_map);
250
} else if( request->type == MAPCACHE_REQUEST_PROXY ) {
251
mapcache_request_proxy *req_proxy = (mapcache_request_proxy*)request;
252
http_response = mapcache_core_proxy_request(ctx, req_proxy);
253
} else if( request->type == MAPCACHE_REQUEST_GET_FEATUREINFO) {
254
mapcache_request_get_feature_info *req_fi = (mapcache_request_get_feature_info*)request;
255
http_response = mapcache_core_get_featureinfo(ctx,req_fi);
259
ctx->set_error(ctx,500,"###BUG### unknown request type");
262
if(GC_HAS_ERROR(ctx)) {
263
// ngx_http_mapcache_write_response(ctx,r, mapcache_core_respond_to_error(ctx));
268
ctx->set_error(ctx,500,"###BUG### NULL response");
269
ngx_http_mapcache_write_response(ctx,r, mapcache_core_respond_to_error(ctx));
273
ngx_http_mapcache_write_response(ctx,r,http_response);
275
if(GC_HAS_ERROR(ctx))
276
ret = ctx->_errcode?ctx->_errcode:500;
277
ctx->clear_errors(ctx);
278
apr_pool_destroy(ctx->pool);
284
ngx_http_mapcache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
286
mapcache_context *ctx = conf;
288
value = cf->args->elts;
289
char *conffile = (char*)value[1].data;
290
ctx->config = mapcache_configuration_create(ctx->pool);
291
mapcache_configuration_parse(ctx,conffile,ctx->config,1);
292
if(GC_HAS_ERROR(ctx)) {
293
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,ctx->get_error_message(ctx));
294
return NGX_CONF_ERROR;
296
mapcache_configuration_post_config(ctx, ctx->config);
297
if(GC_HAS_ERROR(ctx)) {
298
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,ctx->get_error_message(ctx));
299
return NGX_CONF_ERROR;
301
ctx->config->non_blocking = 1;
303
ngx_http_core_loc_conf_t *clcf;
305
clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
306
clcf->handler = ngx_http_mapcache_handler;
308
pathinfo_index = ngx_http_get_variable_index(cf, &pathinfo_str);
309
if (pathinfo_index == NGX_ERROR) {
310
return NGX_CONF_ERROR;
312
urlprefix_index = ngx_http_get_variable_index(cf, &urlprefix_str);
313
if (urlprefix_index == NGX_ERROR) {
314
return NGX_CONF_ERROR;