src/http/modules/ngx_http_uwsgi_module.c - nginx-1.31.4 nginx/ @ 8d9666701

Global variables defined

Data types defined

Functions defined

Source code


  1. /*
  2. * Copyright (C) Unbit S.a.s. 2009-2010
  3. * Copyright (C) 2008 Manlio Perillo (manlio.perillo@gmail.com)
  4. * Copyright (C) Igor Sysoev
  5. * Copyright (C) Nginx, Inc.
  6. */


  7. #include <ngx_config.h>
  8. #include <ngx_core.h>
  9. #include <ngx_http.h>


  10. typedef struct {
  11.     ngx_array_t                caches;  /* ngx_http_file_cache_t * */
  12. } ngx_http_uwsgi_main_conf_t;


  13. typedef struct {
  14.     ngx_array_t               *flushes;
  15.     ngx_array_t               *lengths;
  16.     ngx_array_t               *values;
  17.     ngx_uint_t                 number;
  18.     ngx_hash_t                 hash;
  19. } ngx_http_uwsgi_params_t;


  20. typedef struct {
  21.     ngx_http_upstream_conf_t   upstream;

  22.     ngx_http_uwsgi_params_t    params;
  23. #if (NGX_HTTP_CACHE)
  24.     ngx_http_uwsgi_params_t    params_cache;
  25. #endif
  26.     ngx_array_t               *params_source;

  27.     ngx_array_t               *uwsgi_lengths;
  28.     ngx_array_t               *uwsgi_values;

  29. #if (NGX_HTTP_CACHE)
  30.     ngx_http_complex_value_t   cache_key;
  31. #endif

  32.     ngx_str_t                  uwsgi_string;

  33.     ngx_uint_t                 modifier1;
  34.     ngx_uint_t                 modifier2;

  35. #if (NGX_HTTP_SSL)
  36.     ngx_uint_t                 ssl;
  37.     ngx_uint_t                 ssl_protocols;
  38.     ngx_str_t                  ssl_ciphers;
  39.     ngx_uint_t                 ssl_verify_depth;
  40.     ngx_str_t                  ssl_trusted_certificate;
  41.     ngx_str_t                  ssl_crl;
  42.     ngx_array_t               *ssl_conf_commands;
  43. #endif
  44. } ngx_http_uwsgi_loc_conf_t;


  45. static ngx_int_t ngx_http_uwsgi_eval(ngx_http_request_t *r,
  46.     ngx_http_uwsgi_loc_conf_t *uwcf);
  47. static ngx_int_t ngx_http_uwsgi_create_request(ngx_http_request_t *r);
  48. static ngx_int_t ngx_http_uwsgi_reinit_request(ngx_http_request_t *r);
  49. static ngx_int_t ngx_http_uwsgi_process_status_line(ngx_http_request_t *r);
  50. static ngx_int_t ngx_http_uwsgi_process_header(ngx_http_request_t *r);
  51. static ngx_int_t ngx_http_uwsgi_input_filter_init(void *data);
  52. static void ngx_http_uwsgi_abort_request(ngx_http_request_t *r);
  53. static void ngx_http_uwsgi_finalize_request(ngx_http_request_t *r,
  54.     ngx_int_t rc);

  55. static void *ngx_http_uwsgi_create_main_conf(ngx_conf_t *cf);
  56. static void *ngx_http_uwsgi_create_loc_conf(ngx_conf_t *cf);
  57. static char *ngx_http_uwsgi_merge_loc_conf(ngx_conf_t *cf, void *parent,
  58.     void *child);
  59. static ngx_int_t ngx_http_uwsgi_init_params(ngx_conf_t *cf,
  60.     ngx_http_uwsgi_loc_conf_t *conf, ngx_http_uwsgi_params_t *params,
  61.     ngx_keyval_t *default_params);

  62. static char *ngx_http_uwsgi_pass(ngx_conf_t *cf, ngx_command_t *cmd,
  63.     void *conf);
  64. static char *ngx_http_uwsgi_store(ngx_conf_t *cf, ngx_command_t *cmd,
  65.     void *conf);

  66. #if (NGX_HTTP_CACHE)
  67. static ngx_int_t ngx_http_uwsgi_create_key(ngx_http_request_t *r);
  68. static char *ngx_http_uwsgi_cache(ngx_conf_t *cf, ngx_command_t *cmd,
  69.     void *conf);
  70. static char *ngx_http_uwsgi_cache_key(ngx_conf_t *cf, ngx_command_t *cmd,
  71.     void *conf);
  72. #endif

  73. #if (NGX_HTTP_SSL)
  74. static char *ngx_http_uwsgi_ssl_certificate_cache(ngx_conf_t *cf,
  75.     ngx_command_t *cmd, void *conf);
  76. static char *ngx_http_uwsgi_ssl_password_file(ngx_conf_t *cf,
  77.     ngx_command_t *cmd, void *conf);
  78. static char *ngx_http_uwsgi_ssl_conf_command_check(ngx_conf_t *cf, void *post,
  79.     void *data);
  80. static ngx_int_t ngx_http_uwsgi_merge_ssl(ngx_conf_t *cf,
  81.     ngx_http_uwsgi_loc_conf_t *conf, ngx_http_uwsgi_loc_conf_t *prev);
  82. static ngx_int_t ngx_http_uwsgi_set_ssl(ngx_conf_t *cf,
  83.     ngx_http_uwsgi_loc_conf_t *uwcf);
  84. #endif


  85. static ngx_conf_num_bounds_t  ngx_http_uwsgi_modifier_bounds = {
  86.     ngx_conf_check_num_bounds, 0, 255
  87. };


  88. static ngx_conf_bitmask_t ngx_http_uwsgi_next_upstream_masks[] = {
  89.     { ngx_string("error"), NGX_HTTP_UPSTREAM_FT_ERROR },
  90.     { ngx_string("timeout"), NGX_HTTP_UPSTREAM_FT_TIMEOUT },
  91.     { ngx_string("invalid_header"), NGX_HTTP_UPSTREAM_FT_INVALID_HEADER },
  92.     { ngx_string("non_idempotent"), NGX_HTTP_UPSTREAM_FT_NON_IDEMPOTENT },
  93.     { ngx_string("http_500"), NGX_HTTP_UPSTREAM_FT_HTTP_500 },
  94.     { ngx_string("http_503"), NGX_HTTP_UPSTREAM_FT_HTTP_503 },
  95.     { ngx_string("http_403"), NGX_HTTP_UPSTREAM_FT_HTTP_403 },
  96.     { ngx_string("http_404"), NGX_HTTP_UPSTREAM_FT_HTTP_404 },
  97.     { ngx_string("http_429"), NGX_HTTP_UPSTREAM_FT_HTTP_429 },
  98.     { ngx_string("updating"), NGX_HTTP_UPSTREAM_FT_UPDATING },
  99.     { ngx_string("off"), NGX_HTTP_UPSTREAM_FT_OFF },
  100.     { ngx_null_string, 0 }
  101. };


  102. #if (NGX_HTTP_SSL)

  103. static ngx_conf_bitmask_t  ngx_http_uwsgi_ssl_protocols[] = {
  104.     { ngx_string("SSLv2"), NGX_SSL_SSLv2 },
  105.     { ngx_string("SSLv3"), NGX_SSL_SSLv3 },
  106.     { ngx_string("TLSv1"), NGX_SSL_TLSv1 },
  107.     { ngx_string("TLSv1.1"), NGX_SSL_TLSv1_1 },
  108.     { ngx_string("TLSv1.2"), NGX_SSL_TLSv1_2 },
  109.     { ngx_string("TLSv1.3"), NGX_SSL_TLSv1_3 },
  110.     { ngx_null_string, 0 }
  111. };

  112. static ngx_conf_post_t  ngx_http_uwsgi_ssl_conf_command_post =
  113.     { ngx_http_uwsgi_ssl_conf_command_check };

  114. #endif


  115. ngx_module_t  ngx_http_uwsgi_module;


  116. static ngx_command_t ngx_http_uwsgi_commands[] = {

  117.     { ngx_string("uwsgi_pass"),
  118.       NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE1,
  119.       ngx_http_uwsgi_pass,
  120.       NGX_HTTP_LOC_CONF_OFFSET,
  121.       0,
  122.       NULL },

  123.     { ngx_string("uwsgi_modifier1"),
  124.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  125.       ngx_conf_set_num_slot,
  126.       NGX_HTTP_LOC_CONF_OFFSET,
  127.       offsetof(ngx_http_uwsgi_loc_conf_t, modifier1),
  128.       &ngx_http_uwsgi_modifier_bounds },

  129.     { ngx_string("uwsgi_modifier2"),
  130.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  131.       ngx_conf_set_num_slot,
  132.       NGX_HTTP_LOC_CONF_OFFSET,
  133.       offsetof(ngx_http_uwsgi_loc_conf_t, modifier2),
  134.       &ngx_http_uwsgi_modifier_bounds },

  135.     { ngx_string("uwsgi_store"),
  136.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  137.       ngx_http_uwsgi_store,
  138.       NGX_HTTP_LOC_CONF_OFFSET,
  139.       0,
  140.       NULL },

  141.     { ngx_string("uwsgi_store_access"),
  142.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE123,
  143.       ngx_conf_set_access_slot,
  144.       NGX_HTTP_LOC_CONF_OFFSET,
  145.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.store_access),
  146.       NULL },

  147.     { ngx_string("uwsgi_buffering"),
  148.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
  149.       ngx_conf_set_flag_slot,
  150.       NGX_HTTP_LOC_CONF_OFFSET,
  151.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.buffering),
  152.       NULL },

  153.     { ngx_string("uwsgi_request_buffering"),
  154.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
  155.       ngx_conf_set_flag_slot,
  156.       NGX_HTTP_LOC_CONF_OFFSET,
  157.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.request_buffering),
  158.       NULL },

  159.     { ngx_string("uwsgi_ignore_client_abort"),
  160.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
  161.       ngx_conf_set_flag_slot,
  162.       NGX_HTTP_LOC_CONF_OFFSET,
  163.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.ignore_client_abort),
  164.       NULL },

  165.     { ngx_string("uwsgi_bind"),
  166.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12,
  167.       ngx_http_upstream_bind_set_slot,
  168.       NGX_HTTP_LOC_CONF_OFFSET,
  169.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.local),
  170.       NULL },

  171.     { ngx_string("uwsgi_socket_keepalive"),
  172.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
  173.       ngx_conf_set_flag_slot,
  174.       NGX_HTTP_LOC_CONF_OFFSET,
  175.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.socket_keepalive),
  176.       NULL },

  177.     { ngx_string("uwsgi_socket_rcvbuf"),
  178.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  179.       ngx_conf_set_size_slot,
  180.       NGX_HTTP_LOC_CONF_OFFSET,
  181.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.socket_rcvbuf),
  182.       NULL },

  183.     { ngx_string("uwsgi_socket_sndbuf"),
  184.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  185.       ngx_conf_set_size_slot,
  186.       NGX_HTTP_LOC_CONF_OFFSET,
  187.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.socket_sndbuf),
  188.       NULL },

  189.     { ngx_string("uwsgi_connect_timeout"),
  190.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  191.       ngx_conf_set_msec_slot,
  192.       NGX_HTTP_LOC_CONF_OFFSET,
  193.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.connect_timeout),
  194.       NULL },

  195.     { ngx_string("uwsgi_send_timeout"),
  196.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  197.       ngx_conf_set_msec_slot,
  198.       NGX_HTTP_LOC_CONF_OFFSET,
  199.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.send_timeout),
  200.       NULL },

  201.     { ngx_string("uwsgi_buffer_size"),
  202.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  203.       ngx_conf_set_size_slot,
  204.       NGX_HTTP_LOC_CONF_OFFSET,
  205.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.buffer_size),
  206.       NULL },

  207.     { ngx_string("uwsgi_pass_request_headers"),
  208.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
  209.       ngx_conf_set_flag_slot,
  210.       NGX_HTTP_LOC_CONF_OFFSET,
  211.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.pass_request_headers),
  212.       NULL },

  213.     { ngx_string("uwsgi_pass_request_body"),
  214.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
  215.       ngx_conf_set_flag_slot,
  216.       NGX_HTTP_LOC_CONF_OFFSET,
  217.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.pass_request_body),
  218.       NULL },

  219.     { ngx_string("uwsgi_intercept_errors"),
  220.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
  221.       ngx_conf_set_flag_slot,
  222.       NGX_HTTP_LOC_CONF_OFFSET,
  223.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.intercept_errors),
  224.       NULL },

  225.     { ngx_string("uwsgi_read_timeout"),
  226.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  227.       ngx_conf_set_msec_slot,
  228.       NGX_HTTP_LOC_CONF_OFFSET,
  229.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.read_timeout),
  230.       NULL },

  231.     { ngx_string("uwsgi_buffers"),
  232.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
  233.       ngx_conf_set_bufs_slot,
  234.       NGX_HTTP_LOC_CONF_OFFSET,
  235.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.bufs),
  236.       NULL },

  237.     { ngx_string("uwsgi_busy_buffers_size"),
  238.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  239.       ngx_conf_set_size_slot,
  240.       NGX_HTTP_LOC_CONF_OFFSET,
  241.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.busy_buffers_size_conf),
  242.       NULL },

  243.     { ngx_string("uwsgi_force_ranges"),
  244.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
  245.       ngx_conf_set_flag_slot,
  246.       NGX_HTTP_LOC_CONF_OFFSET,
  247.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.force_ranges),
  248.       NULL },

  249.     { ngx_string("uwsgi_limit_rate"),
  250.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  251.       ngx_http_set_complex_value_size_slot,
  252.       NGX_HTTP_LOC_CONF_OFFSET,
  253.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.limit_rate),
  254.       NULL },

  255. #if (NGX_HTTP_CACHE)

  256.     { ngx_string("uwsgi_cache"),
  257.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  258.       ngx_http_uwsgi_cache,
  259.       NGX_HTTP_LOC_CONF_OFFSET,
  260.       0,
  261.       NULL },

  262.     { ngx_string("uwsgi_cache_key"),
  263.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  264.       ngx_http_uwsgi_cache_key,
  265.       NGX_HTTP_LOC_CONF_OFFSET,
  266.       0,
  267.       NULL },

  268.     { ngx_string("uwsgi_cache_path"),
  269.       NGX_HTTP_MAIN_CONF|NGX_CONF_2MORE,
  270.       ngx_http_file_cache_set_slot,
  271.       NGX_HTTP_MAIN_CONF_OFFSET,
  272.       offsetof(ngx_http_uwsgi_main_conf_t, caches),
  273.       &ngx_http_uwsgi_module },

  274.     { ngx_string("uwsgi_cache_bypass"),
  275.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
  276.       ngx_http_set_predicate_slot,
  277.       NGX_HTTP_LOC_CONF_OFFSET,
  278.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_bypass),
  279.       NULL },

  280.     { ngx_string("uwsgi_no_cache"),
  281.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
  282.       ngx_http_set_predicate_slot,
  283.       NGX_HTTP_LOC_CONF_OFFSET,
  284.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.no_cache),
  285.       NULL },

  286.     { ngx_string("uwsgi_cache_valid"),
  287.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
  288.       ngx_http_file_cache_valid_set_slot,
  289.       NGX_HTTP_LOC_CONF_OFFSET,
  290.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_valid),
  291.       NULL },

  292.     { ngx_string("uwsgi_cache_min_uses"),
  293.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  294.       ngx_conf_set_num_slot,
  295.       NGX_HTTP_LOC_CONF_OFFSET,
  296.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_min_uses),
  297.       NULL },

  298.     { ngx_string("uwsgi_cache_max_range_offset"),
  299.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  300.       ngx_conf_set_off_slot,
  301.       NGX_HTTP_LOC_CONF_OFFSET,
  302.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_max_range_offset),
  303.       NULL },

  304.     { ngx_string("uwsgi_cache_use_stale"),
  305.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
  306.       ngx_conf_set_bitmask_slot,
  307.       NGX_HTTP_LOC_CONF_OFFSET,
  308.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_use_stale),
  309.       &ngx_http_uwsgi_next_upstream_masks },

  310.     { ngx_string("uwsgi_cache_methods"),
  311.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
  312.       ngx_conf_set_bitmask_slot,
  313.       NGX_HTTP_LOC_CONF_OFFSET,
  314.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_methods),
  315.       &ngx_http_upstream_cache_method_mask },

  316.     { ngx_string("uwsgi_cache_lock"),
  317.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
  318.       ngx_conf_set_flag_slot,
  319.       NGX_HTTP_LOC_CONF_OFFSET,
  320.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_lock),
  321.       NULL },

  322.     { ngx_string("uwsgi_cache_lock_timeout"),
  323.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  324.       ngx_conf_set_msec_slot,
  325.       NGX_HTTP_LOC_CONF_OFFSET,
  326.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_lock_timeout),
  327.       NULL },

  328.     { ngx_string("uwsgi_cache_lock_age"),
  329.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  330.       ngx_conf_set_msec_slot,
  331.       NGX_HTTP_LOC_CONF_OFFSET,
  332.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_lock_age),
  333.       NULL },

  334.     { ngx_string("uwsgi_cache_revalidate"),
  335.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
  336.       ngx_conf_set_flag_slot,
  337.       NGX_HTTP_LOC_CONF_OFFSET,
  338.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_revalidate),
  339.       NULL },

  340.     { ngx_string("uwsgi_cache_background_update"),
  341.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  342.       ngx_conf_set_flag_slot,
  343.       NGX_HTTP_LOC_CONF_OFFSET,
  344.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_background_update),
  345.       NULL },

  346. #endif

  347.     { ngx_string("uwsgi_temp_path"),
  348.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1234,
  349.       ngx_conf_set_path_slot,
  350.       NGX_HTTP_LOC_CONF_OFFSET,
  351.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.temp_path),
  352.       NULL },

  353.     { ngx_string("uwsgi_max_temp_file_size"),
  354.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  355.       ngx_conf_set_size_slot,
  356.       NGX_HTTP_LOC_CONF_OFFSET,
  357.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.max_temp_file_size_conf),
  358.       NULL },

  359.     { ngx_string("uwsgi_temp_file_write_size"),
  360.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  361.       ngx_conf_set_size_slot,
  362.       NGX_HTTP_LOC_CONF_OFFSET,
  363.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.temp_file_write_size_conf),
  364.       NULL },

  365.     { ngx_string("uwsgi_next_upstream"),
  366.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
  367.       ngx_conf_set_bitmask_slot,
  368.       NGX_HTTP_LOC_CONF_OFFSET,
  369.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.next_upstream),
  370.       &ngx_http_uwsgi_next_upstream_masks },

  371.     { ngx_string("uwsgi_next_upstream_tries"),
  372.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  373.       ngx_conf_set_num_slot,
  374.       NGX_HTTP_LOC_CONF_OFFSET,
  375.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.next_upstream_tries),
  376.       NULL },

  377.     { ngx_string("uwsgi_next_upstream_timeout"),
  378.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  379.       ngx_conf_set_msec_slot,
  380.       NGX_HTTP_LOC_CONF_OFFSET,
  381.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.next_upstream_timeout),
  382.       NULL },

  383.     { ngx_string("uwsgi_param"),
  384.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE23,
  385.       ngx_http_upstream_param_set_slot,
  386.       NGX_HTTP_LOC_CONF_OFFSET,
  387.       offsetof(ngx_http_uwsgi_loc_conf_t, params_source),
  388.       NULL },

  389.     { ngx_string("uwsgi_string"),
  390.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  391.       ngx_conf_set_str_slot,
  392.       NGX_HTTP_LOC_CONF_OFFSET,
  393.       offsetof(ngx_http_uwsgi_loc_conf_t, uwsgi_string),
  394.       NULL },

  395.     { ngx_string("uwsgi_pass_header"),
  396.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  397.       ngx_conf_set_str_array_slot,
  398.       NGX_HTTP_LOC_CONF_OFFSET,
  399.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.pass_headers),
  400.       NULL },

  401.     { ngx_string("uwsgi_hide_header"),
  402.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  403.       ngx_conf_set_str_array_slot,
  404.       NGX_HTTP_LOC_CONF_OFFSET,
  405.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.hide_headers),
  406.       NULL },

  407.     { ngx_string("uwsgi_ignore_headers"),
  408.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
  409.       ngx_conf_set_bitmask_slot,
  410.       NGX_HTTP_LOC_CONF_OFFSET,
  411.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.ignore_headers),
  412.       &ngx_http_upstream_ignore_headers_masks },

  413. #if (NGX_HTTP_SSL)

  414.     { ngx_string("uwsgi_ssl_session_reuse"),
  415.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
  416.       ngx_conf_set_flag_slot,
  417.       NGX_HTTP_LOC_CONF_OFFSET,
  418.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.ssl_session_reuse),
  419.       NULL },

  420.     { ngx_string("uwsgi_ssl_protocols"),
  421.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
  422.       ngx_conf_set_bitmask_slot,
  423.       NGX_HTTP_LOC_CONF_OFFSET,
  424.       offsetof(ngx_http_uwsgi_loc_conf_t, ssl_protocols),
  425.       &ngx_http_uwsgi_ssl_protocols },

  426.     { ngx_string("uwsgi_ssl_ciphers"),
  427.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  428.       ngx_conf_set_str_slot,
  429.       NGX_HTTP_LOC_CONF_OFFSET,
  430.       offsetof(ngx_http_uwsgi_loc_conf_t, ssl_ciphers),
  431.       NULL },

  432.     { ngx_string("uwsgi_ssl_name"),
  433.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  434.       ngx_http_set_complex_value_slot,
  435.       NGX_HTTP_LOC_CONF_OFFSET,
  436.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.ssl_name),
  437.       NULL },

  438.     { ngx_string("uwsgi_ssl_server_name"),
  439.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
  440.       ngx_conf_set_flag_slot,
  441.       NGX_HTTP_LOC_CONF_OFFSET,
  442.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.ssl_server_name),
  443.       NULL },

  444.     { ngx_string("uwsgi_ssl_verify"),
  445.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
  446.       ngx_conf_set_flag_slot,
  447.       NGX_HTTP_LOC_CONF_OFFSET,
  448.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.ssl_verify),
  449.       NULL },

  450.     { ngx_string("uwsgi_ssl_verify_depth"),
  451.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  452.       ngx_conf_set_num_slot,
  453.       NGX_HTTP_LOC_CONF_OFFSET,
  454.       offsetof(ngx_http_uwsgi_loc_conf_t, ssl_verify_depth),
  455.       NULL },

  456.     { ngx_string("uwsgi_ssl_trusted_certificate"),
  457.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  458.       ngx_conf_set_str_slot,
  459.       NGX_HTTP_LOC_CONF_OFFSET,
  460.       offsetof(ngx_http_uwsgi_loc_conf_t, ssl_trusted_certificate),
  461.       NULL },

  462.     { ngx_string("uwsgi_ssl_crl"),
  463.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  464.       ngx_conf_set_str_slot,
  465.       NGX_HTTP_LOC_CONF_OFFSET,
  466.       offsetof(ngx_http_uwsgi_loc_conf_t, ssl_crl),
  467.       NULL },

  468.     { ngx_string("uwsgi_ssl_certificate"),
  469.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  470.       ngx_http_set_complex_value_zero_slot,
  471.       NGX_HTTP_LOC_CONF_OFFSET,
  472.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.ssl_certificate),
  473.       NULL },

  474.     { ngx_string("uwsgi_ssl_certificate_key"),
  475.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  476.       ngx_http_set_complex_value_zero_slot,
  477.       NGX_HTTP_LOC_CONF_OFFSET,
  478.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.ssl_certificate_key),
  479.       NULL },

  480.     { ngx_string("uwsgi_ssl_certificate_cache"),
  481.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE123,
  482.       ngx_http_uwsgi_ssl_certificate_cache,
  483.       NGX_HTTP_LOC_CONF_OFFSET,
  484.       0,
  485.       NULL },

  486.     { ngx_string("uwsgi_ssl_password_file"),
  487.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  488.       ngx_http_uwsgi_ssl_password_file,
  489.       NGX_HTTP_LOC_CONF_OFFSET,
  490.       0,
  491.       NULL },

  492.     { ngx_string("uwsgi_ssl_conf_command"),
  493.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
  494.       ngx_conf_set_keyval_slot,
  495.       NGX_HTTP_LOC_CONF_OFFSET,
  496.       offsetof(ngx_http_uwsgi_loc_conf_t, ssl_conf_commands),
  497.       &ngx_http_uwsgi_ssl_conf_command_post },

  498. #endif

  499.       ngx_null_command
  500. };


  501. static ngx_http_module_t ngx_http_uwsgi_module_ctx = {
  502.     NULL,                                  /* preconfiguration */
  503.     NULL,                                  /* postconfiguration */

  504.     ngx_http_uwsgi_create_main_conf,       /* create main configuration */
  505.     NULL,                                  /* init main configuration */

  506.     NULL,                                  /* create server configuration */
  507.     NULL,                                  /* merge server configuration */

  508.     ngx_http_uwsgi_create_loc_conf,        /* create location configuration */
  509.     ngx_http_uwsgi_merge_loc_conf          /* merge location configuration */
  510. };


  511. ngx_module_t ngx_http_uwsgi_module = {
  512.     NGX_MODULE_V1,
  513.     &ngx_http_uwsgi_module_ctx,            /* module context */
  514.     ngx_http_uwsgi_commands,               /* module directives */
  515.     NGX_HTTP_MODULE,                       /* module type */
  516.     NULL,                                  /* init master */
  517.     NULL,                                  /* init module */
  518.     NULL,                                  /* init process */
  519.     NULL,                                  /* init thread */
  520.     NULL,                                  /* exit thread */
  521.     NULL,                                  /* exit process */
  522.     NULL,                                  /* exit master */
  523.     NGX_MODULE_V1_PADDING
  524. };


  525. static ngx_str_t ngx_http_uwsgi_hide_headers[] = {
  526.     ngx_string("X-Accel-Expires"),
  527.     ngx_string("X-Accel-Redirect"),
  528.     ngx_string("X-Accel-Limit-Rate"),
  529.     ngx_string("X-Accel-Buffering"),
  530.     ngx_string("X-Accel-Charset"),
  531.     ngx_null_string
  532. };


  533. static ngx_keyval_t  ngx_http_uwsgi_headers[] = {
  534.     { ngx_string("HTTP_HOST"),
  535.       ngx_string("$host$is_request_port$request_port") },
  536.     { ngx_null_string, ngx_null_string }
  537. };


  538. #if (NGX_HTTP_CACHE)

  539. static ngx_keyval_t  ngx_http_uwsgi_cache_headers[] = {
  540.     { ngx_string("HTTP_HOST"),
  541.       ngx_string("$host$is_request_port$request_port") },
  542.     { ngx_string("HTTP_IF_MODIFIED_SINCE"),
  543.       ngx_string("$upstream_cache_last_modified") },
  544.     { ngx_string("HTTP_IF_UNMODIFIED_SINCE"), ngx_string("") },
  545.     { ngx_string("HTTP_IF_NONE_MATCH"), ngx_string("$upstream_cache_etag") },
  546.     { ngx_string("HTTP_IF_MATCH"), ngx_string("") },
  547.     { ngx_string("HTTP_RANGE"), ngx_string("") },
  548.     { ngx_string("HTTP_IF_RANGE"), ngx_string("") },
  549.     { ngx_null_string, ngx_null_string }
  550. };

  551. #endif


  552. static ngx_path_init_t ngx_http_uwsgi_temp_path = {
  553.     ngx_string(NGX_HTTP_UWSGI_TEMP_PATH), { 1, 2, 0 }
  554. };


  555. static ngx_int_t
  556. ngx_http_uwsgi_handler(ngx_http_request_t *r)
  557. {
  558.     ngx_int_t                    rc;
  559.     ngx_http_status_t           *status;
  560.     ngx_http_upstream_t         *u;
  561.     ngx_http_uwsgi_loc_conf_t   *uwcf;
  562. #if (NGX_HTTP_CACHE)
  563.     ngx_http_uwsgi_main_conf_t  *uwmcf;
  564. #endif

  565.     if (ngx_http_upstream_create(r) != NGX_OK) {
  566.         return NGX_HTTP_INTERNAL_SERVER_ERROR;
  567.     }

  568.     status = ngx_pcalloc(r->pool, sizeof(ngx_http_status_t));
  569.     if (status == NULL) {
  570.         return NGX_HTTP_INTERNAL_SERVER_ERROR;
  571.     }

  572.     ngx_http_set_ctx(r, status, ngx_http_uwsgi_module);

  573.     uwcf = ngx_http_get_module_loc_conf(r, ngx_http_uwsgi_module);

  574.     u = r->upstream;

  575.     if (uwcf->uwsgi_lengths == NULL) {

  576. #if (NGX_HTTP_SSL)
  577.         u->ssl = uwcf->ssl;

  578.         if (u->ssl) {
  579.             ngx_str_set(&u->schema, "suwsgi://");

  580.         } else {
  581.             ngx_str_set(&u->schema, "uwsgi://");
  582.         }
  583. #else
  584.         ngx_str_set(&u->schema, "uwsgi://");
  585. #endif

  586.     } else {
  587.         if (ngx_http_uwsgi_eval(r, uwcf) != NGX_OK) {
  588.             return NGX_HTTP_INTERNAL_SERVER_ERROR;
  589.         }
  590.     }

  591.     u->output.tag = (ngx_buf_tag_t) &ngx_http_uwsgi_module;

  592.     u->conf = &uwcf->upstream;

  593. #if (NGX_HTTP_CACHE)
  594.     uwmcf = ngx_http_get_module_main_conf(r, ngx_http_uwsgi_module);

  595.     u->caches = &uwmcf->caches;
  596.     u->create_key = ngx_http_uwsgi_create_key;
  597. #endif

  598.     u->create_request = ngx_http_uwsgi_create_request;
  599.     u->reinit_request = ngx_http_uwsgi_reinit_request;
  600.     u->process_header = ngx_http_uwsgi_process_status_line;
  601.     u->abort_request = ngx_http_uwsgi_abort_request;
  602.     u->finalize_request = ngx_http_uwsgi_finalize_request;
  603.     r->state = 0;

  604.     u->buffering = uwcf->upstream.buffering;

  605.     u->pipe = ngx_pcalloc(r->pool, sizeof(ngx_event_pipe_t));
  606.     if (u->pipe == NULL) {
  607.         return NGX_HTTP_INTERNAL_SERVER_ERROR;
  608.     }

  609.     u->pipe->input_filter = ngx_event_pipe_copy_input_filter;
  610.     u->pipe->input_ctx = r;

  611.     u->input_filter_init = ngx_http_uwsgi_input_filter_init;
  612.     u->input_filter = ngx_http_upstream_non_buffered_filter;
  613.     u->input_filter_ctx = r;

  614.     if (!uwcf->upstream.request_buffering
  615.         && uwcf->upstream.pass_request_body
  616.         && !r->headers_in.chunked)
  617.     {
  618.         r->request_body_no_buffering = 1;
  619.     }

  620.     rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init);

  621.     if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
  622.         return rc;
  623.     }

  624.     return NGX_DONE;
  625. }


  626. static ngx_int_t
  627. ngx_http_uwsgi_eval(ngx_http_request_t *r, ngx_http_uwsgi_loc_conf_t * uwcf)
  628. {
  629.     size_t                add;
  630.     ngx_url_t             url;
  631.     ngx_http_upstream_t  *u;

  632.     ngx_memzero(&url, sizeof(ngx_url_t));

  633.     if (ngx_http_script_run(r, &url.url, uwcf->uwsgi_lengths->elts, 0,
  634.                             uwcf->uwsgi_values->elts)
  635.         == NULL)
  636.     {
  637.         return NGX_ERROR;
  638.     }

  639.     if (url.url.len > 8
  640.         && ngx_strncasecmp(url.url.data, (u_char *) "uwsgi://", 8) == 0)
  641.     {
  642.         add = 8;

  643.     } else if (url.url.len > 9
  644.                && ngx_strncasecmp(url.url.data, (u_char *) "suwsgi://", 9) == 0)
  645.     {

  646. #if (NGX_HTTP_SSL)
  647.         add = 9;
  648.         r->upstream->ssl = 1;
  649. #else
  650.         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  651.                       "suwsgi protocol requires SSL support");
  652.         return NGX_ERROR;
  653. #endif

  654.     } else {
  655.         add = 0;
  656.     }

  657.     u = r->upstream;

  658.     if (add) {
  659.         u->schema.len = add;
  660.         u->schema.data = url.url.data;

  661.         url.url.data += add;
  662.         url.url.len -= add;

  663.     } else {
  664.         ngx_str_set(&u->schema, "uwsgi://");
  665.     }

  666.     url.no_resolve = 1;

  667.     if (ngx_parse_url(r->pool, &url) != NGX_OK) {
  668.         if (url.err) {
  669.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  670.                           "%s in upstream \"%V\"", url.err, &url.url);
  671.         }

  672.         return NGX_ERROR;
  673.     }

  674.     u->resolved = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_resolved_t));
  675.     if (u->resolved == NULL) {
  676.         return NGX_ERROR;
  677.     }

  678.     if (url.addrs) {
  679.         u->resolved->sockaddr = url.addrs[0].sockaddr;
  680.         u->resolved->socklen = url.addrs[0].socklen;
  681.         u->resolved->name = url.addrs[0].name;
  682.         u->resolved->naddrs = 1;
  683.     }

  684.     u->resolved->host = url.host;
  685.     u->resolved->port = url.port;
  686.     u->resolved->no_port = url.no_port;

  687.     return NGX_OK;
  688. }


  689. #if (NGX_HTTP_CACHE)

  690. static ngx_int_t
  691. ngx_http_uwsgi_create_key(ngx_http_request_t *r)
  692. {
  693.     ngx_str_t                  *key;
  694.     ngx_http_uwsgi_loc_conf_t  *uwcf;

  695.     key = ngx_array_push(&r->cache->keys);
  696.     if (key == NULL) {
  697.         return NGX_ERROR;
  698.     }

  699.     uwcf = ngx_http_get_module_loc_conf(r, ngx_http_uwsgi_module);

  700.     if (ngx_http_complex_value(r, &uwcf->cache_key, key) != NGX_OK) {
  701.         return NGX_ERROR;
  702.     }

  703.     return NGX_OK;
  704. }

  705. #endif


  706. static ngx_int_t
  707. ngx_http_uwsgi_create_request(ngx_http_request_t *r)
  708. {
  709.     u_char                        ch, sep, *lowcase_key;
  710.     size_t                        key_len, val_len, len, params_len, allocated;
  711.     ngx_uint_t                    i, n, hash, skip_empty, header_params;
  712.     ngx_buf_t                    *b;
  713.     ngx_chain_t                  *cl, *body;
  714.     ngx_list_part_t              *part;
  715.     ngx_table_elt_t              *header, *hn, **ignored;
  716.     ngx_http_uwsgi_params_t      *params;
  717.     ngx_http_script_code_pt       code;
  718.     ngx_http_script_engine_t      e, le;
  719.     ngx_http_uwsgi_loc_conf_t    *uwcf;
  720.     ngx_http_script_len_code_pt   lcode;

  721.     len = 0;
  722.     params_len = 0;
  723.     header_params = 0;
  724.     ignored = NULL;

  725.     uwcf = ngx_http_get_module_loc_conf(r, ngx_http_uwsgi_module);

  726. #if (NGX_HTTP_CACHE)
  727.     params = r->upstream->cacheable ? &uwcf->params_cache : &uwcf->params;
  728. #else
  729.     params = &uwcf->params;
  730. #endif

  731.     if (params->lengths) {
  732.         ngx_memzero(&le, sizeof(ngx_http_script_engine_t));

  733.         ngx_http_script_flush_no_cacheable_variables(r, params->flushes);
  734.         le.flushed = 1;

  735.         le.ip = params->lengths->elts;
  736.         le.request = r;

  737.         while (*(uintptr_t *) le.ip) {

  738.             lcode = *(ngx_http_script_len_code_pt *) le.ip;
  739.             key_len = lcode(&le);

  740.             lcode = *(ngx_http_script_len_code_pt *) le.ip;
  741.             skip_empty = lcode(&le);

  742.             for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode(&le)) {
  743.                 lcode = *(ngx_http_script_len_code_pt *) le.ip;
  744.             }
  745.             le.ip += sizeof(uintptr_t);

  746.             if (skip_empty && val_len == 0) {
  747.                 continue;
  748.             }

  749.             params_len += 2 + key_len + 2 + val_len;
  750.         }

  751.         len += params_len;
  752.     }

  753.     if (uwcf->upstream.pass_request_headers) {

  754.         allocated = 0;
  755.         lowcase_key = NULL;

  756.         if (ngx_http_link_multi_headers(r) != NGX_OK) {
  757.             return NGX_ERROR;
  758.         }

  759.         if (params->number || r->headers_in.multi) {
  760.             n = 0;
  761.             part = &r->headers_in.headers.part;

  762.             while (part) {
  763.                 n += part->nelts;
  764.                 part = part->next;
  765.             }

  766.             ignored = ngx_palloc(r->pool, n * sizeof(void *));
  767.             if (ignored == NULL) {
  768.                 return NGX_ERROR;
  769.             }
  770.         }

  771.         part = &r->headers_in.headers.part;
  772.         header = part->elts;

  773.         for (i = 0; /* void */ ; i++) {

  774.             if (i >= part->nelts) {
  775.                 if (part->next == NULL) {
  776.                     break;
  777.                 }

  778.                 part = part->next;
  779.                 header = part->elts;
  780.                 i = 0;
  781.             }

  782.             for (n = 0; n < header_params; n++) {
  783.                 if (&header[i] == ignored[n]) {
  784.                     goto next_length;
  785.                 }
  786.             }

  787.             if (params->number) {
  788.                 if (allocated < header[i].key.len) {
  789.                     allocated = header[i].key.len + 16;
  790.                     lowcase_key = ngx_pnalloc(r->pool, allocated);
  791.                     if (lowcase_key == NULL) {
  792.                         return NGX_ERROR;
  793.                     }
  794.                 }

  795.                 hash = 0;

  796.                 for (n = 0; n < header[i].key.len; n++) {
  797.                     ch = header[i].key.data[n];

  798.                     if (ch >= 'A' && ch <= 'Z') {
  799.                         ch |= 0x20;

  800.                     } else if (ch == '-') {
  801.                         ch = '_';
  802.                     }

  803.                     hash = ngx_hash(hash, ch);
  804.                     lowcase_key[n] = ch;
  805.                 }

  806.                 if (ngx_hash_find(&params->hash, hash, lowcase_key, n)) {
  807.                     ignored[header_params++] = &header[i];
  808.                     continue;
  809.                 }
  810.             }

  811.             len += 2 + sizeof("HTTP_") - 1 + header[i].key.len
  812.                  + 2 + header[i].value.len;

  813.             for (hn = header[i].next; hn; hn = hn->next) {
  814.                 len += hn->value.len + 2;
  815.                 ignored[header_params++] = hn;
  816.             }

  817.         next_length:

  818.             continue;
  819.         }
  820.     }

  821.     len += uwcf->uwsgi_string.len;

  822. #if 0
  823.     /* allow custom uwsgi packet */
  824.     if (len > 0 && len < 2) {
  825.         ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
  826.                       "uwsgi request is too little: %uz", len);
  827.         return NGX_ERROR;
  828.     }
  829. #endif

  830.     if (len > 65535) {
  831.         ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
  832.                       "uwsgi request is too big: %uz", len);
  833.         return NGX_ERROR;
  834.     }

  835.     b = ngx_create_temp_buf(r->pool, len + 4);
  836.     if (b == NULL) {
  837.         return NGX_ERROR;
  838.     }

  839.     cl = ngx_alloc_chain_link(r->pool);
  840.     if (cl == NULL) {
  841.         return NGX_ERROR;
  842.     }

  843.     cl->buf = b;

  844.     *b->last++ = (u_char) uwcf->modifier1;
  845.     *b->last++ = (u_char) (len & 0xff);
  846.     *b->last++ = (u_char) ((len >> 8) & 0xff);
  847.     *b->last++ = (u_char) uwcf->modifier2;

  848.     if (params->lengths) {
  849.         ngx_memzero(&e, sizeof(ngx_http_script_engine_t));

  850.         e.ip = params->values->elts;
  851.         e.pos = b->last;
  852.         e.end = b->last + params_len;
  853.         e.request = r;
  854.         e.flushed = 1;

  855.         le.ip = params->lengths->elts;

  856.         while (*(uintptr_t *) le.ip) {

  857.             lcode = *(ngx_http_script_len_code_pt *) le.ip;
  858.             key_len = (u_char) lcode(&le);

  859.             lcode = *(ngx_http_script_len_code_pt *) le.ip;
  860.             skip_empty = lcode(&le);

  861.             for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode(&le)) {
  862.                 lcode = *(ngx_http_script_len_code_pt *) le.ip;
  863.             }
  864.             le.ip += sizeof(uintptr_t);

  865.             if (skip_empty && val_len == 0) {
  866.                 e.skip = 1;

  867.                 while (*(uintptr_t *) e.ip) {
  868.                     code = *(ngx_http_script_code_pt *) e.ip;
  869.                     code((ngx_http_script_engine_t *) &e);
  870.                 }
  871.                 e.ip += sizeof(uintptr_t);

  872.                 e.skip = 0;

  873.                 continue;
  874.             }

  875.             if (ngx_http_script_check_length(&e, 2) != NGX_OK) {
  876.                 return NGX_ERROR;
  877.             }

  878.             *e.pos++ = (u_char) (key_len & 0xff);
  879.             *e.pos++ = (u_char) ((key_len >> 8) & 0xff);

  880.             code = *(ngx_http_script_code_pt *) e.ip;
  881.             code((ngx_http_script_engine_t *) &e);

  882.             if (e.status) {
  883.                 return NGX_ERROR;
  884.             }

  885.             if (ngx_http_script_check_length(&e, 2) != NGX_OK) {
  886.                 return NGX_ERROR;
  887.             }

  888.             *e.pos++ = (u_char) (val_len & 0xff);
  889.             *e.pos++ = (u_char) ((val_len >> 8) & 0xff);

  890.             while (*(uintptr_t *) e.ip) {
  891.                 code = *(ngx_http_script_code_pt *) e.ip;
  892.                 code((ngx_http_script_engine_t *) &e);
  893.             }

  894.             if (e.status) {
  895.                 return NGX_ERROR;
  896.             }

  897.             e.ip += sizeof(uintptr_t);

  898.             ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  899.                            "uwsgi param: \"%*s: %*s\"",
  900.                            key_len, e.pos - (key_len + 2 + val_len),
  901.                            val_len, e.pos - val_len);
  902.         }

  903.         if (e.pos != e.end) {
  904.             ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
  905.                           "uwsgi request length mismatch");
  906.             return NGX_ERROR;
  907.         }

  908.         b->last = e.pos;
  909.     }

  910.     if (uwcf->upstream.pass_request_headers) {

  911.         part = &r->headers_in.headers.part;
  912.         header = part->elts;

  913.         for (i = 0; /* void */ ; i++) {

  914.             if (i >= part->nelts) {
  915.                 if (part->next == NULL) {
  916.                     break;
  917.                 }

  918.                 part = part->next;
  919.                 header = part->elts;
  920.                 i = 0;
  921.             }

  922.             for (n = 0; n < header_params; n++) {
  923.                 if (&header[i] == ignored[n]) {
  924.                     goto next_value;
  925.                 }
  926.             }

  927.             key_len = sizeof("HTTP_") - 1 + header[i].key.len;
  928.             *b->last++ = (u_char) (key_len & 0xff);
  929.             *b->last++ = (u_char) ((key_len >> 8) & 0xff);

  930.             b->last = ngx_cpymem(b->last, "HTTP_", sizeof("HTTP_") - 1);
  931.             for (n = 0; n < header[i].key.len; n++) {
  932.                 ch = header[i].key.data[n];

  933.                 if (ch >= 'a' && ch <= 'z') {
  934.                     ch &= ~0x20;

  935.                 } else if (ch == '-') {
  936.                     ch = '_';
  937.                 }

  938.                 *b->last++ = ch;
  939.             }

  940.             val_len = header[i].value.len;

  941.             for (hn = header[i].next; hn; hn = hn->next) {
  942.                 val_len += hn->value.len + 2;
  943.             }

  944.             *b->last++ = (u_char) (val_len & 0xff);
  945.             *b->last++ = (u_char) ((val_len >> 8) & 0xff);
  946.             b->last = ngx_copy(b->last, header[i].value.data,
  947.                                header[i].value.len);

  948.             if (header[i].next) {

  949.                 if (header[i].key.len == sizeof("Cookie") - 1
  950.                     && ngx_strncasecmp(header[i].key.data, (u_char *) "Cookie",
  951.                                        sizeof("Cookie") - 1)
  952.                        == 0)
  953.                 {
  954.                     sep = ';';

  955.                 } else {
  956.                     sep = ',';
  957.                 }

  958.                 for (hn = header[i].next; hn; hn = hn->next) {
  959.                     *b->last++ = sep;
  960.                     *b->last++ = ' ';
  961.                     b->last = ngx_copy(b->last, hn->value.data, hn->value.len);
  962.                 }
  963.             }

  964.             ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  965.                            "uwsgi param: \"%*s: %*s\"",
  966.                            key_len, b->last - (key_len + 2 + val_len),
  967.                            val_len, b->last - val_len);
  968.         next_value:

  969.             continue;
  970.         }
  971.     }

  972.     b->last = ngx_copy(b->last, uwcf->uwsgi_string.data,
  973.                        uwcf->uwsgi_string.len);

  974.     if (r->request_body_no_buffering) {
  975.         r->upstream->request_bufs = cl;

  976.     } else if (uwcf->upstream.pass_request_body) {
  977.         body = r->upstream->request_bufs;
  978.         r->upstream->request_bufs = cl;

  979.         while (body) {
  980.             b = ngx_alloc_buf(r->pool);
  981.             if (b == NULL) {
  982.                 return NGX_ERROR;
  983.             }

  984.             ngx_memcpy(b, body->buf, sizeof(ngx_buf_t));

  985.             cl->next = ngx_alloc_chain_link(r->pool);
  986.             if (cl->next == NULL) {
  987.                 return NGX_ERROR;
  988.             }

  989.             cl = cl->next;
  990.             cl->buf = b;

  991.             body = body->next;
  992.         }

  993.     } else {
  994.         r->upstream->request_bufs = cl;
  995.     }

  996.     b->flush = 1;
  997.     cl->next = NULL;

  998.     return NGX_OK;
  999. }


  1000. static ngx_int_t
  1001. ngx_http_uwsgi_reinit_request(ngx_http_request_t *r)
  1002. {
  1003.     ngx_http_status_t  *status;

  1004.     status = ngx_http_get_module_ctx(r, ngx_http_uwsgi_module);

  1005.     if (status == NULL) {
  1006.         return NGX_OK;
  1007.     }

  1008.     status->code = 0;
  1009.     status->count = 0;
  1010.     status->start = NULL;
  1011.     status->end = NULL;

  1012.     r->upstream->process_header = ngx_http_uwsgi_process_status_line;
  1013.     r->state = 0;

  1014.     return NGX_OK;
  1015. }


  1016. static ngx_int_t
  1017. ngx_http_uwsgi_process_status_line(ngx_http_request_t *r)
  1018. {
  1019.     size_t                 len;
  1020.     ngx_int_t              rc;
  1021.     ngx_http_status_t     *status;
  1022.     ngx_http_upstream_t   *u;

  1023.     status = ngx_http_get_module_ctx(r, ngx_http_uwsgi_module);

  1024.     if (status == NULL) {
  1025.         return NGX_ERROR;
  1026.     }

  1027.     u = r->upstream;

  1028.     rc = ngx_http_parse_status_line(r, &u->buffer, status);

  1029.     if (rc == NGX_AGAIN) {
  1030.         return rc;
  1031.     }

  1032.     if (rc == NGX_ERROR) {
  1033.         u->process_header = ngx_http_uwsgi_process_header;
  1034.         u->buffer.pos = status->line_start;
  1035.         r->state = 0;
  1036.         return ngx_http_uwsgi_process_header(r);
  1037.     }

  1038.     if (u->state && u->state->status == 0) {
  1039.         u->state->status = status->code;
  1040.     }

  1041.     u->headers_in.status_n = status->code;

  1042.     len = status->end - status->start;
  1043.     u->headers_in.status_line.len = len;

  1044.     u->headers_in.status_line.data = ngx_pnalloc(r->pool, len);
  1045.     if (u->headers_in.status_line.data == NULL) {
  1046.         return NGX_ERROR;
  1047.     }

  1048.     ngx_memcpy(u->headers_in.status_line.data, status->start, len);

  1049.     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  1050.                    "http uwsgi status %ui \"%V\"",
  1051.                    u->headers_in.status_n, &u->headers_in.status_line);

  1052.     u->process_header = ngx_http_uwsgi_process_header;

  1053.     return ngx_http_uwsgi_process_header(r);
  1054. }


  1055. static ngx_int_t
  1056. ngx_http_uwsgi_process_header(ngx_http_request_t *r)
  1057. {
  1058.     ngx_str_t                      *status_line;
  1059.     ngx_int_t                       rc, status;
  1060.     ngx_table_elt_t                *h;
  1061.     ngx_http_upstream_t            *u;
  1062.     ngx_http_upstream_header_t     *hh;
  1063.     ngx_http_upstream_main_conf_t  *umcf;

  1064.     umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module);

  1065.     for ( ;; ) {

  1066.         rc = ngx_http_parse_header_line(r, &r->upstream->buffer, 1);

  1067.         if (rc == NGX_OK) {

  1068.             /* a header line has been parsed successfully */

  1069.             h = ngx_list_push(&r->upstream->headers_in.headers);
  1070.             if (h == NULL) {
  1071.                 return NGX_ERROR;
  1072.             }

  1073.             h->hash = r->header_hash;

  1074.             h->key.len = r->header_name_end - r->header_name_start;
  1075.             h->value.len = r->header_end - r->header_start;

  1076.             h->key.data = ngx_pnalloc(r->pool,
  1077.                                       h->key.len + 1 + h->value.len + 1
  1078.                                       + h->key.len);
  1079.             if (h->key.data == NULL) {
  1080.                 h->hash = 0;
  1081.                 return NGX_ERROR;
  1082.             }

  1083.             h->value.data = h->key.data + h->key.len + 1;
  1084.             h->lowcase_key = h->key.data + h->key.len + 1 + h->value.len + 1;

  1085.             ngx_memcpy(h->key.data, r->header_name_start, h->key.len);
  1086.             h->key.data[h->key.len] = '\0';
  1087.             ngx_memcpy(h->value.data, r->header_start, h->value.len);
  1088.             h->value.data[h->value.len] = '\0';

  1089.             if (h->key.len == r->lowcase_index) {
  1090.                 ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len);

  1091.             } else {
  1092.                 ngx_strlow(h->lowcase_key, h->key.data, h->key.len);
  1093.             }

  1094.             hh = ngx_hash_find(&umcf->headers_in_hash, h->hash,
  1095.                                h->lowcase_key, h->key.len);

  1096.             if (hh) {
  1097.                 rc = hh->handler(r, h, hh->offset);

  1098.                 if (rc != NGX_OK) {
  1099.                     return rc;
  1100.                 }
  1101.             }

  1102.             ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  1103.                            "http uwsgi header: \"%V: %V\"", &h->key, &h->value);

  1104.             continue;
  1105.         }

  1106.         if (rc == NGX_HTTP_PARSE_HEADER_DONE) {

  1107.             /* a whole header has been parsed successfully */

  1108.             ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  1109.                            "http uwsgi header done");

  1110.             u = r->upstream;

  1111.             if (u->headers_in.status_n) {
  1112.                 goto done;
  1113.             }

  1114.             if (u->headers_in.status) {
  1115.                 status_line = &u->headers_in.status->value;

  1116.                 status = ngx_atoi(status_line->data, 3);
  1117.                 if (status == NGX_ERROR) {
  1118.                     ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1119.                                   "upstream sent invalid status \"%V\"",
  1120.                                   status_line);
  1121.                     return NGX_HTTP_UPSTREAM_INVALID_HEADER;
  1122.                 }

  1123.                 u->headers_in.status_n = status;

  1124.                 if (status_line->len > 3) {
  1125.                     u->headers_in.status_line = *status_line;
  1126.                 }

  1127.             } else if (u->headers_in.location) {
  1128.                 u->headers_in.status_n = 302;
  1129.                 ngx_str_set(&u->headers_in.status_line,
  1130.                             "302 Moved Temporarily");

  1131.             } else {
  1132.                 u->headers_in.status_n = 200;
  1133.                 ngx_str_set(&u->headers_in.status_line, "200 OK");
  1134.             }

  1135.             if (u->state && u->state->status == 0) {
  1136.                 u->state->status = u->headers_in.status_n;
  1137.             }

  1138.         done:

  1139.             if (u->headers_in.status_n == NGX_HTTP_SWITCHING_PROTOCOLS
  1140.                 && r->headers_in.upgrade)
  1141.             {
  1142.                 u->upgrade = 1;
  1143.             }

  1144.             return NGX_OK;
  1145.         }

  1146.         if (rc == NGX_AGAIN) {
  1147.             return NGX_AGAIN;
  1148.         }

  1149.         /* rc == NGX_HTTP_PARSE_INVALID_HEADER */

  1150.         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1151.                       "upstream sent invalid header: \"%*s\\x%02xd...\"",
  1152.                       r->header_end - r->header_name_start,
  1153.                       r->header_name_start, *r->header_end);

  1154.         return NGX_HTTP_UPSTREAM_INVALID_HEADER;
  1155.     }
  1156. }


  1157. static ngx_int_t
  1158. ngx_http_uwsgi_input_filter_init(void *data)
  1159. {
  1160.     ngx_http_request_t   *r = data;
  1161.     ngx_http_upstream_t  *u;

  1162.     u = r->upstream;

  1163.     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  1164.                    "http uwsgi filter init s:%ui l:%O",
  1165.                    u->headers_in.status_n, u->headers_in.content_length_n);

  1166.     if (u->headers_in.status_n == NGX_HTTP_NO_CONTENT
  1167.         || u->headers_in.status_n == NGX_HTTP_NOT_MODIFIED)
  1168.     {
  1169.         u->pipe->length = 0;
  1170.         u->length = 0;

  1171.     } else if (r->method == NGX_HTTP_HEAD) {
  1172.         u->pipe->length = -1;
  1173.         u->length = -1;

  1174.     } else {
  1175.         u->pipe->length = u->headers_in.content_length_n;
  1176.         u->length = u->headers_in.content_length_n;
  1177.     }

  1178.     return NGX_OK;
  1179. }


  1180. static void
  1181. ngx_http_uwsgi_abort_request(ngx_http_request_t *r)
  1182. {
  1183.     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  1184.                    "abort http uwsgi request");

  1185.     return;
  1186. }


  1187. static void
  1188. ngx_http_uwsgi_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
  1189. {
  1190.     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  1191.                    "finalize http uwsgi request");

  1192.     return;
  1193. }


  1194. static void *
  1195. ngx_http_uwsgi_create_main_conf(ngx_conf_t *cf)
  1196. {
  1197.     ngx_http_uwsgi_main_conf_t  *conf;

  1198.     conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_uwsgi_main_conf_t));
  1199.     if (conf == NULL) {
  1200.         return NULL;
  1201.     }

  1202. #if (NGX_HTTP_CACHE)
  1203.     if (ngx_array_init(&conf->caches, cf->pool, 4,
  1204.                        sizeof(ngx_http_file_cache_t *))
  1205.         != NGX_OK)
  1206.     {
  1207.         return NULL;
  1208.     }
  1209. #endif

  1210.     return conf;
  1211. }


  1212. static void *
  1213. ngx_http_uwsgi_create_loc_conf(ngx_conf_t *cf)
  1214. {
  1215.     ngx_http_uwsgi_loc_conf_t  *conf;

  1216.     conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_uwsgi_loc_conf_t));
  1217.     if (conf == NULL) {
  1218.         return NULL;
  1219.     }

  1220.     /*
  1221.      * set by ngx_pcalloc():
  1222.      *
  1223.      *     conf->upstream.bufs.num = 0;
  1224.      *     conf->upstream.ignore_headers = 0;
  1225.      *     conf->upstream.next_upstream = 0;
  1226.      *     conf->upstream.cache_zone = NULL;
  1227.      *     conf->upstream.cache_use_stale = 0;
  1228.      *     conf->upstream.cache_methods = 0;
  1229.      *     conf->upstream.temp_path = NULL;
  1230.      *     conf->upstream.hide_headers_hash = { NULL, 0 };
  1231.      *     conf->upstream.store_lengths = NULL;
  1232.      *     conf->upstream.store_values = NULL;
  1233.      *
  1234.      *     conf->uwsgi_string = { 0, NULL };
  1235.      *     conf->ssl = 0;
  1236.      *     conf->ssl_protocols = 0;
  1237.      *     conf->ssl_ciphers = { 0, NULL };
  1238.      *     conf->ssl_trusted_certificate = { 0, NULL };
  1239.      *     conf->ssl_crl = { 0, NULL };
  1240.      */

  1241.     conf->modifier1 = NGX_CONF_UNSET_UINT;
  1242.     conf->modifier2 = NGX_CONF_UNSET_UINT;

  1243.     conf->upstream.store = NGX_CONF_UNSET;
  1244.     conf->upstream.store_access = NGX_CONF_UNSET_UINT;
  1245.     conf->upstream.next_upstream_tries = NGX_CONF_UNSET_UINT;
  1246.     conf->upstream.buffering = NGX_CONF_UNSET;
  1247.     conf->upstream.request_buffering = NGX_CONF_UNSET;
  1248.     conf->upstream.ignore_client_abort = NGX_CONF_UNSET;
  1249.     conf->upstream.force_ranges = NGX_CONF_UNSET;

  1250.     conf->upstream.local = NGX_CONF_UNSET_PTR;
  1251.     conf->upstream.socket_keepalive = NGX_CONF_UNSET;
  1252.     conf->upstream.socket_rcvbuf = NGX_CONF_UNSET_SIZE;
  1253.     conf->upstream.socket_sndbuf = NGX_CONF_UNSET_SIZE;

  1254.     conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC;
  1255.     conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC;
  1256.     conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC;
  1257.     conf->upstream.next_upstream_timeout = NGX_CONF_UNSET_MSEC;

  1258.     conf->upstream.send_lowat = NGX_CONF_UNSET_SIZE;
  1259.     conf->upstream.buffer_size = NGX_CONF_UNSET_SIZE;
  1260.     conf->upstream.limit_rate = NGX_CONF_UNSET_PTR;

  1261.     conf->upstream.busy_buffers_size_conf = NGX_CONF_UNSET_SIZE;
  1262.     conf->upstream.max_temp_file_size_conf = NGX_CONF_UNSET_SIZE;
  1263.     conf->upstream.temp_file_write_size_conf = NGX_CONF_UNSET_SIZE;

  1264.     conf->upstream.pass_request_headers = NGX_CONF_UNSET;
  1265.     conf->upstream.pass_request_body = NGX_CONF_UNSET;

  1266. #if (NGX_HTTP_CACHE)
  1267.     conf->upstream.cache = NGX_CONF_UNSET;
  1268.     conf->upstream.cache_min_uses = NGX_CONF_UNSET_UINT;
  1269.     conf->upstream.cache_max_range_offset = NGX_CONF_UNSET;
  1270.     conf->upstream.cache_bypass = NGX_CONF_UNSET_PTR;
  1271.     conf->upstream.no_cache = NGX_CONF_UNSET_PTR;
  1272.     conf->upstream.cache_valid = NGX_CONF_UNSET_PTR;
  1273.     conf->upstream.cache_lock = NGX_CONF_UNSET;
  1274.     conf->upstream.cache_lock_timeout = NGX_CONF_UNSET_MSEC;
  1275.     conf->upstream.cache_lock_age = NGX_CONF_UNSET_MSEC;
  1276.     conf->upstream.cache_revalidate = NGX_CONF_UNSET;
  1277.     conf->upstream.cache_background_update = NGX_CONF_UNSET;
  1278. #endif

  1279.     conf->upstream.hide_headers = NGX_CONF_UNSET_PTR;
  1280.     conf->upstream.pass_headers = NGX_CONF_UNSET_PTR;

  1281.     conf->upstream.intercept_errors = NGX_CONF_UNSET;

  1282. #if (NGX_HTTP_SSL)
  1283.     conf->upstream.ssl_session_reuse = NGX_CONF_UNSET;
  1284.     conf->upstream.ssl_name = NGX_CONF_UNSET_PTR;
  1285.     conf->upstream.ssl_server_name = NGX_CONF_UNSET;
  1286.     conf->upstream.ssl_verify = NGX_CONF_UNSET;
  1287.     conf->ssl_verify_depth = NGX_CONF_UNSET_UINT;
  1288.     conf->upstream.ssl_certificate = NGX_CONF_UNSET_PTR;
  1289.     conf->upstream.ssl_certificate_key = NGX_CONF_UNSET_PTR;
  1290.     conf->upstream.ssl_certificate_cache = NGX_CONF_UNSET_PTR;
  1291.     conf->upstream.ssl_passwords = NGX_CONF_UNSET_PTR;
  1292.     conf->ssl_conf_commands = NGX_CONF_UNSET_PTR;
  1293. #endif

  1294.     /* "uwsgi_cyclic_temp_file" is disabled */
  1295.     conf->upstream.cyclic_temp_file = 0;

  1296.     conf->upstream.change_buffering = 1;

  1297.     ngx_str_set(&conf->upstream.module, "uwsgi");

  1298.     return conf;
  1299. }


  1300. static char *
  1301. ngx_http_uwsgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
  1302. {
  1303.     ngx_http_uwsgi_loc_conf_t *prev = parent;
  1304.     ngx_http_uwsgi_loc_conf_t *conf = child;

  1305.     size_t                        size;
  1306.     ngx_int_t                     rc;
  1307.     ngx_hash_init_t               hash;
  1308.     ngx_http_core_loc_conf_t     *clcf;

  1309. #if (NGX_HTTP_CACHE)

  1310.     if (conf->upstream.store > 0) {
  1311.         conf->upstream.cache = 0;
  1312.     }

  1313.     if (conf->upstream.cache > 0) {
  1314.         conf->upstream.store = 0;
  1315.     }

  1316. #endif

  1317.     if (conf->upstream.store == NGX_CONF_UNSET) {
  1318.         ngx_conf_merge_value(conf->upstream.store, prev->upstream.store, 0);

  1319.         conf->upstream.store_lengths = prev->upstream.store_lengths;
  1320.         conf->upstream.store_values = prev->upstream.store_values;
  1321.     }

  1322.     ngx_conf_merge_uint_value(conf->upstream.store_access,
  1323.                               prev->upstream.store_access, 0600);

  1324.     ngx_conf_merge_uint_value(conf->upstream.next_upstream_tries,
  1325.                               prev->upstream.next_upstream_tries, 0);

  1326.     ngx_conf_merge_value(conf->upstream.buffering,
  1327.                               prev->upstream.buffering, 1);

  1328.     ngx_conf_merge_value(conf->upstream.request_buffering,
  1329.                               prev->upstream.request_buffering, 1);

  1330.     ngx_conf_merge_value(conf->upstream.ignore_client_abort,
  1331.                               prev->upstream.ignore_client_abort, 0);

  1332.     ngx_conf_merge_value(conf->upstream.force_ranges,
  1333.                               prev->upstream.force_ranges, 0);

  1334.     ngx_conf_merge_ptr_value(conf->upstream.local,
  1335.                               prev->upstream.local, NULL);

  1336.     ngx_conf_merge_value(conf->upstream.socket_keepalive,
  1337.                               prev->upstream.socket_keepalive, 0);

  1338.     ngx_conf_merge_size_value(conf->upstream.socket_rcvbuf,
  1339.                               prev->upstream.socket_rcvbuf, 0);

  1340.     ngx_conf_merge_size_value(conf->upstream.socket_sndbuf,
  1341.                               prev->upstream.socket_sndbuf, 0);

  1342.     ngx_conf_merge_msec_value(conf->upstream.connect_timeout,
  1343.                               prev->upstream.connect_timeout, 60000);

  1344.     ngx_conf_merge_msec_value(conf->upstream.send_timeout,
  1345.                               prev->upstream.send_timeout, 60000);

  1346.     ngx_conf_merge_msec_value(conf->upstream.read_timeout,
  1347.                               prev->upstream.read_timeout, 60000);

  1348.     ngx_conf_merge_msec_value(conf->upstream.next_upstream_timeout,
  1349.                               prev->upstream.next_upstream_timeout, 0);

  1350.     ngx_conf_merge_size_value(conf->upstream.send_lowat,
  1351.                               prev->upstream.send_lowat, 0);

  1352.     ngx_conf_merge_size_value(conf->upstream.buffer_size,
  1353.                               prev->upstream.buffer_size,
  1354.                               (size_t) ngx_pagesize);

  1355.     ngx_conf_merge_ptr_value(conf->upstream.limit_rate,
  1356.                               prev->upstream.limit_rate, NULL);


  1357.     ngx_conf_merge_bufs_value(conf->upstream.bufs, prev->upstream.bufs,
  1358.                               8, ngx_pagesize);

  1359.     if (conf->upstream.bufs.num < 2) {
  1360.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  1361.                            "there must be at least 2 \"uwsgi_buffers\"");
  1362.         return NGX_CONF_ERROR;
  1363.     }


  1364.     size = conf->upstream.buffer_size;
  1365.     if (size < conf->upstream.bufs.size) {
  1366.         size = conf->upstream.bufs.size;
  1367.     }


  1368.     ngx_conf_merge_size_value(conf->upstream.busy_buffers_size_conf,
  1369.                               prev->upstream.busy_buffers_size_conf,
  1370.                               NGX_CONF_UNSET_SIZE);

  1371.     if (conf->upstream.busy_buffers_size_conf == NGX_CONF_UNSET_SIZE) {
  1372.         conf->upstream.busy_buffers_size = 2 * size;
  1373.     } else {
  1374.         conf->upstream.busy_buffers_size =
  1375.             conf->upstream.busy_buffers_size_conf;
  1376.     }

  1377.     if (conf->upstream.busy_buffers_size < size) {
  1378.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  1379.             "\"uwsgi_busy_buffers_size\" must be equal to or greater "
  1380.             "than the maximum of the value of \"uwsgi_buffer_size\" and "
  1381.             "one of the \"uwsgi_buffers\"");

  1382.         return NGX_CONF_ERROR;
  1383.     }

  1384.     if (conf->upstream.busy_buffers_size
  1385.         > (conf->upstream.bufs.num - 1) * conf->upstream.bufs.size)
  1386.     {
  1387.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  1388.             "\"uwsgi_busy_buffers_size\" must be less than "
  1389.             "the size of all \"uwsgi_buffers\" minus one buffer");

  1390.         return NGX_CONF_ERROR;
  1391.     }


  1392.     ngx_conf_merge_size_value(conf->upstream.temp_file_write_size_conf,
  1393.                               prev->upstream.temp_file_write_size_conf,
  1394.                               NGX_CONF_UNSET_SIZE);

  1395.     if (conf->upstream.temp_file_write_size_conf == NGX_CONF_UNSET_SIZE) {
  1396.         conf->upstream.temp_file_write_size = 2 * size;
  1397.     } else {
  1398.         conf->upstream.temp_file_write_size =
  1399.             conf->upstream.temp_file_write_size_conf;
  1400.     }

  1401.     if (conf->upstream.temp_file_write_size < size) {
  1402.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  1403.             "\"uwsgi_temp_file_write_size\" must be equal to or greater than "
  1404.             "the maximum of the value of \"uwsgi_buffer_size\" and "
  1405.             "one of the \"uwsgi_buffers\"");

  1406.         return NGX_CONF_ERROR;
  1407.     }


  1408.     ngx_conf_merge_size_value(conf->upstream.max_temp_file_size_conf,
  1409.                               prev->upstream.max_temp_file_size_conf,
  1410.                               NGX_CONF_UNSET_SIZE);

  1411.     if (conf->upstream.max_temp_file_size_conf == NGX_CONF_UNSET_SIZE) {
  1412.         conf->upstream.max_temp_file_size = 1024 * 1024 * 1024;
  1413.     } else {
  1414.         conf->upstream.max_temp_file_size =
  1415.             conf->upstream.max_temp_file_size_conf;
  1416.     }

  1417.     if (conf->upstream.max_temp_file_size != 0
  1418.         && conf->upstream.max_temp_file_size < size)
  1419.     {
  1420.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  1421.             "\"uwsgi_max_temp_file_size\" must be equal to zero to disable "
  1422.             "temporary files usage or must be equal to or greater than "
  1423.             "the maximum of the value of \"uwsgi_buffer_size\" and "
  1424.             "one of the \"uwsgi_buffers\"");

  1425.         return NGX_CONF_ERROR;
  1426.     }


  1427.     ngx_conf_merge_bitmask_value(conf->upstream.ignore_headers,
  1428.                                  prev->upstream.ignore_headers,
  1429.                                  NGX_CONF_BITMASK_SET);


  1430.     ngx_conf_merge_bitmask_value(conf->upstream.next_upstream,
  1431.                                  prev->upstream.next_upstream,
  1432.                                  (NGX_CONF_BITMASK_SET
  1433.                                   |NGX_HTTP_UPSTREAM_FT_ERROR
  1434.                                   |NGX_HTTP_UPSTREAM_FT_TIMEOUT));

  1435.     if (conf->upstream.next_upstream & NGX_HTTP_UPSTREAM_FT_OFF) {
  1436.         conf->upstream.next_upstream = NGX_CONF_BITMASK_SET
  1437.                                        |NGX_HTTP_UPSTREAM_FT_OFF;
  1438.     }

  1439.     if (ngx_conf_merge_path_value(cf, &conf->upstream.temp_path,
  1440.                                   prev->upstream.temp_path,
  1441.                                   &ngx_http_uwsgi_temp_path)
  1442.         != NGX_CONF_OK)
  1443.     {
  1444.         return NGX_CONF_ERROR;
  1445.     }

  1446. #if (NGX_HTTP_CACHE)

  1447.     if (conf->upstream.cache == NGX_CONF_UNSET) {
  1448.         ngx_conf_merge_value(conf->upstream.cache,
  1449.                               prev->upstream.cache, 0);

  1450.         conf->upstream.cache_zone = prev->upstream.cache_zone;
  1451.         conf->upstream.cache_value = prev->upstream.cache_value;
  1452.     }

  1453.     if (conf->upstream.cache_zone && conf->upstream.cache_zone->data == NULL) {
  1454.         ngx_shm_zone_t  *shm_zone;

  1455.         shm_zone = conf->upstream.cache_zone;

  1456.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  1457.                            "\"uwsgi_cache\" zone \"%V\" is unknown",
  1458.                            &shm_zone->shm.name);

  1459.         return NGX_CONF_ERROR;
  1460.     }

  1461.     ngx_conf_merge_uint_value(conf->upstream.cache_min_uses,
  1462.                               prev->upstream.cache_min_uses, 1);

  1463.     ngx_conf_merge_off_value(conf->upstream.cache_max_range_offset,
  1464.                               prev->upstream.cache_max_range_offset,
  1465.                               NGX_MAX_OFF_T_VALUE);

  1466.     ngx_conf_merge_bitmask_value(conf->upstream.cache_use_stale,
  1467.                               prev->upstream.cache_use_stale,
  1468.                               (NGX_CONF_BITMASK_SET
  1469.                                |NGX_HTTP_UPSTREAM_FT_OFF));

  1470.     if (conf->upstream.cache_use_stale & NGX_HTTP_UPSTREAM_FT_OFF) {
  1471.         conf->upstream.cache_use_stale = NGX_CONF_BITMASK_SET
  1472.                                          |NGX_HTTP_UPSTREAM_FT_OFF;
  1473.     }

  1474.     if (conf->upstream.cache_use_stale & NGX_HTTP_UPSTREAM_FT_ERROR) {
  1475.         conf->upstream.cache_use_stale |= NGX_HTTP_UPSTREAM_FT_NOLIVE;
  1476.     }

  1477.     if (conf->upstream.cache_methods == 0) {
  1478.         conf->upstream.cache_methods = prev->upstream.cache_methods;
  1479.     }

  1480.     conf->upstream.cache_methods |= NGX_HTTP_GET|NGX_HTTP_HEAD;

  1481.     ngx_conf_merge_ptr_value(conf->upstream.cache_bypass,
  1482.                              prev->upstream.cache_bypass, NULL);

  1483.     ngx_conf_merge_ptr_value(conf->upstream.no_cache,
  1484.                              prev->upstream.no_cache, NULL);

  1485.     ngx_conf_merge_ptr_value(conf->upstream.cache_valid,
  1486.                              prev->upstream.cache_valid, NULL);

  1487.     if (conf->cache_key.value.data == NULL) {
  1488.         conf->cache_key = prev->cache_key;
  1489.     }

  1490.     if (conf->upstream.cache && conf->cache_key.value.data == NULL) {
  1491.         ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
  1492.                            "no \"uwsgi_cache_key\" for \"uwsgi_cache\"");
  1493.     }

  1494.     ngx_conf_merge_value(conf->upstream.cache_lock,
  1495.                               prev->upstream.cache_lock, 0);

  1496.     ngx_conf_merge_msec_value(conf->upstream.cache_lock_timeout,
  1497.                               prev->upstream.cache_lock_timeout, 5000);

  1498.     ngx_conf_merge_msec_value(conf->upstream.cache_lock_age,
  1499.                               prev->upstream.cache_lock_age, 5000);

  1500.     ngx_conf_merge_value(conf->upstream.cache_revalidate,
  1501.                               prev->upstream.cache_revalidate, 0);

  1502.     ngx_conf_merge_value(conf->upstream.cache_background_update,
  1503.                               prev->upstream.cache_background_update, 0);

  1504. #endif

  1505.     ngx_conf_merge_value(conf->upstream.pass_request_headers,
  1506.                          prev->upstream.pass_request_headers, 1);
  1507.     ngx_conf_merge_value(conf->upstream.pass_request_body,
  1508.                          prev->upstream.pass_request_body, 1);

  1509.     ngx_conf_merge_value(conf->upstream.intercept_errors,
  1510.                          prev->upstream.intercept_errors, 0);

  1511. #if (NGX_HTTP_SSL)

  1512.     if (ngx_http_uwsgi_merge_ssl(cf, conf, prev) != NGX_OK) {
  1513.         return NGX_CONF_ERROR;
  1514.     }

  1515.     ngx_conf_merge_value(conf->upstream.ssl_session_reuse,
  1516.                               prev->upstream.ssl_session_reuse, 1);

  1517.     ngx_conf_merge_bitmask_value(conf->ssl_protocols, prev->ssl_protocols,
  1518.                               (NGX_CONF_BITMASK_SET|NGX_SSL_DEFAULT_PROTOCOLS));

  1519.     ngx_conf_merge_str_value(conf->ssl_ciphers, prev->ssl_ciphers,
  1520.                              "DEFAULT");

  1521.     ngx_conf_merge_ptr_value(conf->upstream.ssl_name,
  1522.                               prev->upstream.ssl_name, NULL);
  1523.     ngx_conf_merge_value(conf->upstream.ssl_server_name,
  1524.                               prev->upstream.ssl_server_name, 0);
  1525.     ngx_conf_merge_value(conf->upstream.ssl_verify,
  1526.                               prev->upstream.ssl_verify, 0);
  1527.     ngx_conf_merge_uint_value(conf->ssl_verify_depth,
  1528.                               prev->ssl_verify_depth, 1);
  1529.     ngx_conf_merge_str_value(conf->ssl_trusted_certificate,
  1530.                               prev->ssl_trusted_certificate, "");
  1531.     ngx_conf_merge_str_value(conf->ssl_crl, prev->ssl_crl, "");

  1532.     ngx_conf_merge_ptr_value(conf->upstream.ssl_certificate,
  1533.                               prev->upstream.ssl_certificate, NULL);
  1534.     ngx_conf_merge_ptr_value(conf->upstream.ssl_certificate_key,
  1535.                               prev->upstream.ssl_certificate_key, NULL);
  1536.     ngx_conf_merge_ptr_value(conf->upstream.ssl_certificate_cache,
  1537.                               prev->upstream.ssl_certificate_cache, NULL);

  1538.     if (ngx_http_upstream_merge_ssl_passwords(cf, &conf->upstream,
  1539.                                               &prev->upstream)
  1540.         != NGX_OK)
  1541.     {
  1542.         return NGX_CONF_ERROR;
  1543.     }

  1544.     ngx_conf_merge_ptr_value(conf->ssl_conf_commands,
  1545.                               prev->ssl_conf_commands, NULL);

  1546.     if (conf->ssl && ngx_http_uwsgi_set_ssl(cf, conf) != NGX_OK) {
  1547.         return NGX_CONF_ERROR;
  1548.     }

  1549. #endif

  1550.     ngx_conf_merge_str_value(conf->uwsgi_string, prev->uwsgi_string, "");

  1551.     hash.max_size = 512;
  1552.     hash.bucket_size = ngx_align(64, ngx_cacheline_size);
  1553.     hash.name = "uwsgi_hide_headers_hash";

  1554.     if (ngx_http_upstream_hide_headers_hash(cf, &conf->upstream,
  1555.             &prev->upstream, ngx_http_uwsgi_hide_headers, &hash)
  1556.         != NGX_OK)
  1557.     {
  1558.         return NGX_CONF_ERROR;
  1559.     }

  1560.     clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);

  1561.     if (clcf->noname
  1562.         && conf->upstream.upstream == NULL && conf->uwsgi_lengths == NULL)
  1563.     {
  1564.         conf->upstream.upstream = prev->upstream.upstream;

  1565.         conf->uwsgi_lengths = prev->uwsgi_lengths;
  1566.         conf->uwsgi_values = prev->uwsgi_values;

  1567. #if (NGX_HTTP_SSL)
  1568.         conf->ssl = prev->ssl;
  1569. #endif
  1570.     }

  1571.     if (clcf->lmt_excpt && clcf->handler == NULL
  1572.         && (conf->upstream.upstream || conf->uwsgi_lengths))
  1573.     {
  1574.         clcf->handler = ngx_http_uwsgi_handler;
  1575.     }

  1576.     ngx_conf_merge_uint_value(conf->modifier1, prev->modifier1, 0);
  1577.     ngx_conf_merge_uint_value(conf->modifier2, prev->modifier2, 0);

  1578.     if (conf->params_source == NULL) {
  1579.         conf->params = prev->params;
  1580. #if (NGX_HTTP_CACHE)
  1581.         conf->params_cache = prev->params_cache;
  1582. #endif
  1583.         conf->params_source = prev->params_source;
  1584.     }

  1585.     rc = ngx_http_uwsgi_init_params(cf, conf, &conf->params,
  1586.                                     ngx_http_uwsgi_headers);
  1587.     if (rc != NGX_OK) {
  1588.         return NGX_CONF_ERROR;
  1589.     }

  1590. #if (NGX_HTTP_CACHE)

  1591.     if (conf->upstream.cache) {
  1592.         rc = ngx_http_uwsgi_init_params(cf, conf, &conf->params_cache,
  1593.                                         ngx_http_uwsgi_cache_headers);
  1594.         if (rc != NGX_OK) {
  1595.             return NGX_CONF_ERROR;
  1596.         }
  1597.     }

  1598. #endif

  1599.     /*
  1600.      * special handling to preserve conf->params in the "http" section
  1601.      * to inherit it to all servers
  1602.      */

  1603.     if (prev->params.hash.buckets == NULL
  1604.         && conf->params_source == prev->params_source)
  1605.     {
  1606.         prev->params = conf->params;
  1607. #if (NGX_HTTP_CACHE)
  1608.         prev->params_cache = conf->params_cache;
  1609. #endif
  1610.     }

  1611.     return NGX_CONF_OK;
  1612. }


  1613. static ngx_int_t
  1614. ngx_http_uwsgi_init_params(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *conf,
  1615.     ngx_http_uwsgi_params_t *params, ngx_keyval_t *default_params)
  1616. {
  1617.     u_char                       *p;
  1618.     size_t                        size;
  1619.     uintptr_t                    *code;
  1620.     ngx_uint_t                    i, nsrc;
  1621.     ngx_array_t                   headers_names, params_merged;
  1622.     ngx_keyval_t                 *h;
  1623.     ngx_hash_key_t               *hk;
  1624.     ngx_hash_init_t               hash;
  1625.     ngx_http_upstream_param_t    *src, *s;
  1626.     ngx_http_script_compile_t     sc;
  1627.     ngx_http_script_copy_code_t  *copy;

  1628.     if (params->hash.buckets) {
  1629.         return NGX_OK;
  1630.     }

  1631.     if (conf->params_source == NULL && default_params == NULL) {
  1632.         params->hash.buckets = (void *) 1;
  1633.         return NGX_OK;
  1634.     }

  1635.     params->lengths = ngx_array_create(cf->pool, 64, 1);
  1636.     if (params->lengths == NULL) {
  1637.         return NGX_ERROR;
  1638.     }

  1639.     params->values = ngx_array_create(cf->pool, 512, 1);
  1640.     if (params->values == NULL) {
  1641.         return NGX_ERROR;
  1642.     }

  1643.     if (ngx_array_init(&headers_names, cf->temp_pool, 4, sizeof(ngx_hash_key_t))
  1644.         != NGX_OK)
  1645.     {
  1646.         return NGX_ERROR;
  1647.     }

  1648.     if (conf->params_source) {
  1649.         src = conf->params_source->elts;
  1650.         nsrc = conf->params_source->nelts;

  1651.     } else {
  1652.         src = NULL;
  1653.         nsrc = 0;
  1654.     }

  1655.     if (default_params) {
  1656.         if (ngx_array_init(&params_merged, cf->temp_pool, 4,
  1657.                            sizeof(ngx_http_upstream_param_t))
  1658.             != NGX_OK)
  1659.         {
  1660.             return NGX_ERROR;
  1661.         }

  1662.         for (i = 0; i < nsrc; i++) {

  1663.             s = ngx_array_push(&params_merged);
  1664.             if (s == NULL) {
  1665.                 return NGX_ERROR;
  1666.             }

  1667.             *s = src[i];
  1668.         }

  1669.         h = default_params;

  1670.         while (h->key.len) {

  1671.             src = params_merged.elts;
  1672.             nsrc = params_merged.nelts;

  1673.             for (i = 0; i < nsrc; i++) {
  1674.                 if (ngx_strcasecmp(h->key.data, src[i].key.data) == 0) {
  1675.                     goto next;
  1676.                 }
  1677.             }

  1678.             s = ngx_array_push(&params_merged);
  1679.             if (s == NULL) {
  1680.                 return NGX_ERROR;
  1681.             }

  1682.             s->key = h->key;
  1683.             s->value = h->value;
  1684.             s->skip_empty = 1;

  1685.         next:

  1686.             h++;
  1687.         }

  1688.         src = params_merged.elts;
  1689.         nsrc = params_merged.nelts;
  1690.     }

  1691.     for (i = 0; i < nsrc; i++) {

  1692.         if (src[i].key.len > sizeof("HTTP_") - 1
  1693.             && ngx_strncmp(src[i].key.data, "HTTP_", sizeof("HTTP_") - 1) == 0)
  1694.         {
  1695.             hk = ngx_array_push(&headers_names);
  1696.             if (hk == NULL) {
  1697.                 return NGX_ERROR;
  1698.             }

  1699.             hk->key.len = src[i].key.len - 5;
  1700.             hk->key.data = src[i].key.data + 5;
  1701.             hk->key_hash = ngx_hash_key_lc(hk->key.data, hk->key.len);
  1702.             hk->value = (void *) 1;

  1703.             if (src[i].value.len == 0) {
  1704.                 continue;
  1705.             }
  1706.         }

  1707.         copy = ngx_array_push_n(params->lengths,
  1708.                                 sizeof(ngx_http_script_copy_code_t));
  1709.         if (copy == NULL) {
  1710.             return NGX_ERROR;
  1711.         }

  1712.         copy->code = (ngx_http_script_code_pt) (void *)
  1713.                                                  ngx_http_script_copy_len_code;
  1714.         copy->len = src[i].key.len;

  1715.         copy = ngx_array_push_n(params->lengths,
  1716.                                 sizeof(ngx_http_script_copy_code_t));
  1717.         if (copy == NULL) {
  1718.             return NGX_ERROR;
  1719.         }

  1720.         copy->code = (ngx_http_script_code_pt) (void *)
  1721.                                                  ngx_http_script_copy_len_code;
  1722.         copy->len = src[i].skip_empty;


  1723.         size = (sizeof(ngx_http_script_copy_code_t)
  1724.                 + src[i].key.len + sizeof(uintptr_t) - 1)
  1725.                & ~(sizeof(uintptr_t) - 1);

  1726.         copy = ngx_array_push_n(params->values, size);
  1727.         if (copy == NULL) {
  1728.             return NGX_ERROR;
  1729.         }

  1730.         copy->code = ngx_http_script_copy_code;
  1731.         copy->len = src[i].key.len;

  1732.         p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t);
  1733.         ngx_memcpy(p, src[i].key.data, src[i].key.len);


  1734.         ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));

  1735.         sc.cf = cf;
  1736.         sc.source = &src[i].value;
  1737.         sc.flushes = &params->flushes;
  1738.         sc.lengths = &params->lengths;
  1739.         sc.values = &params->values;

  1740.         if (ngx_http_script_compile(&sc) != NGX_OK) {
  1741.             return NGX_ERROR;
  1742.         }

  1743.         code = ngx_array_push_n(params->lengths, sizeof(uintptr_t));
  1744.         if (code == NULL) {
  1745.             return NGX_ERROR;
  1746.         }

  1747.         *code = (uintptr_t) NULL;


  1748.         code = ngx_array_push_n(params->values, sizeof(uintptr_t));
  1749.         if (code == NULL) {
  1750.             return NGX_ERROR;
  1751.         }

  1752.         *code = (uintptr_t) NULL;
  1753.     }

  1754.     code = ngx_array_push_n(params->lengths, sizeof(uintptr_t));
  1755.     if (code == NULL) {
  1756.         return NGX_ERROR;
  1757.     }

  1758.     *code = (uintptr_t) NULL;

  1759.     params->number = headers_names.nelts;

  1760.     hash.hash = &params->hash;
  1761.     hash.key = ngx_hash_key_lc;
  1762.     hash.max_size = 512;
  1763.     hash.bucket_size = 64;
  1764.     hash.name = "uwsgi_params_hash";
  1765.     hash.pool = cf->pool;
  1766.     hash.temp_pool = NULL;

  1767.     return ngx_hash_init(&hash, headers_names.elts, headers_names.nelts);
  1768. }


  1769. static char *
  1770. ngx_http_uwsgi_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  1771. {
  1772.     ngx_http_uwsgi_loc_conf_t *uwcf = conf;

  1773.     size_t                      add;
  1774.     ngx_url_t                   u;
  1775.     ngx_str_t                  *value, *url;
  1776.     ngx_uint_t                  n;
  1777.     ngx_http_core_loc_conf_t   *clcf;
  1778.     ngx_http_script_compile_t   sc;

  1779.     if (uwcf->upstream.upstream || uwcf->uwsgi_lengths) {
  1780.         return "is duplicate";
  1781.     }

  1782.     clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
  1783.     clcf->handler = ngx_http_uwsgi_handler;

  1784.     value = cf->args->elts;

  1785.     url = &value[1];

  1786.     n = ngx_http_script_variables_count(url);

  1787.     if (n) {

  1788.         ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));

  1789.         sc.cf = cf;
  1790.         sc.source = url;
  1791.         sc.lengths = &uwcf->uwsgi_lengths;
  1792.         sc.values = &uwcf->uwsgi_values;
  1793.         sc.variables = n;
  1794.         sc.complete_lengths = 1;
  1795.         sc.complete_values = 1;

  1796.         if (ngx_http_script_compile(&sc) != NGX_OK) {
  1797.             return NGX_CONF_ERROR;
  1798.         }

  1799. #if (NGX_HTTP_SSL)
  1800.         uwcf->ssl = 1;
  1801. #endif

  1802.         return NGX_CONF_OK;
  1803.     }

  1804.     if (ngx_strncasecmp(url->data, (u_char *) "uwsgi://", 8) == 0) {
  1805.         add = 8;

  1806.     } else if (ngx_strncasecmp(url->data, (u_char *) "suwsgi://", 9) == 0) {

  1807. #if (NGX_HTTP_SSL)
  1808.         add = 9;
  1809.         uwcf->ssl = 1;
  1810. #else
  1811.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  1812.                            "suwsgi protocol requires SSL support");
  1813.         return NGX_CONF_ERROR;
  1814. #endif

  1815.     } else {
  1816.         add = 0;
  1817.     }

  1818.     ngx_memzero(&u, sizeof(ngx_url_t));

  1819.     u.url.len = url->len - add;
  1820.     u.url.data = url->data + add;
  1821.     u.no_resolve = 1;

  1822.     uwcf->upstream.upstream = ngx_http_upstream_add(cf, &u, 0);
  1823.     if (uwcf->upstream.upstream == NULL) {
  1824.         return NGX_CONF_ERROR;
  1825.     }

  1826.     if (clcf->name.len && clcf->name.data[clcf->name.len - 1] == '/') {
  1827.         clcf->auto_redirect = 1;
  1828.     }

  1829.     return NGX_CONF_OK;
  1830. }


  1831. static char *
  1832. ngx_http_uwsgi_store(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  1833. {
  1834.     ngx_http_uwsgi_loc_conf_t *uwcf = conf;

  1835.     ngx_str_t                  *value;
  1836.     ngx_http_script_compile_t   sc;

  1837.     if (uwcf->upstream.store != NGX_CONF_UNSET) {
  1838.         return "is duplicate";
  1839.     }

  1840.     value = cf->args->elts;

  1841.     if (ngx_strcmp(value[1].data, "off") == 0) {
  1842.         uwcf->upstream.store = 0;
  1843.         return NGX_CONF_OK;
  1844.     }

  1845.     if (value[1].len == 0) {
  1846.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "empty path");
  1847.         return NGX_CONF_ERROR;
  1848.     }

  1849. #if (NGX_HTTP_CACHE)

  1850.     if (uwcf->upstream.cache > 0) {
  1851.         return "is incompatible with \"uwsgi_cache\"";
  1852.     }

  1853. #endif

  1854.     uwcf->upstream.store = 1;

  1855.     if (ngx_strcmp(value[1].data, "on") == 0) {
  1856.         return NGX_CONF_OK;
  1857.     }

  1858.     /* include the terminating '\0' into script */
  1859.     value[1].len++;

  1860.     ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));

  1861.     sc.cf = cf;
  1862.     sc.source = &value[1];
  1863.     sc.lengths = &uwcf->upstream.store_lengths;
  1864.     sc.values = &uwcf->upstream.store_values;
  1865.     sc.variables = ngx_http_script_variables_count(&value[1]);
  1866.     sc.complete_lengths = 1;
  1867.     sc.complete_values = 1;

  1868.     if (ngx_http_script_compile(&sc) != NGX_OK) {
  1869.         return NGX_CONF_ERROR;
  1870.     }

  1871.     return NGX_CONF_OK;
  1872. }


  1873. #if (NGX_HTTP_CACHE)

  1874. static char *
  1875. ngx_http_uwsgi_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  1876. {
  1877.     ngx_http_uwsgi_loc_conf_t *uwcf = conf;

  1878.     ngx_str_t                         *value;
  1879.     ngx_http_complex_value_t           cv;
  1880.     ngx_http_compile_complex_value_t   ccv;

  1881.     value = cf->args->elts;

  1882.     if (uwcf->upstream.cache != NGX_CONF_UNSET) {
  1883.         return "is duplicate";
  1884.     }

  1885.     if (ngx_strcmp(value[1].data, "off") == 0) {
  1886.         uwcf->upstream.cache = 0;
  1887.         return NGX_CONF_OK;
  1888.     }

  1889.     if (uwcf->upstream.store > 0) {
  1890.         return "is incompatible with \"uwsgi_store\"";
  1891.     }

  1892.     uwcf->upstream.cache = 1;

  1893.     ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));

  1894.     ccv.cf = cf;
  1895.     ccv.value = &value[1];
  1896.     ccv.complex_value = &cv;

  1897.     if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
  1898.         return NGX_CONF_ERROR;
  1899.     }

  1900.     if (cv.lengths != NULL) {

  1901.         uwcf->upstream.cache_value = ngx_palloc(cf->pool,
  1902.                                              sizeof(ngx_http_complex_value_t));
  1903.         if (uwcf->upstream.cache_value == NULL) {
  1904.             return NGX_CONF_ERROR;
  1905.         }

  1906.         *uwcf->upstream.cache_value = cv;

  1907.         return NGX_CONF_OK;
  1908.     }

  1909.     uwcf->upstream.cache_zone = ngx_shared_memory_add(cf, &value[1], 0,
  1910.                                                       &ngx_http_uwsgi_module);
  1911.     if (uwcf->upstream.cache_zone == NULL) {
  1912.         return NGX_CONF_ERROR;
  1913.     }

  1914.     return NGX_CONF_OK;
  1915. }


  1916. static char *
  1917. ngx_http_uwsgi_cache_key(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  1918. {
  1919.     ngx_http_uwsgi_loc_conf_t *uwcf = conf;

  1920.     ngx_str_t                         *value;
  1921.     ngx_http_compile_complex_value_t   ccv;

  1922.     value = cf->args->elts;

  1923.     if (uwcf->cache_key.value.data) {
  1924.         return "is duplicate";
  1925.     }

  1926.     ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));

  1927.     ccv.cf = cf;
  1928.     ccv.value = &value[1];
  1929.     ccv.complex_value = &uwcf->cache_key;

  1930.     if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
  1931.         return NGX_CONF_ERROR;
  1932.     }

  1933.     return NGX_CONF_OK;
  1934. }

  1935. #endif


  1936. #if (NGX_HTTP_SSL)

  1937. static char *
  1938. ngx_http_uwsgi_ssl_certificate_cache(ngx_conf_t *cf, ngx_command_t *cmd,
  1939.     void *conf)
  1940. {
  1941.     ngx_http_uwsgi_loc_conf_t *plcf = conf;

  1942.     time_t       inactive, valid;
  1943.     ngx_str_t   *value, s;
  1944.     ngx_int_t    max;
  1945.     ngx_uint_t   i;

  1946.     if (plcf->upstream.ssl_certificate_cache != NGX_CONF_UNSET_PTR) {
  1947.         return "is duplicate";
  1948.     }

  1949.     value = cf->args->elts;

  1950.     max = 0;
  1951.     inactive = 10;
  1952.     valid = 60;

  1953.     for (i = 1; i < cf->args->nelts; i++) {

  1954.         if (ngx_strncmp(value[i].data, "max=", 4) == 0) {

  1955.             max = ngx_atoi(value[i].data + 4, value[i].len - 4);
  1956.             if (max <= 0) {
  1957.                 goto failed;
  1958.             }

  1959.             continue;
  1960.         }

  1961.         if (ngx_strncmp(value[i].data, "inactive=", 9) == 0) {

  1962.             s.len = value[i].len - 9;
  1963.             s.data = value[i].data + 9;

  1964.             inactive = ngx_parse_time(&s, 1);
  1965.             if (inactive == (time_t) NGX_ERROR) {
  1966.                 goto failed;
  1967.             }

  1968.             continue;
  1969.         }

  1970.         if (ngx_strncmp(value[i].data, "valid=", 6) == 0) {

  1971.             s.len = value[i].len - 6;
  1972.             s.data = value[i].data + 6;

  1973.             valid = ngx_parse_time(&s, 1);
  1974.             if (valid == (time_t) NGX_ERROR) {
  1975.                 goto failed;
  1976.             }

  1977.             continue;
  1978.         }

  1979.         if (ngx_strcmp(value[i].data, "off") == 0) {

  1980.             plcf->upstream.ssl_certificate_cache = NULL;

  1981.             continue;
  1982.         }

  1983.     failed:

  1984.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  1985.                            "invalid parameter \"%V\"", &value[i]);
  1986.         return NGX_CONF_ERROR;
  1987.     }

  1988.     if (plcf->upstream.ssl_certificate_cache == NULL) {
  1989.         return NGX_CONF_OK;
  1990.     }

  1991.     if (max == 0) {
  1992.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  1993.                            "\"uwsgi_ssl_certificate_cache\" must have "
  1994.                            "the \"max\" parameter");
  1995.         return NGX_CONF_ERROR;
  1996.     }

  1997.     plcf->upstream.ssl_certificate_cache = ngx_ssl_cache_init(cf->pool, max,
  1998.                                                               valid, inactive);
  1999.     if (plcf->upstream.ssl_certificate_cache == NULL) {
  2000.         return NGX_CONF_ERROR;
  2001.     }

  2002.     return NGX_CONF_OK;
  2003. }


  2004. static char *
  2005. ngx_http_uwsgi_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  2006. {
  2007.     ngx_http_uwsgi_loc_conf_t *uwcf = conf;

  2008.     ngx_str_t  *value;

  2009.     if (uwcf->upstream.ssl_passwords != NGX_CONF_UNSET_PTR) {
  2010.         return "is duplicate";
  2011.     }

  2012.     value = cf->args->elts;

  2013.     uwcf->upstream.ssl_passwords = ngx_ssl_read_password_file(cf, &value[1]);

  2014.     if (uwcf->upstream.ssl_passwords == NULL) {
  2015.         return NGX_CONF_ERROR;
  2016.     }

  2017.     return NGX_CONF_OK;
  2018. }


  2019. static char *
  2020. ngx_http_uwsgi_ssl_conf_command_check(ngx_conf_t *cf, void *post, void *data)
  2021. {
  2022. #ifndef SSL_CONF_FLAG_FILE
  2023.     return "is not supported on this platform";
  2024. #else
  2025.     return NGX_CONF_OK;
  2026. #endif
  2027. }


  2028. static ngx_int_t
  2029. ngx_http_uwsgi_merge_ssl(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *conf,
  2030.     ngx_http_uwsgi_loc_conf_t *prev)
  2031. {
  2032.     ngx_uint_t  preserve;

  2033.     if (conf->ssl_protocols == 0
  2034.         && conf->ssl_ciphers.data == NULL
  2035.         && conf->upstream.ssl_certificate == NGX_CONF_UNSET_PTR
  2036.         && conf->upstream.ssl_certificate_key == NGX_CONF_UNSET_PTR
  2037.         && conf->upstream.ssl_passwords == NGX_CONF_UNSET_PTR
  2038.         && conf->upstream.ssl_verify == NGX_CONF_UNSET
  2039.         && conf->ssl_verify_depth == NGX_CONF_UNSET_UINT
  2040.         && conf->ssl_trusted_certificate.data == NULL
  2041.         && conf->ssl_crl.data == NULL
  2042.         && conf->upstream.ssl_session_reuse == NGX_CONF_UNSET
  2043.         && conf->ssl_conf_commands == NGX_CONF_UNSET_PTR)
  2044.     {
  2045.         if (prev->upstream.ssl) {
  2046.             conf->upstream.ssl = prev->upstream.ssl;
  2047.             return NGX_OK;
  2048.         }

  2049.         preserve = 1;

  2050.     } else {
  2051.         preserve = 0;
  2052.     }

  2053.     conf->upstream.ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t));
  2054.     if (conf->upstream.ssl == NULL) {
  2055.         return NGX_ERROR;
  2056.     }

  2057.     conf->upstream.ssl->log = cf->log;

  2058.     /*
  2059.      * special handling to preserve conf->upstream.ssl
  2060.      * in the "http" section to inherit it to all servers
  2061.      */

  2062.     if (preserve) {
  2063.         prev->upstream.ssl = conf->upstream.ssl;
  2064.     }

  2065.     return NGX_OK;
  2066. }


  2067. static ngx_int_t
  2068. ngx_http_uwsgi_set_ssl(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *uwcf)
  2069. {
  2070.     ngx_pool_cleanup_t  *cln;

  2071.     if (uwcf->upstream.ssl->ctx) {
  2072.         return NGX_OK;
  2073.     }

  2074.     if (ngx_ssl_create(uwcf->upstream.ssl, uwcf->ssl_protocols, NULL)
  2075.         != NGX_OK)
  2076.     {
  2077.         return NGX_ERROR;
  2078.     }

  2079.     cln = ngx_pool_cleanup_add(cf->pool, 0);
  2080.     if (cln == NULL) {
  2081.         ngx_ssl_cleanup_ctx(uwcf->upstream.ssl);
  2082.         return NGX_ERROR;
  2083.     }

  2084.     cln->handler = ngx_ssl_cleanup_ctx;
  2085.     cln->data = uwcf->upstream.ssl;

  2086.     if (ngx_ssl_ciphers(cf, uwcf->upstream.ssl, &uwcf->ssl_ciphers, 0)
  2087.         != NGX_OK)
  2088.     {
  2089.         return NGX_ERROR;
  2090.     }

  2091.     if (uwcf->upstream.ssl_certificate
  2092.         && uwcf->upstream.ssl_certificate->value.len)
  2093.     {
  2094.         if (uwcf->upstream.ssl_certificate_key == NULL) {
  2095.             ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
  2096.                           "no \"uwsgi_ssl_certificate_key\" is defined "
  2097.                           "for certificate \"%V\"",
  2098.                           &uwcf->upstream.ssl_certificate->value);
  2099.             return NGX_ERROR;
  2100.         }

  2101.         if (uwcf->upstream.ssl_certificate->lengths == NULL
  2102.             && uwcf->upstream.ssl_certificate_key->lengths == NULL)
  2103.         {
  2104.             if (ngx_ssl_certificate(cf, uwcf->upstream.ssl,
  2105.                                     &uwcf->upstream.ssl_certificate->value,
  2106.                                     &uwcf->upstream.ssl_certificate_key->value,
  2107.                                     uwcf->upstream.ssl_passwords)
  2108.                 != NGX_OK)
  2109.             {
  2110.                 return NGX_ERROR;
  2111.             }
  2112.         }
  2113.     }

  2114.     if (uwcf->upstream.ssl_verify) {
  2115.         if (uwcf->ssl_trusted_certificate.len == 0) {
  2116.             ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
  2117.                       "no uwsgi_ssl_trusted_certificate for uwsgi_ssl_verify");
  2118.             return NGX_ERROR;
  2119.         }

  2120.         if (ngx_ssl_trusted_certificate(cf, uwcf->upstream.ssl,
  2121.                                         &uwcf->ssl_trusted_certificate,
  2122.                                         uwcf->ssl_verify_depth)
  2123.             != NGX_OK)
  2124.         {
  2125.             return NGX_ERROR;
  2126.         }

  2127.         if (ngx_ssl_crl(cf, uwcf->upstream.ssl, &uwcf->ssl_crl) != NGX_OK) {
  2128.             return NGX_ERROR;
  2129.         }
  2130.     }

  2131.     if (ngx_ssl_client_session_cache(cf, uwcf->upstream.ssl,
  2132.                                      uwcf->upstream.ssl_session_reuse)
  2133.         != NGX_OK)
  2134.     {
  2135.         return NGX_ERROR;
  2136.     }

  2137.     if (ngx_ssl_conf_commands(cf, uwcf->upstream.ssl, uwcf->ssl_conf_commands)
  2138.         != NGX_OK)
  2139.     {
  2140.         return NGX_ERROR;
  2141.     }

  2142.     return NGX_OK;
  2143. }

  2144. #endif