diff options
Diffstat (limited to 'src/http/modules/perl')
-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 |
3 files changed, 202 insertions, 222 deletions
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_ */ |