zoukankan      html  css  js  c++  java
  • 用于解决用户多线路访问的nginx cross isp module

    在互联网应用中都会面对多线负载与策略的问题,nginx cross isp module提供了一种简单的解决方案。

    nginx cross isp module是基于nginx(http://nginx.org/)开发的,完全用c语言编写,借助于linux系统与nginx强大的功能与性能。

    nginx cross isp module的主要逻辑很简单,根据访问用户的ip,从isp数据中查找,如果找到符合条件的,则根据配置,重新定向与相对应的链接地址。isp数据存在mysql中,由于isp数据一般不会经常变化,所以是nginx启动时,一次性读入。如果数据变更,可以重新启动nginx。

    在实际应用中,需要为每个isp配置不同的域名,可以是二级域名。以下是nginx cross isp module的所有源码:

    #include <ngx_config.h>
    #include <ngx_core.h>
    #include <ngx_http.h>
    #include <ngx_regex.h>

    #include <pcre.h>
    #include <my_global.h>
    #include <mysql.h>


    #define HTTP_COOKIES_MAX_EXPIRES  2145916555
    #define HTTP_DOMAIN_COOKIE_NAME_LEN (size_t) 6
    #define HTTP_SCHEMA_LEN (size_t) 7
    #define HTTPS_SCHEMA_LEN (size_t) 8


    typedef struct
    {
      ngx_uint_t ip_start;
      ngx_uint_t ip_end;
      u_char isp[3];
    } ngx_isp_store_t;

    typedef struct
    {
      u_char isp[3];
      ngx_regex_t *regex;
      ngx_str_t pattern;
      ngx_str_t replace;
      ngx_str_t domain;
    } ngx_isp_domain_t;

    typedef struct
    {
      ngx_regex_t *regex;
      ngx_str_t pattern;
    } ngx_isp_proxy_t;

    typedef struct
    {
      ngx_str_t host;
      ngx_int_t port;
      ngx_str_t usr;
      ngx_str_t pwd;
      ngx_str_t db;
      ngx_str_t tb;
      ngx_str_t isp_rhost_cookie_name;
      ngx_str_t isp_taddr_cookie_name;
      time_t isp_cookies_expires;
      ngx_array_t isp_store;
      ngx_array_t isp_domains;
      ngx_array_t isp_proxies;
    } ngx_http_cross_isp_main_conf_t;


    static u_char ngx_http_domain_cookie_name[] = "domain";
    static u_char ngx_http_cookies_expires[] =
      "; expires=Thu, 31-Dec-37 23:55:55 GMT";
    static u_char ngx_http_schema[] = "http://";
    static u_char ngx_https_schema[] = "https://";
    static u_char ngx_http_302_page[] = "<html><head>" CRLF
      "<title>302 Redirect</title></head>" CRLF
      "<body><center><h1>302 Redirect</h1>" CRLF "</center></body></html>" CRLF;


    static ngx_int_t ngx_http_cross_isp_init (ngx_conf_t * cf);
    static void *ngx_http_cross_isp_create_main_conf (ngx_conf_t * cf);
    static char *ngx_http_cross_isp_init_main_conf (ngx_conf_t * cf, void *conf);

    static char *ngx_conf_set_isp_cookies_expires (ngx_conf_t * cf,
                               ngx_command_t * cmd,
                               void *conf);
    static char *ngx_conf_set_isp_domain (ngx_conf_t * cf, ngx_command_t * cmd,
                          void *conf);
    static char *ngx_conf_set_isp_proxy (ngx_conf_t * cf, ngx_command_t * cmd,
                         void *conf);

    static ngx_int_t ngx_http_cross_isp_handler (ngx_http_request_t * r);
    static long ngx_isp_store_binary_search (ngx_array_t data, ngx_uint_t ip);
    static ngx_int_t ngx_cross_isp_redirect (ngx_http_request_t * r,
                         ngx_str_t url);
    static void ngx_http_write_isp_cookie (ngx_http_request_t * r,
                           u_char * cookie);

    static ngx_command_t ngx_http_cross_isp_commands[] = {
      {
       ngx_string ("isp_store_host"),
       NGX_HTTP_MAIN_CONF | NGX_CONF_TAKE1,
       ngx_conf_set_str_slot,
       NGX_HTTP_MAIN_CONF_OFFSET,
       offsetof (ngx_http_cross_isp_main_conf_t, host),
       NULL},
      {
       ngx_string ("isp_store_port"),
       NGX_HTTP_MAIN_CONF | NGX_CONF_TAKE1,
       ngx_conf_set_num_slot,
       NGX_HTTP_MAIN_CONF_OFFSET,
       offsetof (ngx_http_cross_isp_main_conf_t, port),
       NULL},
      {
       ngx_string ("isp_store_usr"),
       NGX_HTTP_MAIN_CONF | NGX_CONF_TAKE1,
       ngx_conf_set_str_slot,
       NGX_HTTP_MAIN_CONF_OFFSET,
       offsetof (ngx_http_cross_isp_main_conf_t, usr),
       NULL},
      {
       ngx_string ("isp_store_pwd"),
       NGX_HTTP_MAIN_CONF | NGX_CONF_TAKE1,
       ngx_conf_set_str_slot,
       NGX_HTTP_MAIN_CONF_OFFSET,
       offsetof (ngx_http_cross_isp_main_conf_t, pwd),
       NULL},
      {
       ngx_string ("isp_store_db"),
       NGX_HTTP_MAIN_CONF | NGX_CONF_TAKE1,
       ngx_conf_set_str_slot,
       NGX_HTTP_MAIN_CONF_OFFSET,
       offsetof (ngx_http_cross_isp_main_conf_t, db),
       NULL},
      {
       ngx_string ("isp_store_tb"),
       NGX_HTTP_MAIN_CONF | NGX_CONF_TAKE1,
       ngx_conf_set_str_slot,
       NGX_HTTP_MAIN_CONF_OFFSET,
       offsetof (ngx_http_cross_isp_main_conf_t, tb),
       NULL},
      {
       ngx_string ("isp_rhost_cookie_name"),
       NGX_HTTP_MAIN_CONF | NGX_CONF_TAKE1,
       ngx_conf_set_str_slot,
       NGX_HTTP_MAIN_CONF_OFFSET,
       offsetof (ngx_http_cross_isp_main_conf_t, isp_rhost_cookie_name),
       NULL},
      {
       ngx_string ("isp_taddr_cookie_name"),
       NGX_HTTP_MAIN_CONF | NGX_CONF_TAKE1,
       ngx_conf_set_str_slot,
       NGX_HTTP_MAIN_CONF_OFFSET,
       offsetof (ngx_http_cross_isp_main_conf_t, isp_taddr_cookie_name),
       NULL},
      {
       ngx_string ("isp_cookies_expires"),
       NGX_HTTP_MAIN_CONF | NGX_CONF_TAKE1,
       ngx_conf_set_isp_cookies_expires,
       NGX_HTTP_MAIN_CONF_OFFSET,
       offsetof (ngx_http_cross_isp_main_conf_t, isp_cookies_expires),
       NULL},
      {
       ngx_string ("isp_domain"),
       NGX_HTTP_MAIN_CONF | NGX_CONF_TAKE4,
       ngx_conf_set_isp_domain,
       NGX_HTTP_MAIN_CONF_OFFSET,
       offsetof (ngx_http_cross_isp_main_conf_t, isp_domains),
       NULL},
      {
       ngx_string ("cross_isp"),
       NGX_HTTP_MAIN_CONF | NGX_CONF_TAKE1,
       ngx_conf_set_isp_proxy,
       NGX_HTTP_MAIN_CONF_OFFSET,
       offsetof (ngx_http_cross_isp_main_conf_t, isp_proxies),
       NULL},
      ngx_null_command
    };

    static ngx_http_module_t ngx_http_cross_isp_module_ctx = {
      NULL,                /* preconfiguration */
      ngx_http_cross_isp_init,    /* postconfiguration */

      ngx_http_cross_isp_create_main_conf,    /* create main configuration */
      ngx_http_cross_isp_init_main_conf,    /* init main configuration */

      NULL,                /* create server configuration */
      NULL,                /* merge server configuration */

      NULL,                /* create location configuration */
      NULL                /* merge location configuration */
    };

    ngx_module_t ngx_http_cross_isp_module = {
      NGX_MODULE_V1,
      &ngx_http_cross_isp_module_ctx,    /* module context */
      ngx_http_cross_isp_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 ngx_int_t
    ngx_http_cross_isp_init (ngx_conf_t * cf)
    {
      ngx_http_handler_pt *h;
      ngx_http_core_main_conf_t *cmcf;

      cmcf = ngx_http_conf_get_module_main_conf (cf, ngx_http_core_module);
      h = ngx_array_push (&cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers);
      if (h == NULL)
        {
          return NGX_ERROR;
        }

      *h = ngx_http_cross_isp_handler;

      return NGX_OK;
    }

    static void *
    ngx_http_cross_isp_create_main_conf (ngx_conf_t * cf)
    {
      ngx_http_cross_isp_main_conf_t *iscf;

      iscf = ngx_pcalloc (cf->pool, sizeof (ngx_http_cross_isp_main_conf_t));
      if (iscf == NULL)
        {
          return NGX_CONF_ERROR;
        }

      if (ngx_array_init
          (&iscf->isp_store, cf->pool, 20000, sizeof (ngx_isp_store_t)) != NGX_OK)
        {
          return NGX_CONF_ERROR;
        }

      if (ngx_array_init
          (&iscf->isp_domains, cf->pool, 10, sizeof (ngx_isp_domain_t)) != NGX_OK)
        {
          return NGX_CONF_ERROR;
        }

      if (ngx_array_init
          (&iscf->isp_proxies, cf->pool, 100, sizeof (ngx_isp_proxy_t)) != NGX_OK)
        {
          return NGX_CONF_ERROR;
        }

      iscf->port = NGX_CONF_UNSET_UINT;
      iscf->isp_cookies_expires = NGX_CONF_UNSET;

      return iscf;
    }

    static char *
    ngx_http_cross_isp_init_main_conf (ngx_conf_t * cf, void *conf)
    {
      MYSQL *conn = NULL;
      MYSQL_RES *result = NULL;
      MYSQL_ROW row;
      char query[80];
      ngx_isp_store_t *elt;
      ngx_http_cross_isp_main_conf_t *iscf = conf;

      sprintf (query,
           "SELECT `ip_start`,`ip_end`,`isp` FROM `%s` ORDER BY `ip_start`",
           (char *) iscf->tb.data);

      conn = mysql_init (NULL);
      if (conn == NULL)
        {
          ngx_conf_log_error (NGX_LOG_EMERG,
                  cf,
                  0,
                  "init mysql error(host: %V port:%d user: %V password: %V database: %V table:%V)",
                  iscf->host, iscf->port, iscf->pwd, iscf->db,
                  iscf->tb);
        }

      mysql_real_connect (conn, (char *) iscf->host.data, (char *) iscf->usr.data,
                  (char *) iscf->pwd.data, (char *) iscf->db.data,
                  (unsigned int) iscf->port, NULL, 0);
      mysql_real_query (conn, query, strlen (query));
      result = mysql_store_result (conn);
      if (result == NULL)
        {
          ngx_conf_log_error (NGX_LOG_EMERG,
                  cf,
                  0,
                  "can not get isp data from mysql(host: %V port:%d user: %V password: %V database: %V table:%V)",
                  iscf->host, iscf->port, iscf->pwd, iscf->db,
                  iscf->tb);
          return NGX_CONF_ERROR;
        }

      while ((row = mysql_fetch_row (result)))
        {
          elt = (ngx_isp_store_t *) ngx_array_push (&iscf->isp_store);
          elt->ip_start = strtol (row[0], NULL, 10);
          elt->ip_end = strtol (row[1], NULL, 10);
          ngx_strlow (elt->isp, (u_char *) row[2], 3);
        }

      mysql_free_result (result);
      mysql_close (conn);

      return NGX_CONF_OK;
    }

    static char *
    ngx_conf_set_isp_cookies_expires (ngx_conf_t * cf, ngx_command_t * cmd,
                      void *conf)
    {
      ngx_http_cross_isp_main_conf_t *iscf = conf;

      ngx_str_t *value;
      if (iscf->isp_cookies_expires != NGX_CONF_UNSET)
        {
          return "is duplicate";
        }

      value = cf->args->elts;

      if (ngx_strcmp (value[1].data, "max") == 0)
        {
          iscf->isp_cookies_expires = HTTP_COOKIES_MAX_EXPIRES;
          return NGX_CONF_OK;
        }

      if (ngx_strcmp (value[1].data, "off") == 0)
        {
          iscf->isp_cookies_expires = 0;
          return NGX_CONF_OK;
        }

      iscf->isp_cookies_expires = ngx_parse_time (&value[1], 1);
      if (iscf->isp_cookies_expires == NGX_ERROR)
        {
          return "invalid value";
        }

      if (iscf->isp_cookies_expires == NGX_PARSE_LARGE_TIME)
        {
          return "value must be less than 68 years";
        }

      return NGX_CONF_OK;
    }

    static char *
    ngx_conf_set_isp_domain (ngx_conf_t * cf, ngx_command_t * cmd, void *conf)
    {
      ngx_regex_compile_t rc;
      u_char errstr[NGX_MAX_CONF_ERRSTR];

      char *p = conf;
      ngx_isp_domain_t *s;
      ngx_str_t *value;
      ngx_array_t *a;

      a = (ngx_array_t *) (p + cmd->offset);
      s = ngx_array_push (a);
      if (s == NULL)
        {
          return NGX_CONF_ERROR;
        }

      value = cf->args->elts;
      ngx_strlow (s->isp, value[1].data, 3);
      s->pattern = value[2];
      s->replace = value[3];
      s->domain = value[4];

      ngx_memzero (&rc, sizeof (ngx_regex_compile_t));

      rc.pattern = s->pattern;
      rc.pool = cf->pool;
      rc.err.len = NGX_MAX_CONF_ERRSTR;
      rc.err.data = errstr;
      if (ngx_regex_compile (&rc) != NGX_OK)
        {
          ngx_conf_log_error (NGX_LOG_EMERG, cf, 0, "%V", &rc.err);
          return NGX_CONF_ERROR;
        }

      s->regex = rc.regex;
      if (s->regex == NULL)
        {
          return NGX_CONF_ERROR;
        }

      return NGX_CONF_OK;
    }

    static char *
    ngx_conf_set_isp_proxy (ngx_conf_t * cf, ngx_command_t * cmd, void *conf)
    {
      ngx_regex_compile_t rc;
      u_char errstr[NGX_MAX_CONF_ERRSTR];

      char *p = conf;
      ngx_isp_proxy_t *s;
      ngx_str_t *value;
      ngx_array_t *a;

      a = (ngx_array_t *) (p + cmd->offset);
      s = ngx_array_push (a);
      if (s == NULL)
        {
          return NGX_CONF_ERROR;
        }

      value = cf->args->elts;
      s->pattern = value[1];

      ngx_memzero (&rc, sizeof (ngx_regex_compile_t));

      rc.pattern = s->pattern;
      rc.pool = cf->pool;
      rc.err.len = NGX_MAX_CONF_ERRSTR;
      rc.err.data = errstr;
      if (ngx_regex_compile (&rc) != NGX_OK)
        {
          ngx_conf_log_error (NGX_LOG_EMERG, cf, 0, "%V", &rc.err);
          return NGX_CONF_ERROR;
        }

      s->regex = rc.regex;
      if (s->regex == NULL)
        {
          return NGX_CONF_ERROR;
        }

      return NGX_CONF_OK;
    }

    static ngx_int_t
    ngx_http_cross_isp_handler (ngx_http_request_t * r)
    {
      ngx_http_cross_isp_main_conf_t *ipmcf;
      ngx_int_t pc1 = NGX_DECLINED, pc2 = NGX_DECLINED, ssl, rc;
      ngx_uint_t i, m;
      ngx_uint_t ip;
      ngx_str_t str_uri;
      ngx_str_t isp_rhost_cookie, isp_taddr_cookie;
      ngx_isp_proxy_t *ipt;
      ngx_isp_store_t *ist;
      ngx_isp_domain_t *idt;
      u_char *u_uri, *u_relative_uri, *p, *u_isp_rhost_cookie,
        *u_isp_taddr_cookie, *taddr;

      struct sockaddr_in *sin;
      size_t str_uri_len, str_relative_uri_len, con_schema_len, taddr_len,
        cookie_expires_len;
      char *pt;
      long ip_pos;
      int cmp_r1, cmp_r2;

      ipmcf = ngx_http_get_module_main_conf (r, ngx_http_cross_isp_module);

      ipt = ipmcf->isp_proxies.elts;

      for (i = 0; i < ipmcf->isp_proxies.nelts; i++)
        {
          rc = ngx_regex_exec (ipt[i].regex, &r->uri, NULL, 0);
          if (rc == NGX_REGEX_NO_MATCHED)
        {
          continue;
        }

          pc1 =
        ngx_http_parse_multi_header_lines (&r->headers_in.cookies,
                           &ipmcf->isp_rhost_cookie_name,
                           &isp_rhost_cookie);
          pc2 =
        ngx_http_parse_multi_header_lines (&r->headers_in.cookies,
                           &ipmcf->isp_taddr_cookie_name,
                           &isp_taddr_cookie);

          sin = (struct sockaddr_in *) (r->connection->sockaddr);
          ip = ntohl (sin->sin_addr.s_addr);
          pt = inet_ntoa (sin->sin_addr);
          if (pt == NULL)
        {
          ngx_log_error (NGX_LOG_ERR,
                 r->connection->log, 0, "inet_ntoa get taddr error");
          return NGX_DECLINED;
        }

          taddr_len = strlen (pt);
          taddr = ngx_pcalloc (r->pool, taddr_len * sizeof (u_char));
          if (taddr == NULL)
        {
          ngx_log_error (NGX_LOG_ERR,
                 r->connection->log,
                 0, "ngx_pcalloc no args taddr error");

          return NGX_DECLINED;
        }

          p = ngx_copy (taddr, pt, taddr_len);

          cmp_r1 =
        ngx_strncmp (isp_rhost_cookie.data, r->headers_in.host->value.data,
                 isp_rhost_cookie.len);
          cmp_r2 =
        ngx_strncmp (isp_taddr_cookie.data, taddr, isp_taddr_cookie.len);
          if (pc1 != NGX_DECLINED && cmp_r1 == 0 && pc2 != NGX_DECLINED
          && cmp_r2 == 0)
        {
          return NGX_DECLINED;
        }

          ip_pos = ngx_isp_store_binary_search (ipmcf->isp_store, ip);
          if (ip_pos == -1)
        {
          return NGX_DECLINED;
        }

          ist = ipmcf->isp_store.elts;
          idt = ipmcf->isp_domains.elts;

          for (m = 0; m < ipmcf->isp_domains.nelts; m++)
        {
          if (ngx_strcmp (idt[m].isp, ist[ip_pos].isp) == 0)
            {
              rc = ngx_regex_exec (idt[m].regex, &r->headers_in.host->value,
                       NULL, 0);
              if (rc >= 0)
            {
              if (ipmcf->isp_cookies_expires)
                {
                  cookie_expires_len =
                sizeof (ngx_http_cookies_expires) - 1;
                }

              if (pc1 == NGX_DECLINED || cmp_r1 != 0)
                {

                  u_isp_rhost_cookie = ngx_pcalloc (r->pool,
                                (ipmcf->isp_rhost_cookie_name.len
                                 + 1 +
                                 r->headers_in.
                                 host->value.len +
                                 cookie_expires_len +
                                 1 +
                                 HTTP_DOMAIN_COOKIE_NAME_LEN
                                 + 1 +
                                 idt[m].domain.len +
                                 1) *
                                sizeof (u_char));
                  if (u_isp_rhost_cookie == NULL)
                {
                  ngx_log_error (NGX_LOG_ERR,
                         r->connection->log,
                         0,
                         "ngx_pcalloc no args u_isp_rhost_cookie error");

                  return NGX_DECLINED;
                }

                  p = ngx_copy (u_isp_rhost_cookie,
                        ipmcf->isp_rhost_cookie_name.data,
                        ipmcf->isp_rhost_cookie_name.len);
                  *p++ = '=';

                  p = ngx_copy (p, r->headers_in.host->value.data,
                        r->headers_in.host->value.len);

                  if (ipmcf->isp_cookies_expires ==
                  HTTP_COOKIES_MAX_EXPIRES)
                {
                  p =
                    ngx_copy (p, ngx_http_cookies_expires,
                          cookie_expires_len);
                }
                  else if (ipmcf->isp_cookies_expires)
                {
                  p =
                    ngx_copy (p, ngx_http_cookies_expires,
                          sizeof ("; expires=") - 1);
                  p =
                    ngx_http_cookie_time (p,
                              ngx_time () +
                              ipmcf->isp_cookies_expires);
                }

                  *p++ = ';';

                  p = ngx_copy (p, ngx_http_domain_cookie_name,
                        HTTP_DOMAIN_COOKIE_NAME_LEN);
                  *p++ = '=';

                  p = ngx_copy (p, idt[m].domain.data, idt[m].domain.len);
                  *p++ = '\0';

                  ngx_http_write_isp_cookie (r, u_isp_rhost_cookie);
                }

              if (pc2 == NGX_DECLINED || cmp_r2 != 0)
                {
                  u_isp_taddr_cookie = ngx_pcalloc (r->pool,
                                (ipmcf->isp_taddr_cookie_name.len
                                 + 1 + taddr_len +
                                 cookie_expires_len +
                                 1 +
                                 HTTP_DOMAIN_COOKIE_NAME_LEN
                                 + 1 +
                                 idt[m].domain.len +
                                 1) *
                                sizeof (u_char));
                  if (u_isp_taddr_cookie == NULL)
                {
                  ngx_log_error (NGX_LOG_ERR,
                         r->connection->log,
                         0,
                         "ngx_pcalloc no args u_isp_taddr_cookie error");

                  return NGX_DECLINED;
                }

                  p =
                ngx_copy (u_isp_taddr_cookie,
                      ipmcf->isp_taddr_cookie_name.data,
                      ipmcf->isp_taddr_cookie_name.len);
                  *p++ = '=';

                  p = ngx_copy (p, taddr, taddr_len);

                  if (ipmcf->isp_cookies_expires ==
                  HTTP_COOKIES_MAX_EXPIRES)
                {
                  p =
                    ngx_copy (p, ngx_http_cookies_expires,
                          cookie_expires_len);
                }
                  else if (ipmcf->isp_cookies_expires)
                {
                  p =
                    ngx_copy (p, ngx_http_cookies_expires,
                          sizeof ("; expires=") - 1);
                  p =
                    ngx_http_cookie_time (p,
                              ngx_time () +
                              ipmcf->isp_cookies_expires);
                }

                  *p++ = ';';

                  p =
                ngx_copy (p, ngx_http_domain_cookie_name,
                      HTTP_DOMAIN_COOKIE_NAME_LEN);
                  *p++ = '=';

                  p = ngx_copy (p, idt[m].domain.data, idt[m].domain.len);
                  *p++ = '\0';

                  ngx_http_write_isp_cookie (r, u_isp_taddr_cookie);
                }

              return NGX_DECLINED;
            }
              else
            {
              ssl = r->connection->ssl == NULL ? 0 : 1;
              con_schema_len = ssl ? HTTPS_SCHEMA_LEN : HTTP_SCHEMA_LEN;

              if (r->args.data == NULL)
                {
                  u_relative_uri =
                ngx_pcalloc (r->pool,
                         (r->uri.len + 1) * sizeof (u_char));
                  if (u_relative_uri == NULL)
                {
                  ngx_log_error (NGX_LOG_ERR,
                         r->connection->log,
                         0,
                         "ngx_pcalloc no args u_relative_uri error");

                  return NGX_DECLINED;
                }

                  p = ngx_copy (u_relative_uri, r->uri.data, r->uri.len);
                  *p++ = '\0';
                }
              else
                {
                  u_relative_uri =
                ngx_pcalloc (r->pool,
                         (r->uri.len + r->args.len +
                          2) * sizeof (u_char));
                  if (u_relative_uri == NULL)
                {
                  ngx_log_error (NGX_LOG_ERR,
                         r->connection->log,
                         0,
                         "ngx_pcalloc with args u_relative_uri error");

                  return NGX_DECLINED;
                }

                  p = ngx_copy (u_relative_uri, r->uri.data, r->uri.len);
                  *p++ = '?';

                  p = ngx_copy (p, r->args.data, r->args.len);
                  *p++ = '\0';
                }

              str_relative_uri_len = ngx_strlen (u_relative_uri);
              str_uri_len =
                con_schema_len + idt[m].replace.len +
                str_relative_uri_len;
              u_uri =
                ngx_pcalloc (r->pool, str_uri_len * sizeof (u_char));
              if (u_uri == NULL)
                {
                  ngx_log_error (NGX_LOG_ERR,
                         r->connection->log,
                         0, "ngx_pcalloc no args u_uri error");
                  return NGX_DECLINED;
                }

              p =
                (ssl ? ngx_copy (u_uri, ngx_https_schema, con_schema_len)
                 : ngx_copy (u_uri, ngx_http_schema, con_schema_len));
              p = ngx_copy (p, idt[m].replace.data, idt[m].replace.len);
              p = ngx_copy (p, u_relative_uri, str_relative_uri_len);

              str_uri.len = str_uri_len;
              str_uri.data = u_uri;

              return ngx_cross_isp_redirect (r, str_uri);
            }
            }
        }
        }

      return NGX_DECLINED;
    }

    static long
    ngx_isp_store_binary_search (ngx_array_t data, ngx_uint_t ip)
    {
      long low = -1;
      long high = data.nelts;
      ngx_uint_t mid;
      ngx_isp_store_t *ist = data.elts;

      while (high - low > 1)
        {
          mid = (low + high) >> 1;

          if (ist[mid].ip_start > ip)
        {
          high = mid;
        }
          else
        {
          low = mid;
        }
        }

      if ((low == -1) || !(ist[low].ip_start <= ip && ip <= ist[low].ip_end))
        {
          return -1;
        }
      else
        {
          return low;
        }
    }

    static ngx_int_t
    ngx_cross_isp_redirect (ngx_http_request_t * r, ngx_str_t url)
    {
      ngx_buf_t *b;
      ngx_chain_t out;
      size_t ngx_http_302_page_len = ngx_strlen (ngx_http_302_page);

      r->headers_out.content_type.len = sizeof ("text/html") - 1;
      r->headers_out.content_type.data = (u_char *) "text/html";

      b = ngx_pcalloc (r->pool, sizeof (ngx_buf_t));

      out.buf = b;
      out.next = NULL;

      b->pos = ngx_http_302_page;
      b->last = ngx_http_302_page + ngx_http_302_page_len;
      b->memory = 1;
      b->last_buf = 1;

      r->headers_out.status = NGX_HTTP_MOVED_TEMPORARILY;
      r->headers_out.location = ngx_list_push (&r->headers_out.headers);
      r->headers_out.location->hash = 1;
      ngx_str_set (&r->headers_out.location->key, "Location");
      r->headers_out.location->value = url;
      r->headers_out.content_length_n = ngx_http_302_page_len;

      ngx_http_send_header (r);

      return ngx_http_write_filter (r, &out);
    }

    static void
    ngx_http_write_isp_cookie (ngx_http_request_t * r, u_char * cookie)
    {
      ngx_table_elt_t *set_cookie;

      set_cookie = ngx_list_push (&r->headers_out.headers);
      if (set_cookie == NULL)
        {
          return;
        }

      set_cookie->hash = 1;
      set_cookie->key.len = sizeof ("Set-Cookie") - 1;
      set_cookie->key.data = (u_char *) "Set-Cookie";
      set_cookie->value.len = ngx_strlen (cookie);
      set_cookie->value.data = cookie;
    }
    nginx cross isp module将会开源在http://code.google.com/p/easy-net/,后期将会对现有功能进行改进。

  • 相关阅读:
    远程桌面无法复制粘贴
    tns no listener
    10046 trace and sql
    MySQL replace into 用法(insert into 的增强版)
    USB接口大百科:看完你就分得清充电线了
    世界富人的财富诀窍
    php 23种设计模式的趣味解释
    23种设计模式
    设计模式的分类记忆方法
    项目管理基础:考试必过神之冲刺背诵口诀精简
  • 原文地址:https://www.cnblogs.com/TerryLiang/p/2028685.html
Copyright © 2011-2022 走看看