Mercurial > hg > nginx-vendor-current
diff src/http/modules/perl/nginx.xs @ 182:13710a1813ad NGINX_0_3_38
nginx 0.3.38
*) Feature: the ngx_http_dav_module.
*) Change: the ngx_http_perl_module optimizations.
Thanks to Sergey Skvortsov.
*) Feature: the ngx_http_perl_module supports the $r->request_body_file
method.
*) Feature: the "client_body_in_file_only" directive.
*) Workaround: now on disk overflow nginx tries to write access logs
once a second only.
Thanks to Anton Yuzhaninov and Maxim Dounin.
*) Bugfix: now the "limit_rate" directive more precisely limits rate if
rate is more than 100 Kbyte/s.
Thanks to ForJest.
*) Bugfix: now the IMAP/POP3 proxy escapes the "\r" and "\n" symbols in
login and password to pass authorization server.
Thanks to Maxim Dounin.
author | Igor Sysoev <http://sysoev.ru> |
---|---|
date | Fri, 14 Apr 2006 00:00:00 +0400 |
parents | 4cd3e70c4d60 |
children | fa32d59d9a15 |
line wrap: on
line diff
--- 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 MODULE = nginx PACKAGE = nginx -int +void send_http_header(r, ...) - nginx r + CODE: - PREINIT: + ngx_http_request_t *r; + SV *sv; - 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); - - done: - - OUTPUT: - RETVAL - - -int -header_only(r) - nginx r - - CODE: - RETVAL = r->header_only; - - OUTPUT: - RETVAL + (void) ngx_http_send_header(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. - -char * -uri(r, ...) - nginx r - +void +header_only(r) CODE: - if (items != 1) { - croak("$r->uri(text) is not implemented"); - } + dXSTARG; + ngx_http_request_t *r; + + ngx_http_perl_set_request(r); - RETVAL = ngx_palloc(r->pool, r->uri.len + 1); - if (RETVAL == NULL) { - XSRETURN_UNDEF; - } + sv_upgrade(TARG, SVt_IV); + sv_setiv(TARG, r->header_only); - ngx_cpystrn((u_char *) RETVAL, r->uri.data, r->uri.len + 1); - - OUTPUT: - RETVAL + ST(0) = TARG; -char * -args(r, ...) - nginx r +void +uri(r) + CODE: + + dXSTARG; + ngx_http_request_t *r; + ngx_http_perl_set_request(r); + ngx_http_perl_set_targ(r->uri.data, r->uri.len, 0); + + ST(0) = TARG; + + +void +args(r) CODE: - if (items != 1) { - croak("$r->args(text) is not implemented"); - } + dXSTARG; + ngx_http_request_t *r; - RETVAL = ngx_palloc(r->pool, r->args.len + 1); - if (RETVAL == NULL) { - XSRETURN_UNDEF; - } + ngx_http_perl_set_request(r); + ngx_http_perl_set_targ(r->args.data, r->args.len, 0); - ngx_cpystrn((u_char *) RETVAL, r->args.data, r->args.len + 1); - - OUTPUT: - RETVAL + ST(0) = TARG; -char * +void request_method(r) - nginx r + CODE: + + dXSTARG; + ngx_http_request_t *r; + ngx_http_perl_set_request(r); + ngx_http_perl_set_targ(r->method_name.data, r->method_name.len, 0); + + ST(0) = TARG; + + +void +remote_addr(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->connection->addr_text.data, + r->connection->addr_text.len, 1); - OUTPUT: - RETVAL + ST(0) = TARG; -char * -remote_addr(r) - nginx r - +void +header_in(r, key) CODE: - RETVAL = (char *) r->connection->addr_text.data; - - OUTPUT: - RETVAL - + 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; -char * -header_in(r, key) - nginx r - SV *key - - PREINIT: + ngx_http_perl_set_request(r); - u_char *p; - STRLEN len; - ngx_uint_t i; - ngx_list_part_t *part; - ngx_table_elt_t *header; - - 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; + + ngx_http_perl_set_request(r); - for (cl = r->request_body->bufs; cl; cl = cl->next) { - if (cl->buf->in_file) { - XSRETURN_UNDEF; - } + if (r->request_body->temp_file || r->request_body->bufs == NULL) { + XSRETURN_UNDEF; + } - len += cl->buf->last - cl->buf->pos; - } + 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); - for (cl = r->request_body->bufs; cl; cl = cl->next) { - sv_catpvn(RETVAL, cl->buf->pos, cl->buf->last - cl->buf->pos); - } - - OUTPUT: - RETVAL + ST(0) = TARG; -int -header_out(r, key, value) - nginx r - SV *key - SV *value +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; + } + + ngx_http_perl_set_targ(r->request_body->temp_file->file.name.data, + r->request_body->temp_file->file.name.len, 1); - PREINIT: + ST(0) = TARG; + + +void +header_out(r, key, value) + CODE: - ngx_table_elt_t *header; + ngx_http_request_t *r; + SV *key; + SV *value; + ngx_table_elt_t *header; - CODE: + ngx_http_perl_set_request(r); + + 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 + CODE: - PREINIT: - - 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); + (void) ngx_http_perl_output(r, b); - done: - - 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 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 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 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: - - OUTPUT: - RETVAL + XSRETURN_EMPTY; -int +void rflush(r) - nginx r + CODE: - PREINIT: + ngx_http_request_t *r; + ngx_buf_t *b; - 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 + CODE: - PREINIT: - + 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 - - PREINIT: - - u_char *p, *dst, *src; - STRLEN n; - CODE: - src = (u_char *) SvPV(text, n); + dXSTARG; + ngx_http_request_t *r; + SV *text; + int type; + u_char *p, *dst, *src; + STRLEN len; - p = ngx_palloc(r->pool, n + 1); + ngx_http_perl_set_request(r); + + text = ST(1); + + src = (u_char *) SvPV(text, len); + + 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;