How to modfiy headers in and headers out
Igor Sysoev
is at rambler-co.ru
Thu Nov 1 08:37:42 MSK 2007
On Thu, Nov 01, 2007 at 11:22:22AM +0800, Yingyuan Cheng wrote:
>
> Hello Igor.
>
> I tracked executing path using gdb, found the content of param "r"
> (ngx_http_request_t) past by hook routine was a awful mess, and
> r.headers_out.headers.last pointed to 0x22, which was in a protected
> memory region. When executing path left my module and went to other
> modules, the same param "r" was in its normal status. After I changed
> the module code layout, such as moving "#include <openssl/md5>" after
> nginx including headers, the problem diminished. Is it a compiling
> problem? The configuring line is:
I suspect that you did it on Linux or Solaris, where default off_t
is 32-bit size. nginx headers set "#define _FILE_OFFSET_BITS 64" and
nginx is built with 64-bit off_t.
If you include openssl/md5.h before nginx headers then your module
is built with 32-bit off_t, whereas all another obj files are built
with 64-bit off_t.
The general rule: include custom headers after nginx headers.
> CFLAGS="-g" ./configure --with-debug
> --add-module=/home/yingyuan/workspace/ngx_http_sessid_filter/
>
> ngx_http_sessid_filter_module "borrows" code snippets from
> ngx_http_userid_filter_module and ngx_http_upstream_ip_hash_module.
> First it acts as a load balancer, dispatching requests to backends based
> on cookie. If the cookie not found in request, it'll generate a new one.
> Then in the filter phase, it sends the cookie to client if it was
> generated newly in balancing phase. So we can make the client always
> dispatched to the same backend.
>
> Another question I want to ask: May I change request headers_out in
> upstream_init_peer phase?
No, it's too early.
> Thank you very much.
>
> Best Regards
>
> --
> yingyuan
>
> Igor Sysoev ??????:
> >On Wed, Oct 31, 2007 at 07:45:39PM +0800, Yingyuan Cheng wrote:
> >
> >
> >>After changed the order of my filter module defined in
> >>objs/ngx_modules.c which should go after ngx_http_header_filter module,
> >>it works. But I still get a segment fault when calling
> >>ngx_list_push(&r->headers_out.headers) in filter hook function.
> >>
> >>Anyone could give me a explanation?
> >>
> >>Thanks very much.
> >>
> >
> >ngx_list_push(&r->headers_out.headers) should not cause segfault in this
> >phase.
> >Could you show more code ?
> >
> >
> >
>
>
> ngx_addon_name=ngx_http_sessid_filter_module
> HTTP_MODULES="$HTTP_MODULES ngx_http_sessid_filter_module"
> NGX_ADDON_SRCS="$NGX_ADDON_SRCS /home/yingyuan/workspace/ngx_http_sessid_filter/ngx_http_sessid_filter_module.c"
> CORE_LIBS="$CORE_LIBS -lssl"
>
>
> /**
> * Load balancer based on user session_id
> *
> * yingyuan at staff.sina.com.cn
> * $Id$
> *
> */
>
> #include <ngx_config.h>
> #include <ngx_core.h>
> #include <ngx_http.h>
>
> #include <stdio.h>
> #include <openssl/md5.h>
>
> #define SID_COOKIE_EXPIRES_MAX 2145916555
> #define SID_COOKIE_LEN 32
> #define SID_COOKIE_NAME "SGSID"
> #define SID_COOKIE_RND "dw3$32EtBXW24"__DATE__":"__TIME__
> #define SID_COOKIE_ID "COOKIE"
>
> typedef struct {
> ngx_str_t name;
> ngx_str_t domain;
> ngx_str_t path;
> ngx_str_t rnd; /* random string to defend from attacking */
>
> time_t expires;
>
> } ngx_http_sessid_filter_conf_t;
>
> typedef struct {
> /* Must be placed in first field to be compatible with upstream_rr */
> ngx_http_upstream_rr_peer_data_t rrp;
>
> ngx_uint_t hash;
>
> ngx_str_t cookie;
> u_char tries;
>
> ngx_event_get_peer_pt get_rr_peer;
>
> u_char filter; /* set cookie or not */
>
> } ngx_http_sessid_filter_peer_data_t;
>
> static u_char expires[] = "; expires=Thu, 31-Dec-37 23:55:55 GMT";
> static ngx_http_output_header_filter_pt ngx_http_next_header_filter;
>
> static u_char cookie_key[] = SID_COOKIE_ID;
> static u_char cookie_rnd[] = SID_COOKIE_RND;
>
> static void *ngx_http_sessid_filter_create_conf(ngx_conf_t *cf);
> static char *ngx_http_sessid_filter_merge_conf(ngx_conf_t *cf, void *parent, void *child);
> static char *ngx_http_sessid_filter_conf_domain(ngx_conf_t *cf, void *post, void *data);
> static char *ngx_http_sessid_filter_conf_path(ngx_conf_t *cf, void *post, void *data);
> static char *ngx_http_sessid_filter_conf_expires(ngx_conf_t *cf, ngx_command_t *cmd,
> void *conf);
>
> static char *ngx_http_upstream_sessid_init_conf(ngx_conf_t *cf,
> ngx_command_t *cmd, void *conf);
> static ngx_int_t ngx_http_upstream_sessid_init_hash(ngx_conf_t *cf,
> ngx_http_upstream_srv_conf_t *us);
> static ngx_int_t ngx_http_upstream_sessid_init_hash_peer(ngx_http_request_t *r,
> ngx_http_upstream_srv_conf_t *us);
> static ngx_int_t ngx_http_upstream_sessid_get_hash_peer(ngx_peer_connection_t *pc,
> void *data);
>
> static ngx_int_t ngx_http_sessid_filter_init(ngx_conf_t *cf);
> static ngx_int_t ngx_http_sessid_filter_filter(ngx_http_request_t *r);
>
> static ngx_int_t sessid_filter_get_sid(ngx_http_request_t *r,
> ngx_http_sessid_filter_peer_data_t *ctx,
> ngx_http_sessid_filter_conf_t *conf);
> static ngx_int_t sessid_filter_set_sid(ngx_http_request_t *r,
> ngx_http_sessid_filter_peer_data_t *ctx,
> ngx_http_sessid_filter_conf_t *conf);
> static ngx_int_t sessid_filter_make_sid(ngx_http_request_t *r,
> ngx_http_sessid_filter_peer_data_t *ctx,
> ngx_http_sessid_filter_conf_t *conf);
> static ngx_int_t sessid_filter_send_sid(ngx_http_request_t *r,
> ngx_http_sessid_filter_peer_data_t *ctx,
> ngx_http_sessid_filter_conf_t *conf);
>
> static ngx_conf_post_handler_pt ngx_http_sessid_filter_domain_p =
> ngx_http_sessid_filter_conf_domain;
> static ngx_conf_post_handler_pt ngx_http_sessid_filter_path_p =
> ngx_http_sessid_filter_conf_path;
>
> static ngx_command_t ngx_http_sessid_filter_commands[] = {
>
> { ngx_string("sessid_hash"),
> NGX_HTTP_UPS_CONF|NGX_CONF_NOARGS,
> ngx_http_upstream_sessid_init_conf,
> 0,
> 0,
> NULL },
>
> { ngx_string("sessid_name"),
> NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
> ngx_conf_set_str_slot,
> NGX_HTTP_LOC_CONF_OFFSET,
> offsetof(ngx_http_sessid_filter_conf_t, name),
> NULL },
>
> { ngx_string("sessid_domain"),
> NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
> ngx_conf_set_str_slot,
> NGX_HTTP_LOC_CONF_OFFSET,
> offsetof(ngx_http_sessid_filter_conf_t, domain),
> &ngx_http_sessid_filter_domain_p },
>
> { ngx_string("sessid_path"),
> NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
> ngx_conf_set_str_slot,
> NGX_HTTP_LOC_CONF_OFFSET,
> offsetof(ngx_http_sessid_filter_conf_t, path),
> &ngx_http_sessid_filter_path_p },
>
> { ngx_string("sessid_rnd"),
> NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
> ngx_conf_set_str_slot,
> NGX_HTTP_LOC_CONF_OFFSET,
> offsetof(ngx_http_sessid_filter_conf_t, rnd),
> NULL },
>
> { ngx_string("sessid_expires"),
> NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
> ngx_http_sessid_filter_conf_expires,
> NGX_HTTP_LOC_CONF_OFFSET,
> 0,
> NULL },
>
> ngx_null_command
> };
>
>
> static ngx_http_module_t ngx_http_sessid_filter_module_ctx = {
> NULL, /* preconfiguration */
> ngx_http_sessid_filter_init, /* postconfiguration */
> NULL, /* create main configuration */
> NULL, /* init main configuration */
> NULL, /* create server configuration */
> NULL, /* merge server configuration */
> ngx_http_sessid_filter_create_conf, /* create location configuration */
> ngx_http_sessid_filter_merge_conf /* merge location configuration */
> };
>
>
> ngx_module_t ngx_http_sessid_filter_module = {
> NGX_MODULE_V1,
> &ngx_http_sessid_filter_module_ctx, /* module context */
> ngx_http_sessid_filter_commands, /* module directives */
> NGX_HTTP_MODULE, /* module type */
> NULL, /* init master */
> NULL, /* init module */
> NULL, /* init process */
> NULL, /* init thread */
> NULL, /* exit thread */
> NULL, /* exit process */
> NULL, /* exit master */
> NGX_MODULE_V1_PADDING
> };
>
> static char *
> ngx_http_sessid_filter_conf_expires(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
> {
> ngx_http_sessid_filter_conf_t *ucf = conf;
>
> ngx_str_t *value;
>
> if (ucf->expires != NGX_CONF_UNSET) {
> return "is duplicate";
> }
>
> value = cf->args->elts;
>
> if (ngx_strcmp(value[1].data, "max") == 0) {
> ucf->expires = SID_COOKIE_EXPIRES_MAX;
> return NGX_CONF_OK;
> }
>
> if (ngx_strcmp(value[1].data, "off") == 0) {
> ucf->expires = 0;
> return NGX_CONF_OK;
> }
>
> ucf->expires = ngx_parse_time(&value[1], 1);
> if (ucf->expires == NGX_ERROR) {
> return "invalid value";
> }
>
> if (ucf->expires == NGX_PARSE_LARGE_TIME) {
> return "value must be less than 68 years";
> }
>
> return NGX_CONF_OK;
> }
>
>
> static char *
> ngx_http_sessid_filter_conf_domain(ngx_conf_t *cf, void *post, void *data)
> {
> ngx_str_t *domain = data;
>
> u_char *p, *new;
>
> if (ngx_strcmp(domain->data, "none") == 0) {
> domain->len = 0;
> domain->data = (u_char *) "";
>
> return NGX_CONF_OK;
> }
>
> new = ngx_palloc(cf->pool, sizeof("; domain=") - 1 + domain->len);
> if (new == NULL) {
> return NGX_CONF_ERROR;
> }
>
> p = ngx_cpymem(new, "; domain=", sizeof("; domain=") - 1);
> ngx_memcpy(p, domain->data, domain->len);
>
> domain->len += sizeof("; domain=") - 1;
> domain->data = new;
>
> return NGX_CONF_OK;
> }
>
>
> static char *
> ngx_http_sessid_filter_conf_path(ngx_conf_t *cf, void *post, void *data)
> {
> ngx_str_t *path = data;
>
> u_char *p, *new;
>
> new = ngx_palloc(cf->pool, sizeof("; path=") - 1 + path->len);
> if (new == NULL) {
> return NGX_CONF_ERROR;
> }
>
> p = ngx_cpymem(new, "; path=", sizeof("; path=") - 1);
> ngx_memcpy(p, path->data, path->len);
>
> path->len += sizeof("; path=") - 1;
> path->data = new;
>
> return NGX_CONF_OK;
> }
>
>
> static void *
> ngx_http_sessid_filter_create_conf(ngx_conf_t *cf)
> {
> ngx_http_sessid_filter_conf_t *conf;
>
> conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_sessid_filter_conf_t));
> if (conf == NULL) {
> return NGX_CONF_ERROR;
> }
>
> /*
> * set by ngx_pcalloc():
> *
> * conf->name.len = 0;
> * conf->name.data = NULL;
> * conf->domain.len = 0;
> * conf->domain.data = NULL;
> * conf->path.len = 0;
> * conf->path.data = NULL;
> */
>
> return conf;
> }
>
>
> static char *
> ngx_http_sessid_filter_merge_conf(ngx_conf_t *cf, void *parent, void *child)
> {
> ngx_http_sessid_filter_conf_t *prev = parent;
> ngx_http_sessid_filter_conf_t *conf = child;
>
> ngx_conf_merge_str_value(conf->name, prev->name, SID_COOKIE_NAME);
> ngx_conf_merge_str_value(conf->domain, prev->domain, "");
> ngx_conf_merge_str_value(conf->path, prev->path, "; path=/");
> ngx_conf_merge_str_value(conf->rnd, prev->rnd, cookie_rnd);
> ngx_conf_merge_sec_value(conf->expires, prev->expires, 0);
>
> return NGX_CONF_OK;
> }
>
>
> static char *
> ngx_http_upstream_sessid_init_conf(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
> {
> ngx_http_upstream_srv_conf_t *uscf;
>
> uscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_upstream_module);
>
> uscf->peer.init_upstream = ngx_http_upstream_sessid_init_hash;
>
> uscf->flags = NGX_HTTP_UPSTREAM_CREATE
> |NGX_HTTP_UPSTREAM_MAX_FAILS
> |NGX_HTTP_UPSTREAM_FAIL_TIMEOUT
> |NGX_HTTP_UPSTREAM_DOWN;
>
> return NGX_CONF_OK;
> }
>
>
> static ngx_int_t
> ngx_http_upstream_sessid_init_hash(ngx_conf_t *cf,
> ngx_http_upstream_srv_conf_t *us)
> {
> if (ngx_http_upstream_init_round_robin(cf, us) != NGX_OK) {
> return NGX_ERROR;
> }
>
> us->peer.init = ngx_http_upstream_sessid_init_hash_peer;
>
> return NGX_OK;
> }
>
>
> static ngx_int_t
> ngx_http_upstream_sessid_init_hash_peer(ngx_http_request_t *r,
> ngx_http_upstream_srv_conf_t *us)
> {
> ngx_http_sessid_filter_peer_data_t *sidhp;
> ngx_http_sessid_filter_conf_t *conf;
>
> sidhp = ngx_palloc(r->pool, sizeof(ngx_http_sessid_filter_peer_data_t));
> if (sidhp == NULL) {
> return NGX_ERROR;
> }
>
> sidhp->hash = 89;
> sidhp->tries = 0;
> sidhp->get_rr_peer = ngx_http_upstream_get_round_robin_peer;
> sidhp->filter = 0;
>
> r->upstream->peer.data = &sidhp->rrp;
>
> if (ngx_http_upstream_init_round_robin_peer(r, us) != NGX_OK) {
> return NGX_ERROR;
> }
>
> r->upstream->peer.get = ngx_http_upstream_sessid_get_hash_peer;
>
> conf = ngx_http_get_module_loc_conf(r, ngx_http_sessid_filter_module);
> if (!sessid_filter_get_sid(r, sidhp, conf)) {
> if (!sessid_filter_set_sid(r, sidhp, conf)) {
> return NGX_ERROR;
>
> }
>
> /* generated session_id should be sent to client */
> sidhp->filter = 1;
> }
>
> /* sidhp would be reused in filter phase */
> ngx_http_set_ctx(r, sidhp, ngx_http_sessid_filter_module);
>
> return NGX_OK;
> }
>
>
> static ngx_int_t
> ngx_http_upstream_sessid_get_hash_peer(ngx_peer_connection_t *pc, void *data)
> {
> ngx_http_sessid_filter_peer_data_t *sidhp = data;
>
> time_t now;
> uintptr_t m;
> ngx_uint_t i, n, p, hash;
> ngx_http_upstream_rr_peer_t *peer;
>
> ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0,
> "ngx_http_upstream_get_sessid_hash_peer: try %ui", pc->tries);
>
> /* TODO: cached */
>
> if (sidhp->tries > 20 || sidhp->rrp.peers->number == 1 ||
> sidhp->cookie.len < SID_COOKIE_LEN) {
> return sidhp->get_rr_peer(pc, &sidhp->rrp);
>
> }
>
> now = ngx_time();
>
> pc->cached = 0;
> pc->connection = NULL;
>
> hash = sidhp->hash;
>
> for ( ;; ) {
>
> for (i = 0; i < SID_COOKIE_LEN; i++) {
> hash = (hash * 113 + sidhp->cookie.data[i]) % 6271;
> }
>
> p = hash % sidhp->rrp.peers->number;
>
> n = p / (8 * sizeof(uintptr_t));
> m = 1 << p % (8 * sizeof(uintptr_t));
>
> if (!(sidhp->rrp.tried[n] & m)) {
>
> ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0,
> "ngx_http_upstream_get_sessid_hash_peer: hash: %ui %04XA", p, m);
>
> peer = &sidhp->rrp.peers->peer[p];
> /* ngx_lock_mutex(sidhp->rrp.peers->mutex); */
>
> if (!peer->down) {
>
> if (peer->max_fails == 0 || peer->fails < peer->max_fails) {
> break;
> }
>
> if (now - peer->accessed > peer->fail_timeout) {
> peer->fails = 0;
> break;
> }
> }
>
> sidhp->rrp.tried[n] |= m;
> /* ngx_unlock_mutex(sidhp->rrp.peers->mutex); */
> pc->tries--;
> }
>
> if (++sidhp->tries >= 20) {
> return sidhp->get_rr_peer(pc, &sidhp->rrp);
> }
> }
>
> pc->sockaddr = peer->sockaddr;
> pc->socklen = peer->socklen;
> pc->name = &peer->name;
>
> /* ngx_unlock_mutex(sidhp->rrp.peers->mutex); */
> sidhp->rrp.tried[n] |= m;
> sidhp->hash = hash;
>
> return NGX_OK;
> }
>
>
> static ngx_int_t
> sessid_filter_get_sid(ngx_http_request_t *r, ngx_http_sessid_filter_peer_data_t *ctx,
> ngx_http_sessid_filter_conf_t *conf)
> {
> ngx_int_t n;
> ngx_table_elt_t **cookies;
>
> n = ngx_http_parse_multi_header_lines(&r->headers_in.cookies,
> &conf->name, &ctx->cookie);
> if (n == NGX_DECLINED) {
> return 0;
> }
>
> if (ctx->cookie.len < SID_COOKIE_LEN) {
> return 0;
> }
>
> return 1;
> }
>
>
> static ngx_int_t
> sessid_filter_set_sid(ngx_http_request_t *r,
> ngx_http_sessid_filter_peer_data_t *ctx,
> ngx_http_sessid_filter_conf_t *conf)
> {
> u_char *cookie, *p;
> ngx_table_elt_t *set_cookie;
> u_char ch;
> int i, j;
>
> if (!sessid_filter_make_sid(r, ctx, conf)) {
> return 0;
> }
>
> ngx_list_part_t *part = &(r->headers_in.headers.part);
> ngx_table_elt_t *header = part->elts;
> set_cookie = NULL;
>
> for (i = 0;/* void */; i++) {
> if (i >= part->nelts) {
> if (part->next == NULL) {
> break;
> }
>
> part = part->next;
> header = part->elts;
> i = 0;
> }
>
> if (header[i].key.len != (sizeof(cookie_key) - 1)) {
> continue;
> }
>
> for (j = 0; j < (sizeof(cookie_key) - 1); j++) {
> ch = header[i].key.data[j];
> if (ch >= 'a' && ch <= 'z') ch &= ~0x20;
> if (ch != cookie_key[j]) break;
> }
>
> if (j == (sizeof(cookie_key) - 1)) {
> set_cookie = &header[i];
>
> }
> }
>
> if (set_cookie == NULL) {
> set_cookie = ngx_list_push(&(r->headers_in.headers));
> if (set_cookie == NULL) {
> return 0;
> }
>
> set_cookie->hash = 1;
> set_cookie->key.len = sizeof(cookie_key) - 1;
> set_cookie->key.data = cookie_key;
>
> cookie = ngx_palloc(r->pool, conf->name.len + 1 + ctx->cookie.len);
> if (cookie == NULL) {
> return 0;
> }
>
> p = ngx_copy(cookie, conf->name.data, conf->name.len);
> *p++ = '=';
> p = ngx_copy(p, ctx->cookie.data, ctx->cookie.len);
> set_cookie->value.len = p - cookie;
> set_cookie->value.data = cookie;
>
> } else {
> cookie = ngx_palloc(r->pool, set_cookie->value.len + 2 + conf->name.len + 1 +
> ctx->cookie.len);
> if (cookie == NULL) {
> return 0;
> }
>
> p = ngx_copy(cookie, set_cookie->value.data, set_cookie->value.len);
> *p++ = ';';
> *p++ = ' ';
> p = ngx_copy(p, conf->name.data, conf->name.len);
> *p++ = '=';
> p = ngx_copy(p, ctx->cookie.data, ctx->cookie.len);
> set_cookie->value.len = p - cookie;
> set_cookie->value.data = cookie;
> }
>
> return 1;
> }
>
>
> static ngx_int_t
> sessid_filter_make_sid(ngx_http_request_t *r,
> ngx_http_sessid_filter_peer_data_t *ctx,
> ngx_http_sessid_filter_conf_t *conf)
> {
> int i, j;
> unsigned char digest[16];
> unsigned char buf[256];
> struct timeval tv;
> unsigned char ch;
> const char *hexdigitals = "0123456789abcdef";
> struct sockaddr_in *sin;
> u_char *p;
>
> ctx->cookie.len = SID_COOKIE_LEN;
>
> ctx->cookie.data = ngx_palloc(r->pool, SID_COOKIE_LEN);
> if (ctx->cookie.data == NULL) {
> return 0;
> }
>
> sin = (struct sockaddr_in *) r->connection->sockaddr;
> p = (u_char *) &sin->sin_addr.s_addr;
> gettimeofday(&tv, NULL);
>
> i = sprintf(buf, "%lu:%lu:%02x%02x%02x%02x:%lu:%lu:", tv.tv_sec, tv.tv_usec,
> p[0], p[1], p[2], p[3], ntohs(sin->sin_port), rand());
> j = (256 - i < conf->rnd.len) ? (256 - i):conf->rnd.len;
> ngx_copy(buf+i, conf->rnd.data, j);
> buf[i + j] = '\0';
>
> if (!MD5(buf, i+j, digest)) {
> return 0;
> }
>
> /* TODO: SID_COOKIE_LEN is coupled with 32 */
> for (i = 0, j = 0; i < 16; i++) {
> ch = digest[i];
> ctx->cookie.data[j++] = hexdigitals[ch>>4];
> ctx->cookie.data[j++] = hexdigitals[ch&15];
> }
>
> return 1;
> }
>
>
> static ngx_int_t
> sessid_filter_send_sid(ngx_http_request_t *r,
> ngx_http_sessid_filter_peer_data_t *ctx,
> ngx_http_sessid_filter_conf_t *conf)
> {
> u_char *cookie, *p;
> size_t len;
> ngx_table_elt_t *set_cookie;
>
> len = conf->name.len + 1 + ctx->cookie.len + conf->path.len;
>
> if (conf->expires) {
> len += sizeof(expires) - 1 + 2;
> }
>
> if (conf->domain.len) {
> len += conf->domain.len;
> }
>
> cookie = ngx_palloc(r->pool, len);
> if (cookie == NULL) {
> return 0;
> }
>
> p = ngx_copy(cookie, conf->name.data, conf->name.len);
> *p++ = '=';
> p = ngx_copy(p, ctx->cookie.data, ctx->cookie.len);
>
> if (conf->expires == SID_COOKIE_EXPIRES_MAX) {
> p = ngx_cpymem(p, expires, sizeof(expires) - 1);
>
> } else if (conf->expires) {
> p = ngx_cpymem(p, expires, sizeof("; expires=") - 1);
> p = ngx_http_cookie_time(p, ngx_time() + conf->expires);
> }
>
> p = ngx_copy(p, conf->domain.data, conf->domain.len);
> p = ngx_copy(p, conf->path.data, conf->path.len);
>
> set_cookie = ngx_list_push(&r->headers_out.headers);
> if (set_cookie == NULL) {
> return 0;
> }
>
> set_cookie->hash = 1;
> set_cookie->key.len = sizeof("Set-Cookie") - 1;
> set_cookie->key.data = (u_char *) "Set-Cookie";
> set_cookie->value.len = p - cookie;
> set_cookie->value.data = cookie;
>
> return 1;
> }
>
>
> static ngx_int_t
> ngx_http_sessid_filter_init(ngx_conf_t *cf)
> {
> ngx_http_next_header_filter = ngx_http_top_header_filter;
> ngx_http_top_header_filter = ngx_http_sessid_filter_filter;
>
> return NGX_OK;
> }
>
>
> static ngx_int_t
> ngx_http_sessid_filter_filter(ngx_http_request_t *r)
> {
> ngx_int_t rc;
> ngx_http_sessid_filter_peer_data_t *ctx;
> ngx_http_sessid_filter_conf_t *conf;
>
> if (r != r->main) {
> return ngx_http_next_header_filter(r);
> }
>
> conf = ngx_http_get_module_loc_conf(r, ngx_http_sessid_filter_module);
> ctx = ngx_http_get_module_ctx(r, ngx_http_sessid_filter_module);
>
> if (!ctx || ctx->filter == 0) {
> return ngx_http_next_header_filter(r);
> }
>
> sessid_filter_send_sid(r, ctx, conf);
> ctx->filter = 0;
>
> return ngx_http_next_header_filter(r);
> }
>
>
--
Igor Sysoev
http://sysoev.ru/en/
More information about the nginx
mailing list