diff options
Diffstat (limited to 'src/http/modules')
-rw-r--r-- | src/http/modules/ngx_http_chunked_filter_module.c | 1 | ||||
-rw-r--r-- | src/http/modules/ngx_http_dav_module.c | 286 | ||||
-rw-r--r-- | src/http/modules/ngx_http_log_module.c | 28 | ||||
-rw-r--r-- | src/http/modules/perl/nginx.xs | 403 | ||||
-rw-r--r-- | src/http/modules/perl/ngx_http_perl_module.c | 16 | ||||
-rw-r--r-- | src/http/modules/perl/ngx_http_perl_module.h | 5 |
6 files changed, 515 insertions, 224 deletions
diff --git a/src/http/modules/ngx_http_chunked_filter_module.c b/src/http/modules/ngx_http_chunked_filter_module.c index 45110c59e..6581e5904 100644 --- a/src/http/modules/ngx_http_chunked_filter_module.c +++ b/src/http/modules/ngx_http_chunked_filter_module.c @@ -52,6 +52,7 @@ ngx_http_chunked_header_filter(ngx_http_request_t *r) { if (r->headers_out.status == NGX_HTTP_NOT_MODIFIED || r->headers_out.status == NGX_HTTP_NO_CONTENT + || r->headers_out.status == NGX_HTTP_CREATED || r != r->main) { return ngx_http_next_header_filter(r); diff --git a/src/http/modules/ngx_http_dav_module.c b/src/http/modules/ngx_http_dav_module.c new file mode 100644 index 000000000..1b982044f --- /dev/null +++ b/src/http/modules/ngx_http_dav_module.c @@ -0,0 +1,286 @@ + +/* + * Copyright (C) Igor Sysoev + */ + + +#include <ngx_config.h> +#include <ngx_core.h> +#include <ngx_http.h> + + +#define NGX_HTTP_DAV_OFF 2 + +typedef struct { + ngx_uint_t methods; +} ngx_http_dav_loc_conf_t; + + +static ngx_int_t ngx_http_dav_handler(ngx_http_request_t *r); +static void ngx_http_dav_put_handler(ngx_http_request_t *r); +static void *ngx_http_dav_create_loc_conf(ngx_conf_t *cf); +static char *ngx_http_dav_merge_loc_conf(ngx_conf_t *cf, + void *parent, void *child); +static ngx_int_t ngx_http_dav_init(ngx_cycle_t *cycle); + + +static ngx_conf_bitmask_t ngx_http_dav_methods_mask[] = { + { ngx_string("off"), NGX_HTTP_DAV_OFF }, + { ngx_string("put"), NGX_HTTP_PUT }, + { ngx_string("delete"), NGX_HTTP_DELETE }, + { ngx_null_string, 0 } +}; + + +static ngx_command_t ngx_http_dav_commands[] = { + + { ngx_string("dav_methods"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, + ngx_conf_set_bitmask_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_dav_loc_conf_t, methods), + &ngx_http_dav_methods_mask }, + + ngx_null_command +}; + + +ngx_http_module_t ngx_http_dav_module_ctx = { + NULL, /* preconfiguration */ + NULL, /* postconfiguration */ + + NULL, /* create main configuration */ + NULL, /* init main configuration */ + + NULL, /* create server configuration */ + NULL, /* merge server configuration */ + + ngx_http_dav_create_loc_conf, /* create location configuration */ + ngx_http_dav_merge_loc_conf /* merge location configuration */ +}; + + +ngx_module_t ngx_http_dav_module = { + NGX_MODULE_V1, + &ngx_http_dav_module_ctx, /* module context */ + ngx_http_dav_commands, /* module directives */ + NGX_HTTP_MODULE, /* module type */ + NULL, /* init master */ + ngx_http_dav_init, /* init module */ + NULL, /* init process */ + NULL, /* init thread */ + NULL, /* exit thread */ + NULL, /* exit process */ + NULL, /* exit master */ + NGX_MODULE_V1_PADDING +}; + + +static ngx_int_t +ngx_http_dav_handler(ngx_http_request_t *r) +{ + ngx_int_t rc; + ngx_str_t path; + ngx_http_dav_loc_conf_t *dlcf; + + /* TODO: Win32 */ + if (r->zero_in_uri) { + return NGX_DECLINED; + } + + dlcf = ngx_http_get_module_loc_conf(r, ngx_http_dav_module); + + if (!(r->method & dlcf->methods)) { + return NGX_DECLINED; + } + + switch (r->method) { + + case NGX_HTTP_PUT: + + if (r->uri.data[r->uri.len - 1] == '/') { + return NGX_DECLINED; + } + + r->request_body_in_file_only = 1; + r->request_body_in_persistent_file = 1; + r->request_body_delete_incomplete_file = 1; + r->request_body_file_group_access = 1; + + rc = ngx_http_read_client_request_body(r, ngx_http_dav_put_handler); + + if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { + return rc; + } + + return NGX_DONE; + + case NGX_HTTP_DELETE: + + if (r->uri.data[r->uri.len - 1] == '/') { + return NGX_DECLINED; + } + + ngx_http_map_uri_to_path(r, &path, 0); + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http delete filename: \"%s\"", path.data); + + if (ngx_delete_file(path.data) == NGX_FILE_ERROR) { + ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno, + ngx_delete_file_n " \"%s\" failed", path.data); + + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + return NGX_HTTP_NO_CONTENT; + } + + return NGX_DECLINED; +} + + +static void +ngx_http_dav_put_handler(ngx_http_request_t *r) +{ + u_char *location; + ngx_err_t err; + ngx_str_t *temp, path; + ngx_uint_t status; + ngx_file_info_t fi; + ngx_http_core_loc_conf_t *clcf; + + ngx_http_map_uri_to_path(r, &path, 0); + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http put filename: \"%s\"", path.data); + + temp = &r->request_body->temp_file->file.name; + + if (ngx_file_info(path.data, &fi) == -1) { + status = NGX_HTTP_CREATED; + + } else { + status = NGX_HTTP_NO_CONTENT; + } + + if (ngx_rename_file(temp->data, path.data) != NGX_FILE_ERROR) { + goto ok; + } + + err = ngx_errno; + +#if (NGX_WIN32) + + if (err == NGX_EEXIST) { + if (ngx_win32_rename_file(temp, &path, r->pool) != NGX_ERROR) { + + if (ngx_rename_file(temp->data, path.data) != NGX_FILE_ERROR) { + goto ok; + } + } + + err = ngx_errno; + } + +#endif + + ngx_log_error(NGX_LOG_CRIT, r->connection->log, err, + ngx_rename_file_n " \"%s\" failed", path.data); + + ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + +ok: + + if (status == NGX_HTTP_CREATED) { + + r->headers_out.location = ngx_palloc(r->pool, sizeof(ngx_table_elt_t)); + if (r->headers_out.location == NULL) { + ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + + if (!clcf->alias && clcf->root_lengths == NULL) { + location = path.data + clcf->root.len; + + } else { + location = ngx_palloc(r->pool, r->uri.len); + if (location == NULL) { + ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + + ngx_memcpy(location, r->uri.data, r->uri.len); + } + + /* + * we do not need to set the r->headers_out.location->hash and + * r->headers_out.location->key fields + */ + + r->headers_out.location->value.len = r->uri.len; + r->headers_out.location->value.data = location; + + } + + r->headers_out.status = status; + r->header_only = 1; + + ngx_http_finalize_request(r, ngx_http_send_header(r)); + return; +} + + +static void * +ngx_http_dav_create_loc_conf(ngx_conf_t *cf) +{ + ngx_http_dav_loc_conf_t *conf; + + conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_dav_loc_conf_t)); + if (conf == NULL) { + return NGX_CONF_ERROR; + } + + /* + * set by ngx_pcalloc(): + * + * conf->methods = 0; + */ + + return conf; +} + + +static char * +ngx_http_dav_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) +{ + ngx_http_dav_loc_conf_t *prev = parent; + ngx_http_dav_loc_conf_t *conf = child; + + ngx_conf_merge_bitmask_value(conf->methods, prev->methods, + (NGX_CONF_BITMASK_SET|NGX_HTTP_DAV_OFF)); + + return NGX_CONF_OK; +} + + +static ngx_int_t +ngx_http_dav_init(ngx_cycle_t *cycle) +{ + ngx_http_handler_pt *h; + ngx_http_core_main_conf_t *cmcf; + + cmcf = ngx_http_cycle_get_module_main_conf(cycle, ngx_http_core_module); + + h = ngx_array_push(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers); + if (h == NULL) { + return NGX_ERROR; + } + + *h = ngx_http_dav_handler; + + return NGX_OK; +} diff --git a/src/http/modules/ngx_http_log_module.c b/src/http/modules/ngx_http_log_module.c index 9436e5983..07ac113a4 100644 --- a/src/http/modules/ngx_http_log_module.c +++ b/src/http/modules/ngx_http_log_module.c @@ -23,6 +23,7 @@ typedef struct { typedef struct { ngx_open_file_t *file; + time_t disk_full_time; ngx_array_t *ops; /* array of ngx_http_log_op_t */ } ngx_http_log_t; @@ -253,6 +254,17 @@ ngx_http_log_handler(ngx_http_request_t *r) log = lcf->logs->elts; for (l = 0; l < lcf->logs->nelts; l++) { + if (ngx_time() == log[l].disk_full_time) { + + /* + * On FreeBSD writing to a full filesystem with enabled softupdates + * may block process for much longer time than writing to non-full + * filesystem, so we skip writing the log for one second. + */ + + continue; + } + len = 0; op = log[l].ops->elts; for (i = 0; i < log[l].ops->nelts; i++) { @@ -272,7 +284,13 @@ ngx_http_log_handler(ngx_http_request_t *r) if (len > (size_t) (file->last - file->pos)) { - ngx_write_fd(file->fd, file->buffer, file->pos - file->buffer); + if (ngx_write_fd(file->fd, file->buffer, + file->pos - file->buffer) + == -1 + && ngx_errno == NGX_ENOSPC) + { + log[l].disk_full_time = ngx_time(); + } file->pos = file->buffer; } @@ -306,7 +324,11 @@ ngx_http_log_handler(ngx_http_request_t *r) ngx_linefeed(p); - ngx_write_fd(file->fd, line, p - line); + if (ngx_write_fd(file->fd, line, p - line) == -1 + && ngx_errno == NGX_ENOSPC) + { + log[l].disk_full_time = ngx_time(); + } } return NGX_OK; @@ -1017,6 +1039,8 @@ ngx_http_log_set_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) return NGX_CONF_ERROR; } + log->disk_full_time = 0; + if (cf->args->nelts >= 3) { name = value[2]; diff --git a/src/http/modules/perl/nginx.xs b/src/http/modules/perl/nginx.xs index 7e2cec30e..735cc377b 100644 --- a/src/http/modules/perl/nginx.xs +++ b/src/http/modules/perl/nginx.xs @@ -13,6 +13,20 @@ #include "XSUB.h" +#define ngx_http_perl_set_request(r) \ + r = INT2PTR(ngx_http_request_t *, SvIV((SV *) SvRV(ST(0)))) + + +#define ngx_http_perl_set_targ(p, len, z) \ + \ + sv_upgrade(TARG, SVt_PV); \ + SvPOK_on(TARG); \ + SvPV_set(TARG, (char *) p); \ + SvLEN_set(TARG, len + z); \ + SvCUR_set(TARG, len); \ + SvFAKE_on(TARG); \ + SvREADONLY_on(TARG); \ + static ngx_int_t ngx_http_perl_sv2str(pTHX_ ngx_http_request_t *r, ngx_str_t *s, SV *sv) @@ -79,15 +93,14 @@ ngx_http_perl_output(ngx_http_request_t *r, ngx_buf_t *b) MODULE = nginx PACKAGE = nginx -int +void send_http_header(r, ...) - nginx r - - PREINIT: + CODE: - SV *sv; + ngx_http_request_t *r; + SV *sv; - CODE: + ngx_http_perl_set_request(r); if (r->headers_out.status == 0) { r->headers_out.status = NGX_HTTP_OK; @@ -99,127 +112,104 @@ send_http_header(r, ...) if (ngx_http_perl_sv2str(aTHX_ r, &r->headers_out.content_type, sv) != NGX_OK) { - RETVAL = NGX_ERROR; - goto done; + XSRETURN_EMPTY; } } else { if (r->headers_out.content_type.len == 0) { if (ngx_http_set_content_type(r) != NGX_OK) { - RETVAL = NGX_ERROR; - goto done; + XSRETURN_EMPTY; } } } - RETVAL = ngx_http_send_header(r); + (void) ngx_http_send_header(r); - done: - - OUTPUT: - RETVAL - -int +void header_only(r) - nginx r - CODE: - RETVAL = r->header_only; - - OUTPUT: - RETVAL + dXSTARG; + ngx_http_request_t *r; -# The returning "char *" is more quickly than creating SV, because SV returned -# from XS is never used as permanent storage. Even in simple case: -# "$uri = $r->uri" the SV returned by $r->uri is copied to $uri's SV. + ngx_http_perl_set_request(r); -char * -uri(r, ...) - nginx r + sv_upgrade(TARG, SVt_IV); + sv_setiv(TARG, r->header_only); - CODE: + ST(0) = TARG; - if (items != 1) { - croak("$r->uri(text) is not implemented"); - } - RETVAL = ngx_palloc(r->pool, r->uri.len + 1); - if (RETVAL == NULL) { - XSRETURN_UNDEF; - } +void +uri(r) + CODE: - ngx_cpystrn((u_char *) RETVAL, r->uri.data, r->uri.len + 1); + dXSTARG; + ngx_http_request_t *r; - OUTPUT: - RETVAL + ngx_http_perl_set_request(r); + ngx_http_perl_set_targ(r->uri.data, r->uri.len, 0); + ST(0) = TARG; -char * -args(r, ...) - nginx r +void +args(r) CODE: - if (items != 1) { - croak("$r->args(text) is not implemented"); - } - - RETVAL = ngx_palloc(r->pool, r->args.len + 1); - if (RETVAL == NULL) { - XSRETURN_UNDEF; - } + dXSTARG; + ngx_http_request_t *r; - ngx_cpystrn((u_char *) RETVAL, r->args.data, r->args.len + 1); + ngx_http_perl_set_request(r); + ngx_http_perl_set_targ(r->args.data, r->args.len, 0); - OUTPUT: - RETVAL + ST(0) = TARG; -char * +void request_method(r) - nginx r - CODE: - RETVAL = ngx_palloc(r->pool, r->method_name.len + 1); - if (RETVAL == NULL) { - XSRETURN_UNDEF; - } + dXSTARG; + ngx_http_request_t *r; - ngx_cpystrn((u_char *) RETVAL, r->method_name.data, r->method_name.len + 1); + ngx_http_perl_set_request(r); + ngx_http_perl_set_targ(r->method_name.data, r->method_name.len, 0); - OUTPUT: - RETVAL + ST(0) = TARG; -char * +void remote_addr(r) - nginx r - CODE: - RETVAL = (char *) r->connection->addr_text.data; + dXSTARG; + ngx_http_request_t *r; + + ngx_http_perl_set_request(r); + ngx_http_perl_set_targ(r->connection->addr_text.data, + r->connection->addr_text.len, 1); - OUTPUT: - RETVAL + ST(0) = TARG; -char * +void header_in(r, key) - nginx r - SV *key + CODE: - PREINIT: + dXSTARG; + ngx_http_request_t *r; + SV *key; + u_char *p; + STRLEN len; + ngx_uint_t i; + ngx_list_part_t *part; + ngx_table_elt_t *header; - u_char *p; - STRLEN len; - ngx_uint_t i; - ngx_list_part_t *part; - ngx_table_elt_t *header; + ngx_http_perl_set_request(r); - CODE: + key = ST(1); if (SvROK(key) && SvTYPE(SvRV(key)) == SVt_PV) { key = SvRV(key); @@ -248,7 +238,7 @@ header_in(r, key) continue; } - RETVAL = (char *) header[i].value.data; + ngx_http_perl_set_targ(header[i].value.data, header[i].value.len, 0); goto done; } @@ -257,73 +247,80 @@ header_in(r, key) done: - OUTPUT: - RETVAL + ST(0) = TARG; -SV * +void request_body(r) - nginx r - - PREINIT: - - STRLEN len; - ngx_chain_t *cl; - CODE: - len = 0; + dXSTARG; + ngx_http_request_t *r; + size_t len; - for (cl = r->request_body->bufs; cl; cl = cl->next) { - if (cl->buf->in_file) { - XSRETURN_UNDEF; - } + ngx_http_perl_set_request(r); - len += cl->buf->last - cl->buf->pos; + if (r->request_body->temp_file || r->request_body->bufs == NULL) { + XSRETURN_UNDEF; } + len = r->request_body->bufs->buf->last - r->request_body->bufs->buf->pos; + if (len == 0) { XSRETURN_UNDEF; } - RETVAL = newSV(len); + ngx_http_perl_set_targ(r->request_body->bufs->buf->pos, len, 0); + + ST(0) = TARG; - for (cl = r->request_body->bufs; cl; cl = cl->next) { - sv_catpvn(RETVAL, cl->buf->pos, cl->buf->last - cl->buf->pos); + +void +request_body_file(r) + CODE: + + dXSTARG; + ngx_http_request_t *r; + + ngx_http_perl_set_request(r); + + if (r->request_body->temp_file == NULL) { + XSRETURN_UNDEF; } - OUTPUT: - RETVAL + ngx_http_perl_set_targ(r->request_body->temp_file->file.name.data, + r->request_body->temp_file->file.name.len, 1); + ST(0) = TARG; -int + +void header_out(r, key, value) - nginx r - SV *key - SV *value + CODE: - PREINIT: + ngx_http_request_t *r; + SV *key; + SV *value; + ngx_table_elt_t *header; - ngx_table_elt_t *header; + ngx_http_perl_set_request(r); - CODE: + key = ST(1); + value = ST(2); header = ngx_list_push(&r->headers_out.headers); if (header == NULL) { - RETVAL = NGX_ERROR; - goto done; + XSRETURN_EMPTY; } header->hash = 1; if (ngx_http_perl_sv2str(aTHX_ r, &header->key, key) != NGX_OK) { - RETVAL = NGX_ERROR; - goto done; + XSRETURN_EMPTY; } if (ngx_http_perl_sv2str(aTHX_ r, &header->value, value) != NGX_OK) { - RETVAL = NGX_ERROR; - goto done; + XSRETURN_EMPTY; } if (header->key.len == sizeof("Content-Length") - 1 @@ -335,62 +332,51 @@ header_out(r, key, value) r->headers_out.content_length = header; } - RETVAL = NGX_OK; - - done: - - OUTPUT: - RETVAL + XSRETURN_EMPTY; -char * +void filename(r) - nginx r - - PREINIT: + CODE: - ngx_str_t path; + dXSTARG; + ngx_http_request_t *r; ngx_http_perl_ctx_t *ctx; - CODE: + ngx_http_perl_set_request(r); ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module); - if (ctx->filename) { + if (ctx->filename.data) { goto done; } - if (ngx_http_map_uri_to_path(r, &path, 0) == NULL) { + if (ngx_http_map_uri_to_path(r, &ctx->filename, 0) == NULL) { XSRETURN_UNDEF; } - ctx->filename = (char *) path.data; - - sv_setpv(PL_statname, ctx->filename); + ctx->filename.len--; + sv_setpv(PL_statname, (char *) ctx->filename.data); done: - RETVAL = ctx->filename; + ngx_http_perl_set_targ(ctx->filename.data, ctx->filename.len, 1); - OUTPUT: - RETVAL + ST(0) = TARG; -int +void print(r, ...) - nginx r - - PREINIT: - - SV *sv; - int i; - u_char *p; - size_t size; - STRLEN len; - ngx_buf_t *b; - CODE: - RETVAL = NGX_OK; + ngx_http_request_t *r; + SV *sv; + int i; + u_char *p; + size_t size; + STRLEN len; + ngx_buf_t *b; + + ngx_http_perl_set_request(r); if (items == 2) { @@ -410,13 +396,12 @@ print(r, ...) p = (u_char *) SvPV(sv, len); if (len == 0) { - goto done; + XSRETURN_EMPTY; } b = ngx_calloc_buf(r->pool); if (b == NULL) { - RETVAL = NGX_ERROR; - goto done; + XSRETURN_EMPTY; } b->memory = 1; @@ -451,13 +436,12 @@ print(r, ...) } if (size == 0) { - goto done; + XSRETURN_EMPTY; } b = ngx_create_temp_buf(r->pool, size); if (b == NULL) { - RETVAL = NGX_ERROR; - goto done; + XSRETURN_EMPTY; } for (i = 1; i < items; i++) { @@ -473,51 +457,49 @@ print(r, ...) out: - RETVAL = ngx_http_perl_output(r, b); - - done: + (void) ngx_http_perl_output(r, b); - OUTPUT: - RETVAL + XSRETURN_EMPTY; -int +void sendfile(r, filename, offset = -1, bytes = 0) - nginx r - char *filename + CODE: + + ngx_http_request_t *r; + char *filename; int offset; size_t bytes; - - PREINIT: - ngx_fd_t fd; ngx_buf_t *b; ngx_file_info_t fi; ngx_pool_cleanup_t *cln; ngx_pool_cleanup_file_t *clnf; - CODE: + ngx_http_perl_set_request(r); + + filename = SvPV_nolen(ST(1)); if (filename == NULL) { croak("sendfile(): NULL filename"); } + offset = items < 3 ? -1 : SvIV(ST(2)); + bytes = items < 4 ? 0 : SvIV(ST(3)); + b = ngx_calloc_buf(r->pool); if (b == NULL) { - RETVAL = NGX_ERROR; - goto done; + XSRETURN_EMPTY; } b->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t)); if (b->file == NULL) { - RETVAL = NGX_ERROR; - goto done; + XSRETURN_EMPTY; } cln = ngx_pool_cleanup_add(r->pool, sizeof(ngx_pool_cleanup_file_t)); if (cln == NULL) { - RETVAL = NGX_ERROR; - goto done; + XSRETURN_EMPTY; } fd = ngx_open_file((u_char *) filename, NGX_FILE_RDONLY, NGX_FILE_OPEN); @@ -525,8 +507,7 @@ sendfile(r, filename, offset = -1, bytes = 0) if (fd == NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno, ngx_open_file_n " \"%s\" failed", filename); - RETVAL = NGX_ERROR; - goto done; + XSRETURN_EMPTY; } if (offset == -1) { @@ -543,9 +524,7 @@ sendfile(r, filename, offset = -1, bytes = 0) ngx_close_file_n " \"%s\" failed", filename); } - RETVAL = NGX_ERROR; - goto done; - + XSRETURN_EMPTY; } bytes = ngx_file_size(&fi) - offset; @@ -566,53 +545,46 @@ sendfile(r, filename, offset = -1, bytes = 0) b->file->fd = fd; b->file->log = r->connection->log; - RETVAL = ngx_http_perl_output(r, b); + (void) ngx_http_perl_output(r, b); - done: + XSRETURN_EMPTY; - OUTPUT: - RETVAL - -int +void rflush(r) - nginx r - - PREINIT: + CODE: - ngx_buf_t *b; + ngx_http_request_t *r; + ngx_buf_t *b; - CODE: + ngx_http_perl_set_request(r); b = ngx_calloc_buf(r->pool); if (b == NULL) { - RETVAL = NGX_ERROR; - goto done; + XSRETURN_EMPTY; } b->flush = 1; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "$r->rflush"); - RETVAL = ngx_http_perl_output(r, b); + (void) ngx_http_perl_output(r, b); - done: - - OUTPUT: - RETVAL + XSRETURN_EMPTY; void internal_redirect(r, uri) - nginx r - SV *uri - - PREINIT: + CODE: + ngx_http_request_t *r; + SV *uri; ngx_uint_t i; ngx_http_perl_ctx_t *ctx; - CODE: + ngx_http_perl_set_request(r); + + uri = ST(1); ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module); @@ -632,32 +604,35 @@ internal_redirect(r, uri) } -char * +void unescape(r, text, type = 0) - nginx r - SV *text - int type + CODE: - PREINIT: + dXSTARG; + ngx_http_request_t *r; + SV *text; + int type; + u_char *p, *dst, *src; + STRLEN len; - u_char *p, *dst, *src; - STRLEN n; + ngx_http_perl_set_request(r); - CODE: + text = ST(1); - src = (u_char *) SvPV(text, n); + src = (u_char *) SvPV(text, len); - p = ngx_palloc(r->pool, n + 1); + p = ngx_palloc(r->pool, len + 1); if (p == NULL) { XSRETURN_UNDEF; } dst = p; - ngx_unescape_uri(&dst, &src, n, (ngx_uint_t) type); + type = items < 3 ? 0 : SvIV(ST(2)); + + ngx_unescape_uri(&dst, &src, len, (ngx_uint_t) type); *dst = '\0'; - RETVAL = (char *) p; + ngx_http_perl_set_targ(p, dst - p, 1); - OUTPUT: - RETVAL + ST(0) = TARG; diff --git a/src/http/modules/perl/ngx_http_perl_module.c b/src/http/modules/perl/ngx_http_perl_module.c index e453dc38b..84de2627a 100644 --- a/src/http/modules/perl/ngx_http_perl_module.c +++ b/src/http/modules/perl/ngx_http_perl_module.c @@ -165,10 +165,14 @@ static ngx_http_ssi_command_t ngx_http_perl_ssi_command = { #endif +static HV *nginx_stash; + static void ngx_http_perl_xs_init(pTHX) { newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, __FILE__); + + nginx_stash = gv_stashpv("nginx", TRUE); } @@ -182,6 +186,9 @@ ngx_http_perl_handler(ngx_http_request_t *r) return NGX_HTTP_NOT_FOUND; } + r->request_body_in_single_buf = 1; + r->request_body_in_persistent_file = 1; + rc = ngx_http_read_client_request_body(r, ngx_http_perl_handle_request); if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { @@ -259,7 +266,7 @@ ngx_http_perl_handle_request(ngx_http_request_t *r) uri.len = 0; } - ctx->filename = NULL; + ctx->filename.data = NULL; ctx->redirect_uri.len = 0; if (uri.len) { @@ -332,7 +339,7 @@ ngx_http_perl_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, v->not_found = 1; } - ctx->filename = NULL; + ctx->filename.data = NULL; ctx->redirect_uri.len = 0; return rc; @@ -409,7 +416,7 @@ ngx_http_perl_ssi(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ssi_ctx, ngx_http_perl_free_interpreter(pmcf, ctx->perl); - ctx->filename = NULL; + ctx->filename.data = NULL; ctx->redirect_uri.len = 0; ctx->ssi = NULL; @@ -631,8 +638,7 @@ ngx_http_perl_call_handler(pTHX_ ngx_http_request_t *r, SV *sub, PUSHMARK(sp); - sv = sv_newmortal(); - sv_setref_pv(sv, "nginx", r); + sv = sv_2mortal(sv_bless(newRV_noinc(newSViv(PTR2IV(r))), nginx_stash)); XPUSHs(sv); if (args) { diff --git a/src/http/modules/perl/ngx_http_perl_module.h b/src/http/modules/perl/ngx_http_perl_module.h index 1bc3852e7..1609c478b 100644 --- a/src/http/modules/perl/ngx_http_perl_module.h +++ b/src/http/modules/perl/ngx_http_perl_module.h @@ -21,8 +21,7 @@ typedef ngx_http_request_t *nginx; typedef struct { PerlInterpreter *perl; - char *filename; - + ngx_str_t filename; ngx_str_t redirect_uri; ngx_str_t redirect_args; @@ -45,7 +44,7 @@ extern ngx_module_t ngx_http_perl_module; #endif -extern void boot_DynaLoader (pTHX_ CV* cv); +extern void boot_DynaLoader(pTHX_ CV* cv); #endif /* _NGX_HTTP_PERL_MODULE_H_INCLUDED_ */ |