Annotation of embedaddon/nginx/src/http/modules/perl/nginx.xs, revision 1.1
1.1 ! misho 1:
! 2: /*
! 3: * Copyright (C) Igor Sysoev
! 4: * Copyright (C) Nginx, Inc.
! 5: */
! 6:
! 7:
! 8: #define PERL_NO_GET_CONTEXT
! 9:
! 10: #include <ngx_config.h>
! 11: #include <ngx_core.h>
! 12: #include <ngx_http.h>
! 13: #include <ngx_http_perl_module.h>
! 14:
! 15: #include "XSUB.h"
! 16:
! 17:
! 18: #define ngx_http_perl_set_request(r) \
! 19: r = INT2PTR(ngx_http_request_t *, SvIV((SV *) SvRV(ST(0))))
! 20:
! 21:
! 22: #define ngx_http_perl_set_targ(p, len) \
! 23: \
! 24: SvUPGRADE(TARG, SVt_PV); \
! 25: SvPOK_on(TARG); \
! 26: sv_setpvn(TARG, (char *) p, len)
! 27:
! 28:
! 29: static ngx_int_t
! 30: ngx_http_perl_sv2str(pTHX_ ngx_http_request_t *r, ngx_str_t *s, SV *sv)
! 31: {
! 32: u_char *p;
! 33: STRLEN len;
! 34:
! 35: if (SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PV) {
! 36: sv = SvRV(sv);
! 37: }
! 38:
! 39: p = (u_char *) SvPV(sv, len);
! 40:
! 41: s->len = len;
! 42:
! 43: if (SvREADONLY(sv) && SvPOK(sv)) {
! 44: s->data = p;
! 45:
! 46: ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
! 47: "perl sv2str: %08XD \"%V\"", sv->sv_flags, s);
! 48:
! 49: return NGX_OK;
! 50: }
! 51:
! 52: s->data = ngx_pnalloc(r->pool, len);
! 53: if (s->data == NULL) {
! 54: return NGX_ERROR;
! 55: }
! 56:
! 57: ngx_memcpy(s->data, p, len);
! 58:
! 59: ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
! 60: "perl sv2str: %08XD \"%V\"", sv->sv_flags, s);
! 61:
! 62: return NGX_OK;
! 63: }
! 64:
! 65:
! 66: static ngx_int_t
! 67: ngx_http_perl_output(ngx_http_request_t *r, ngx_buf_t *b)
! 68: {
! 69: ngx_chain_t out;
! 70: #if (NGX_HTTP_SSI)
! 71: ngx_chain_t *cl;
! 72: ngx_http_perl_ctx_t *ctx;
! 73:
! 74: ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module);
! 75:
! 76: if (ctx->ssi) {
! 77: cl = ngx_alloc_chain_link(r->pool);
! 78: if (cl == NULL) {
! 79: return NGX_ERROR;
! 80: }
! 81:
! 82: cl->buf = b;
! 83: cl->next = NULL;
! 84: *ctx->ssi->last_out = cl;
! 85: ctx->ssi->last_out = &cl->next;
! 86:
! 87: return NGX_OK;
! 88: }
! 89: #endif
! 90:
! 91: out.buf = b;
! 92: out.next = NULL;
! 93:
! 94: return ngx_http_output_filter(r, &out);
! 95: }
! 96:
! 97:
! 98: MODULE = nginx PACKAGE = nginx
! 99:
! 100:
! 101: void
! 102: status(r, code)
! 103: CODE:
! 104:
! 105: ngx_http_request_t *r;
! 106:
! 107: ngx_http_perl_set_request(r);
! 108:
! 109: r->headers_out.status = SvIV(ST(1));
! 110:
! 111: ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
! 112: "perl status: %d", r->headers_out.status);
! 113:
! 114: XSRETURN_UNDEF;
! 115:
! 116:
! 117: void
! 118: send_http_header(r, ...)
! 119: CODE:
! 120:
! 121: ngx_http_request_t *r;
! 122: SV *sv;
! 123:
! 124: ngx_http_perl_set_request(r);
! 125:
! 126: if (r->headers_out.status == 0) {
! 127: r->headers_out.status = NGX_HTTP_OK;
! 128: }
! 129:
! 130: if (items != 1) {
! 131: sv = ST(1);
! 132:
! 133: if (ngx_http_perl_sv2str(aTHX_ r, &r->headers_out.content_type, sv)
! 134: != NGX_OK)
! 135: {
! 136: XSRETURN_EMPTY;
! 137: }
! 138:
! 139: r->headers_out.content_type_len = r->headers_out.content_type.len;
! 140:
! 141: } else {
! 142: if (ngx_http_set_content_type(r) != NGX_OK) {
! 143: XSRETURN_EMPTY;
! 144: }
! 145: }
! 146:
! 147: (void) ngx_http_send_header(r);
! 148:
! 149:
! 150: void
! 151: header_only(r)
! 152: CODE:
! 153:
! 154: dXSTARG;
! 155: ngx_http_request_t *r;
! 156:
! 157: ngx_http_perl_set_request(r);
! 158:
! 159: sv_upgrade(TARG, SVt_IV);
! 160: sv_setiv(TARG, r->header_only);
! 161:
! 162: ST(0) = TARG;
! 163:
! 164:
! 165: void
! 166: uri(r)
! 167: CODE:
! 168:
! 169: dXSTARG;
! 170: ngx_http_request_t *r;
! 171:
! 172: ngx_http_perl_set_request(r);
! 173: ngx_http_perl_set_targ(r->uri.data, r->uri.len);
! 174:
! 175: ST(0) = TARG;
! 176:
! 177:
! 178: void
! 179: args(r)
! 180: CODE:
! 181:
! 182: dXSTARG;
! 183: ngx_http_request_t *r;
! 184:
! 185: ngx_http_perl_set_request(r);
! 186: ngx_http_perl_set_targ(r->args.data, r->args.len);
! 187:
! 188: ST(0) = TARG;
! 189:
! 190:
! 191: void
! 192: request_method(r)
! 193: CODE:
! 194:
! 195: dXSTARG;
! 196: ngx_http_request_t *r;
! 197:
! 198: ngx_http_perl_set_request(r);
! 199: ngx_http_perl_set_targ(r->method_name.data, r->method_name.len);
! 200:
! 201: ST(0) = TARG;
! 202:
! 203:
! 204: void
! 205: remote_addr(r)
! 206: CODE:
! 207:
! 208: dXSTARG;
! 209: ngx_http_request_t *r;
! 210:
! 211: ngx_http_perl_set_request(r);
! 212: ngx_http_perl_set_targ(r->connection->addr_text.data,
! 213: r->connection->addr_text.len);
! 214:
! 215: ST(0) = TARG;
! 216:
! 217:
! 218: void
! 219: header_in(r, key)
! 220: CODE:
! 221:
! 222: dXSTARG;
! 223: ngx_http_request_t *r;
! 224: SV *key;
! 225: u_char *p, *lowcase_key, *value, sep;
! 226: STRLEN len;
! 227: ssize_t size;
! 228: ngx_uint_t i, n, hash;
! 229: ngx_array_t *a;
! 230: ngx_list_part_t *part;
! 231: ngx_table_elt_t *h, **ph;
! 232: ngx_http_header_t *hh;
! 233: ngx_http_core_main_conf_t *cmcf;
! 234:
! 235: ngx_http_perl_set_request(r);
! 236:
! 237: key = ST(1);
! 238:
! 239: if (SvROK(key) && SvTYPE(SvRV(key)) == SVt_PV) {
! 240: key = SvRV(key);
! 241: }
! 242:
! 243: p = (u_char *) SvPV(key, len);
! 244:
! 245: /* look up hashed headers */
! 246:
! 247: lowcase_key = ngx_pnalloc(r->pool, len);
! 248: if (lowcase_key == NULL) {
! 249: XSRETURN_UNDEF;
! 250: }
! 251:
! 252: hash = ngx_hash_strlow(lowcase_key, p, len);
! 253:
! 254: cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
! 255:
! 256: hh = ngx_hash_find(&cmcf->headers_in_hash, hash, lowcase_key, len);
! 257:
! 258: if (hh) {
! 259:
! 260: if (hh->offset == offsetof(ngx_http_headers_in_t, cookies)) {
! 261: sep = ';';
! 262: goto multi;
! 263: }
! 264:
! 265: #if (NGX_HTTP_X_FORWARDED_FOR)
! 266: if (hh->offset == offsetof(ngx_http_headers_in_t, x_forwarded_for)) {
! 267: sep = ',';
! 268: goto multi;
! 269: }
! 270: #endif
! 271:
! 272: if (hh->offset) {
! 273:
! 274: ph = (ngx_table_elt_t **) ((char *) &r->headers_in + hh->offset);
! 275:
! 276: if (*ph) {
! 277: ngx_http_perl_set_targ((*ph)->value.data, (*ph)->value.len);
! 278:
! 279: goto done;
! 280: }
! 281:
! 282: XSRETURN_UNDEF;
! 283: }
! 284:
! 285: multi:
! 286:
! 287: /* Cookie, X-Forwarded-For */
! 288:
! 289: a = (ngx_array_t *) ((char *) &r->headers_in + hh->offset);
! 290:
! 291: n = a->nelts;
! 292:
! 293: if (n == 0) {
! 294: XSRETURN_UNDEF;
! 295: }
! 296:
! 297: ph = a->elts;
! 298:
! 299: if (n == 1) {
! 300: ngx_http_perl_set_targ((*ph)->value.data, (*ph)->value.len);
! 301:
! 302: goto done;
! 303: }
! 304:
! 305: size = - (ssize_t) (sizeof("; ") - 1);
! 306:
! 307: for (i = 0; i < n; i++) {
! 308: size += ph[i]->value.len + sizeof("; ") - 1;
! 309: }
! 310:
! 311: value = ngx_pnalloc(r->pool, size);
! 312: if (value == NULL) {
! 313: XSRETURN_UNDEF;
! 314: }
! 315:
! 316: p = value;
! 317:
! 318: for (i = 0; /* void */ ; i++) {
! 319: p = ngx_copy(p, ph[i]->value.data, ph[i]->value.len);
! 320:
! 321: if (i == n - 1) {
! 322: break;
! 323: }
! 324:
! 325: *p++ = sep; *p++ = ' ';
! 326: }
! 327:
! 328: ngx_http_perl_set_targ(value, size);
! 329:
! 330: goto done;
! 331: }
! 332:
! 333: /* iterate over all headers */
! 334:
! 335: part = &r->headers_in.headers.part;
! 336: h = part->elts;
! 337:
! 338: for (i = 0; /* void */ ; i++) {
! 339:
! 340: if (i >= part->nelts) {
! 341: if (part->next == NULL) {
! 342: break;
! 343: }
! 344:
! 345: part = part->next;
! 346: h = part->elts;
! 347: i = 0;
! 348: }
! 349:
! 350: if (len != h[i].key.len
! 351: || ngx_strcasecmp(p, h[i].key.data) != 0)
! 352: {
! 353: continue;
! 354: }
! 355:
! 356: ngx_http_perl_set_targ(h[i].value.data, h[i].value.len);
! 357:
! 358: goto done;
! 359: }
! 360:
! 361: XSRETURN_UNDEF;
! 362:
! 363: done:
! 364:
! 365: ST(0) = TARG;
! 366:
! 367:
! 368: void
! 369: has_request_body(r, next)
! 370: CODE:
! 371:
! 372: dXSTARG;
! 373: ngx_http_request_t *r;
! 374: ngx_http_perl_ctx_t *ctx;
! 375:
! 376: ngx_http_perl_set_request(r);
! 377:
! 378: if (r->headers_in.content_length_n <= 0 && !r->headers_in.chunked) {
! 379: XSRETURN_UNDEF;
! 380: }
! 381:
! 382: ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module);
! 383: ctx->next = SvRV(ST(1));
! 384:
! 385: r->request_body_in_single_buf = 1;
! 386: r->request_body_in_persistent_file = 1;
! 387: r->request_body_in_clean_file = 1;
! 388:
! 389: if (r->request_body_in_file_only) {
! 390: r->request_body_file_log_level = 0;
! 391: }
! 392:
! 393: ngx_http_read_client_request_body(r, ngx_http_perl_handle_request);
! 394:
! 395: sv_upgrade(TARG, SVt_IV);
! 396: sv_setiv(TARG, 1);
! 397:
! 398: ST(0) = TARG;
! 399:
! 400:
! 401: void
! 402: request_body(r)
! 403: CODE:
! 404:
! 405: dXSTARG;
! 406: ngx_http_request_t *r;
! 407: u_char *p, *data;
! 408: size_t len;
! 409: ngx_buf_t *buf;
! 410: ngx_chain_t *cl;
! 411:
! 412: ngx_http_perl_set_request(r);
! 413:
! 414: if (r->request_body == NULL
! 415: || r->request_body->temp_file
! 416: || r->request_body->bufs == NULL)
! 417: {
! 418: XSRETURN_UNDEF;
! 419: }
! 420:
! 421: cl = r->request_body->bufs;
! 422: buf = cl->buf;
! 423:
! 424: if (cl->next == NULL) {
! 425: len = buf->last - buf->pos;
! 426: data = buf->pos;
! 427: goto done;
! 428: }
! 429:
! 430: len = buf->last - buf->pos;
! 431: cl = cl->next;
! 432:
! 433: for ( /* void */ ; cl; cl = cl->next) {
! 434: buf = cl->buf;
! 435: len += buf->last - buf->pos;
! 436: }
! 437:
! 438: p = ngx_pnalloc(r->pool, len);
! 439: if (p == NULL) {
! 440: XSRETURN_UNDEF;
! 441: }
! 442:
! 443: data = p;
! 444: cl = r->request_body->bufs;
! 445:
! 446: for ( /* void */ ; cl; cl = cl->next) {
! 447: buf = cl->buf;
! 448: p = ngx_cpymem(p, buf->pos, buf->last - buf->pos);
! 449: }
! 450:
! 451: done:
! 452:
! 453: if (len == 0) {
! 454: XSRETURN_UNDEF;
! 455: }
! 456:
! 457: ngx_http_perl_set_targ(data, len);
! 458:
! 459: ST(0) = TARG;
! 460:
! 461:
! 462: void
! 463: request_body_file(r)
! 464: CODE:
! 465:
! 466: dXSTARG;
! 467: ngx_http_request_t *r;
! 468:
! 469: ngx_http_perl_set_request(r);
! 470:
! 471: if (r->request_body == NULL || r->request_body->temp_file == NULL) {
! 472: XSRETURN_UNDEF;
! 473: }
! 474:
! 475: ngx_http_perl_set_targ(r->request_body->temp_file->file.name.data,
! 476: r->request_body->temp_file->file.name.len);
! 477:
! 478: ST(0) = TARG;
! 479:
! 480:
! 481: void
! 482: discard_request_body(r)
! 483: CODE:
! 484:
! 485: ngx_http_request_t *r;
! 486:
! 487: ngx_http_perl_set_request(r);
! 488:
! 489: ngx_http_discard_request_body(r);
! 490:
! 491:
! 492: void
! 493: header_out(r, key, value)
! 494: CODE:
! 495:
! 496: ngx_http_request_t *r;
! 497: SV *key;
! 498: SV *value;
! 499: ngx_table_elt_t *header;
! 500:
! 501: ngx_http_perl_set_request(r);
! 502:
! 503: key = ST(1);
! 504: value = ST(2);
! 505:
! 506: header = ngx_list_push(&r->headers_out.headers);
! 507: if (header == NULL) {
! 508: XSRETURN_EMPTY;
! 509: }
! 510:
! 511: header->hash = 1;
! 512:
! 513: if (ngx_http_perl_sv2str(aTHX_ r, &header->key, key) != NGX_OK) {
! 514: XSRETURN_EMPTY;
! 515: }
! 516:
! 517: if (ngx_http_perl_sv2str(aTHX_ r, &header->value, value) != NGX_OK) {
! 518: XSRETURN_EMPTY;
! 519: }
! 520:
! 521: if (header->key.len == sizeof("Content-Length") - 1
! 522: && ngx_strncasecmp(header->key.data, (u_char *) "Content-Length",
! 523: sizeof("Content-Length") - 1) == 0)
! 524: {
! 525: r->headers_out.content_length_n = (off_t) SvIV(value);
! 526: r->headers_out.content_length = header;
! 527: }
! 528:
! 529: if (header->key.len == sizeof("Content-Encoding") - 1
! 530: && ngx_strncasecmp(header->key.data, (u_char *) "Content-Encoding",
! 531: sizeof("Content-Encoding") - 1) == 0)
! 532: {
! 533: r->headers_out.content_encoding = header;
! 534: }
! 535:
! 536:
! 537: void
! 538: filename(r)
! 539: CODE:
! 540:
! 541: dXSTARG;
! 542: size_t root;
! 543: ngx_http_request_t *r;
! 544: ngx_http_perl_ctx_t *ctx;
! 545:
! 546: ngx_http_perl_set_request(r);
! 547:
! 548: ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module);
! 549: if (ctx->filename.data) {
! 550: goto done;
! 551: }
! 552:
! 553: if (ngx_http_map_uri_to_path(r, &ctx->filename, &root, 0) == NULL) {
! 554: XSRETURN_UNDEF;
! 555: }
! 556:
! 557: ctx->filename.len--;
! 558: sv_setpv(PL_statname, (char *) ctx->filename.data);
! 559:
! 560: done:
! 561:
! 562: ngx_http_perl_set_targ(ctx->filename.data, ctx->filename.len);
! 563:
! 564: ST(0) = TARG;
! 565:
! 566:
! 567: void
! 568: print(r, ...)
! 569: CODE:
! 570:
! 571: ngx_http_request_t *r;
! 572: SV *sv;
! 573: int i;
! 574: u_char *p;
! 575: size_t size;
! 576: STRLEN len;
! 577: ngx_buf_t *b;
! 578:
! 579: ngx_http_perl_set_request(r);
! 580:
! 581: if (items == 2) {
! 582:
! 583: /*
! 584: * do zero copy for prolate single read-only SV:
! 585: * $r->print("some text\n");
! 586: */
! 587:
! 588: sv = ST(1);
! 589:
! 590: if (SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PV) {
! 591: sv = SvRV(sv);
! 592: }
! 593:
! 594: if (SvREADONLY(sv) && SvPOK(sv)) {
! 595:
! 596: p = (u_char *) SvPV(sv, len);
! 597:
! 598: if (len == 0) {
! 599: XSRETURN_EMPTY;
! 600: }
! 601:
! 602: b = ngx_calloc_buf(r->pool);
! 603: if (b == NULL) {
! 604: XSRETURN_EMPTY;
! 605: }
! 606:
! 607: b->memory = 1;
! 608: b->pos = p;
! 609: b->last = p + len;
! 610: b->start = p;
! 611: b->end = b->last;
! 612:
! 613: ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
! 614: "$r->print: read-only SV: %z", len);
! 615:
! 616: goto out;
! 617: }
! 618: }
! 619:
! 620: size = 0;
! 621:
! 622: for (i = 1; i < items; i++) {
! 623:
! 624: sv = ST(i);
! 625:
! 626: if (SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PV) {
! 627: sv = SvRV(sv);
! 628: }
! 629:
! 630: (void) SvPV(sv, len);
! 631:
! 632: ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
! 633: "$r->print: copy SV: %z", len);
! 634:
! 635: size += len;
! 636: }
! 637:
! 638: if (size == 0) {
! 639: XSRETURN_EMPTY;
! 640: }
! 641:
! 642: b = ngx_create_temp_buf(r->pool, size);
! 643: if (b == NULL) {
! 644: XSRETURN_EMPTY;
! 645: }
! 646:
! 647: for (i = 1; i < items; i++) {
! 648: sv = ST(i);
! 649:
! 650: if (SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PV) {
! 651: sv = SvRV(sv);
! 652: }
! 653:
! 654: p = (u_char *) SvPV(sv, len);
! 655: b->last = ngx_cpymem(b->last, p, len);
! 656: }
! 657:
! 658: out:
! 659:
! 660: (void) ngx_http_perl_output(r, b);
! 661:
! 662:
! 663: void
! 664: sendfile(r, filename, offset = -1, bytes = 0)
! 665: CODE:
! 666:
! 667: ngx_http_request_t *r;
! 668: char *filename;
! 669: off_t offset;
! 670: size_t bytes;
! 671: ngx_str_t path;
! 672: ngx_buf_t *b;
! 673: ngx_open_file_info_t of;
! 674: ngx_http_core_loc_conf_t *clcf;
! 675:
! 676: ngx_http_perl_set_request(r);
! 677:
! 678: filename = SvPV_nolen(ST(1));
! 679:
! 680: if (filename == NULL) {
! 681: croak("sendfile(): NULL filename");
! 682: }
! 683:
! 684: offset = items < 3 ? -1 : SvIV(ST(2));
! 685: bytes = items < 4 ? 0 : SvIV(ST(3));
! 686:
! 687: b = ngx_calloc_buf(r->pool);
! 688: if (b == NULL) {
! 689: XSRETURN_EMPTY;
! 690: }
! 691:
! 692: b->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t));
! 693: if (b->file == NULL) {
! 694: XSRETURN_EMPTY;
! 695: }
! 696:
! 697: path.len = ngx_strlen(filename);
! 698:
! 699: path.data = ngx_pnalloc(r->pool, path.len + 1);
! 700: if (path.data == NULL) {
! 701: XSRETURN_EMPTY;
! 702: }
! 703:
! 704: (void) ngx_cpystrn(path.data, (u_char *) filename, path.len + 1);
! 705:
! 706: clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
! 707:
! 708: ngx_memzero(&of, sizeof(ngx_open_file_info_t));
! 709:
! 710: of.read_ahead = clcf->read_ahead;
! 711: of.directio = clcf->directio;
! 712: of.valid = clcf->open_file_cache_valid;
! 713: of.min_uses = clcf->open_file_cache_min_uses;
! 714: of.errors = clcf->open_file_cache_errors;
! 715: of.events = clcf->open_file_cache_events;
! 716:
! 717: if (ngx_http_set_disable_symlinks(r, clcf, &path, &of) != NGX_OK) {
! 718: XSRETURN_EMPTY;
! 719: }
! 720:
! 721: if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
! 722: != NGX_OK)
! 723: {
! 724: if (of.err == 0) {
! 725: XSRETURN_EMPTY;
! 726: }
! 727:
! 728: ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
! 729: "%s \"%s\" failed", of.failed, filename);
! 730: XSRETURN_EMPTY;
! 731: }
! 732:
! 733: if (offset == -1) {
! 734: offset = 0;
! 735: }
! 736:
! 737: if (bytes == 0) {
! 738: bytes = of.size - offset;
! 739: }
! 740:
! 741: b->in_file = 1;
! 742:
! 743: b->file_pos = offset;
! 744: b->file_last = offset + bytes;
! 745:
! 746: b->file->fd = of.fd;
! 747: b->file->log = r->connection->log;
! 748: b->file->directio = of.is_directio;
! 749:
! 750: (void) ngx_http_perl_output(r, b);
! 751:
! 752:
! 753: void
! 754: flush(r)
! 755: CODE:
! 756:
! 757: ngx_http_request_t *r;
! 758: ngx_buf_t *b;
! 759:
! 760: ngx_http_perl_set_request(r);
! 761:
! 762: b = ngx_calloc_buf(r->pool);
! 763: if (b == NULL) {
! 764: XSRETURN_EMPTY;
! 765: }
! 766:
! 767: b->flush = 1;
! 768:
! 769: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "$r->flush");
! 770:
! 771: (void) ngx_http_perl_output(r, b);
! 772:
! 773: XSRETURN_EMPTY;
! 774:
! 775:
! 776: void
! 777: internal_redirect(r, uri)
! 778: CODE:
! 779:
! 780: ngx_http_request_t *r;
! 781: SV *uri;
! 782: ngx_uint_t i;
! 783: ngx_http_perl_ctx_t *ctx;
! 784:
! 785: ngx_http_perl_set_request(r);
! 786:
! 787: uri = ST(1);
! 788:
! 789: ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module);
! 790:
! 791: if (ngx_http_perl_sv2str(aTHX_ r, &ctx->redirect_uri, uri) != NGX_OK) {
! 792: XSRETURN_EMPTY;
! 793: }
! 794:
! 795: for (i = 0; i < ctx->redirect_uri.len; i++) {
! 796: if (ctx->redirect_uri.data[i] == '?') {
! 797:
! 798: ctx->redirect_args.len = ctx->redirect_uri.len - (i + 1);
! 799: ctx->redirect_args.data = &ctx->redirect_uri.data[i + 1];
! 800: ctx->redirect_uri.len = i;
! 801:
! 802: XSRETURN_EMPTY;
! 803: }
! 804: }
! 805:
! 806:
! 807: void
! 808: allow_ranges(r)
! 809: CODE:
! 810:
! 811: ngx_http_request_t *r;
! 812:
! 813: ngx_http_perl_set_request(r);
! 814:
! 815: r->allow_ranges = 1;
! 816:
! 817:
! 818: void
! 819: unescape(r, text, type = 0)
! 820: CODE:
! 821:
! 822: dXSTARG;
! 823: ngx_http_request_t *r;
! 824: SV *text;
! 825: int type;
! 826: u_char *p, *dst, *src;
! 827: STRLEN len;
! 828:
! 829: ngx_http_perl_set_request(r);
! 830:
! 831: text = ST(1);
! 832:
! 833: src = (u_char *) SvPV(text, len);
! 834:
! 835: p = ngx_pnalloc(r->pool, len + 1);
! 836: if (p == NULL) {
! 837: XSRETURN_UNDEF;
! 838: }
! 839:
! 840: dst = p;
! 841:
! 842: type = items < 3 ? 0 : SvIV(ST(2));
! 843:
! 844: ngx_unescape_uri(&dst, &src, len, (ngx_uint_t) type);
! 845: *dst = '\0';
! 846:
! 847: ngx_http_perl_set_targ(p, dst - p);
! 848:
! 849: ST(0) = TARG;
! 850:
! 851:
! 852: void
! 853: variable(r, name, value = NULL)
! 854: CODE:
! 855:
! 856: dXSTARG;
! 857: ngx_http_request_t *r;
! 858: SV *name, *value;
! 859: u_char *p, *lowcase;
! 860: STRLEN len;
! 861: ngx_str_t var, val;
! 862: ngx_uint_t i, hash;
! 863: ngx_http_perl_var_t *v;
! 864: ngx_http_perl_ctx_t *ctx;
! 865: ngx_http_variable_value_t *vv;
! 866:
! 867: ngx_http_perl_set_request(r);
! 868:
! 869: name = ST(1);
! 870:
! 871: if (SvROK(name) && SvTYPE(SvRV(name)) == SVt_PV) {
! 872: name = SvRV(name);
! 873: }
! 874:
! 875: if (items == 2) {
! 876: value = NULL;
! 877:
! 878: } else {
! 879: value = ST(2);
! 880:
! 881: if (SvROK(value) && SvTYPE(SvRV(value)) == SVt_PV) {
! 882: value = SvRV(value);
! 883: }
! 884:
! 885: if (ngx_http_perl_sv2str(aTHX_ r, &val, value) != NGX_OK) {
! 886: XSRETURN_UNDEF;
! 887: }
! 888: }
! 889:
! 890: p = (u_char *) SvPV(name, len);
! 891:
! 892: lowcase = ngx_pnalloc(r->pool, len);
! 893: if (lowcase == NULL) {
! 894: XSRETURN_UNDEF;
! 895: }
! 896:
! 897: hash = ngx_hash_strlow(lowcase, p, len);
! 898:
! 899: var.len = len;
! 900: var.data = lowcase;
! 901:
! 902: #if (NGX_DEBUG)
! 903:
! 904: if (value) {
! 905: ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
! 906: "perl variable: \"%V\"=\"%V\"", &var, &val);
! 907: } else {
! 908: ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
! 909: "perl variable: \"%V\"", &var);
! 910: }
! 911:
! 912: #endif
! 913:
! 914: vv = ngx_http_get_variable(r, &var, hash);
! 915: if (vv == NULL) {
! 916: XSRETURN_UNDEF;
! 917: }
! 918:
! 919: if (vv->not_found) {
! 920:
! 921: ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module);
! 922:
! 923: if (ctx->variables) {
! 924:
! 925: v = ctx->variables->elts;
! 926: for (i = 0; i < ctx->variables->nelts; i++) {
! 927:
! 928: if (hash != v[i].hash
! 929: || len != v[i].name.len
! 930: || ngx_strncmp(lowcase, v[i].name.data, len) != 0)
! 931: {
! 932: continue;
! 933: }
! 934:
! 935: if (value) {
! 936: v[i].value = val;
! 937: XSRETURN_UNDEF;
! 938: }
! 939:
! 940: ngx_http_perl_set_targ(v[i].value.data, v[i].value.len);
! 941:
! 942: goto done;
! 943: }
! 944: }
! 945:
! 946: if (value) {
! 947: if (ctx->variables == NULL) {
! 948: ctx->variables = ngx_array_create(r->pool, 1,
! 949: sizeof(ngx_http_perl_var_t));
! 950: if (ctx->variables == NULL) {
! 951: XSRETURN_UNDEF;
! 952: }
! 953: }
! 954:
! 955: v = ngx_array_push(ctx->variables);
! 956: if (v == NULL) {
! 957: XSRETURN_UNDEF;
! 958: }
! 959:
! 960: v->hash = hash;
! 961: v->name.len = len;
! 962: v->name.data = lowcase;
! 963: v->value = val;
! 964:
! 965: XSRETURN_UNDEF;
! 966: }
! 967:
! 968: XSRETURN_UNDEF;
! 969: }
! 970:
! 971: if (value) {
! 972: vv->len = val.len;
! 973: vv->valid = 1;
! 974: vv->no_cacheable = 0;
! 975: vv->not_found = 0;
! 976: vv->data = val.data;
! 977:
! 978: XSRETURN_UNDEF;
! 979: }
! 980:
! 981: ngx_http_perl_set_targ(vv->data, vv->len);
! 982:
! 983: done:
! 984:
! 985: ST(0) = TARG;
! 986:
! 987:
! 988: void
! 989: sleep(r, sleep, next)
! 990: CODE:
! 991:
! 992: ngx_http_request_t *r;
! 993: ngx_msec_t sleep;
! 994: ngx_http_perl_ctx_t *ctx;
! 995:
! 996: ngx_http_perl_set_request(r);
! 997:
! 998: sleep = (ngx_msec_t) SvIV(ST(1));
! 999:
! 1000: ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
! 1001: "perl sleep: %M", sleep);
! 1002:
! 1003: ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module);
! 1004:
! 1005: ctx->next = SvRV(ST(2));
! 1006:
! 1007: ngx_add_timer(r->connection->write, sleep);
! 1008:
! 1009: r->write_event_handler = ngx_http_perl_sleep_handler;
! 1010: r->main->count++;
! 1011:
! 1012:
! 1013: void
! 1014: log_error(r, err, msg)
! 1015: CODE:
! 1016:
! 1017: ngx_http_request_t *r;
! 1018: SV *err, *msg;
! 1019: u_char *p;
! 1020: STRLEN len;
! 1021: ngx_err_t e;
! 1022:
! 1023: ngx_http_perl_set_request(r);
! 1024:
! 1025: err = ST(1);
! 1026:
! 1027: if (SvROK(err) && SvTYPE(SvRV(err)) == SVt_PV) {
! 1028: err = SvRV(err);
! 1029: }
! 1030:
! 1031: e = SvIV(err);
! 1032:
! 1033: msg = ST(2);
! 1034:
! 1035: if (SvROK(msg) && SvTYPE(SvRV(msg)) == SVt_PV) {
! 1036: msg = SvRV(msg);
! 1037: }
! 1038:
! 1039: p = (u_char *) SvPV(msg, len);
! 1040:
! 1041: ngx_log_error(NGX_LOG_ERR, r->connection->log, e, "perl: %s", p);
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>