src/http/modules/ngx_http_uwsgi_module.c - nginx source code

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_password_file(ngx_conf_t *cf,
  75.     ngx_command_t *cmd, void *conf);
  76. static char *ngx_http_uwsgi_ssl_conf_command_check(ngx_conf_t *cf, void *post,
  77.     void *data);
  78. static ngx_int_t ngx_http_uwsgi_merge_ssl(ngx_conf_t *cf,
  79.     ngx_http_uwsgi_loc_conf_t *conf, ngx_http_uwsgi_loc_conf_t *prev);
  80. static ngx_int_t ngx_http_uwsgi_set_ssl(ngx_conf_t *cf,
  81.     ngx_http_uwsgi_loc_conf_t *uwcf);
  82. #endif


  83. static ngx_conf_num_bounds_t  ngx_http_uwsgi_modifier_bounds = {
  84.     ngx_conf_check_num_bounds, 0, 255
  85. };


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


  100. #if (NGX_HTTP_SSL)

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

  110. static ngx_conf_post_t  ngx_http_uwsgi_ssl_conf_command_post =
  111.     { ngx_http_uwsgi_ssl_conf_command_check };

  112. #endif


  113. ngx_module_t  ngx_http_uwsgi_module;


  114. static ngx_command_t ngx_http_uwsgi_commands[] = {

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

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

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

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

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

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

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

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

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

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

  175.     { ngx_string("uwsgi_connect_timeout"),
  176.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  177.       ngx_conf_set_msec_slot,
  178.       NGX_HTTP_LOC_CONF_OFFSET,
  179.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.connect_timeout),
  180.       NULL },

  181.     { ngx_string("uwsgi_send_timeout"),
  182.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  183.       ngx_conf_set_msec_slot,
  184.       NGX_HTTP_LOC_CONF_OFFSET,
  185.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.send_timeout),
  186.       NULL },

  187.     { ngx_string("uwsgi_buffer_size"),
  188.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  189.       ngx_conf_set_size_slot,
  190.       NGX_HTTP_LOC_CONF_OFFSET,
  191.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.buffer_size),
  192.       NULL },

  193.     { ngx_string("uwsgi_pass_request_headers"),
  194.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
  195.       ngx_conf_set_flag_slot,
  196.       NGX_HTTP_LOC_CONF_OFFSET,
  197.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.pass_request_headers),
  198.       NULL },

  199.     { ngx_string("uwsgi_pass_request_body"),
  200.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
  201.       ngx_conf_set_flag_slot,
  202.       NGX_HTTP_LOC_CONF_OFFSET,
  203.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.pass_request_body),
  204.       NULL },

  205.     { ngx_string("uwsgi_intercept_errors"),
  206.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
  207.       ngx_conf_set_flag_slot,
  208.       NGX_HTTP_LOC_CONF_OFFSET,
  209.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.intercept_errors),
  210.       NULL },

  211.     { ngx_string("uwsgi_read_timeout"),
  212.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  213.       ngx_conf_set_msec_slot,
  214.       NGX_HTTP_LOC_CONF_OFFSET,
  215.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.read_timeout),
  216.       NULL },

  217.     { ngx_string("uwsgi_buffers"),
  218.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
  219.       ngx_conf_set_bufs_slot,
  220.       NGX_HTTP_LOC_CONF_OFFSET,
  221.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.bufs),
  222.       NULL },

  223.     { ngx_string("uwsgi_busy_buffers_size"),
  224.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  225.       ngx_conf_set_size_slot,
  226.       NGX_HTTP_LOC_CONF_OFFSET,
  227.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.busy_buffers_size_conf),
  228.       NULL },

  229.     { ngx_string("uwsgi_force_ranges"),
  230.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
  231.       ngx_conf_set_flag_slot,
  232.       NGX_HTTP_LOC_CONF_OFFSET,
  233.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.force_ranges),
  234.       NULL },

  235.     { ngx_string("uwsgi_limit_rate"),
  236.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  237.       ngx_http_set_complex_value_size_slot,
  238.       NGX_HTTP_LOC_CONF_OFFSET,
  239.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.limit_rate),
  240.       NULL },

  241. #if (NGX_HTTP_CACHE)

  242.     { ngx_string("uwsgi_cache"),
  243.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  244.       ngx_http_uwsgi_cache,
  245.       NGX_HTTP_LOC_CONF_OFFSET,
  246.       0,
  247.       NULL },

  248.     { ngx_string("uwsgi_cache_key"),
  249.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  250.       ngx_http_uwsgi_cache_key,
  251.       NGX_HTTP_LOC_CONF_OFFSET,
  252.       0,
  253.       NULL },

  254.     { ngx_string("uwsgi_cache_path"),
  255.       NGX_HTTP_MAIN_CONF|NGX_CONF_2MORE,
  256.       ngx_http_file_cache_set_slot,
  257.       NGX_HTTP_MAIN_CONF_OFFSET,
  258.       offsetof(ngx_http_uwsgi_main_conf_t, caches),
  259.       &ngx_http_uwsgi_module },

  260.     { ngx_string("uwsgi_cache_bypass"),
  261.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
  262.       ngx_http_set_predicate_slot,
  263.       NGX_HTTP_LOC_CONF_OFFSET,
  264.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_bypass),
  265.       NULL },

  266.     { ngx_string("uwsgi_no_cache"),
  267.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
  268.       ngx_http_set_predicate_slot,
  269.       NGX_HTTP_LOC_CONF_OFFSET,
  270.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.no_cache),
  271.       NULL },

  272.     { ngx_string("uwsgi_cache_valid"),
  273.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
  274.       ngx_http_file_cache_valid_set_slot,
  275.       NGX_HTTP_LOC_CONF_OFFSET,
  276.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_valid),
  277.       NULL },

  278.     { ngx_string("uwsgi_cache_min_uses"),
  279.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  280.       ngx_conf_set_num_slot,
  281.       NGX_HTTP_LOC_CONF_OFFSET,
  282.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_min_uses),
  283.       NULL },

  284.     { ngx_string("uwsgi_cache_max_range_offset"),
  285.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  286.       ngx_conf_set_off_slot,
  287.       NGX_HTTP_LOC_CONF_OFFSET,
  288.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_max_range_offset),
  289.       NULL },

  290.     { ngx_string("uwsgi_cache_use_stale"),
  291.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
  292.       ngx_conf_set_bitmask_slot,
  293.       NGX_HTTP_LOC_CONF_OFFSET,
  294.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_use_stale),
  295.       &ngx_http_uwsgi_next_upstream_masks },

  296.     { ngx_string("uwsgi_cache_methods"),
  297.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
  298.       ngx_conf_set_bitmask_slot,
  299.       NGX_HTTP_LOC_CONF_OFFSET,
  300.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_methods),
  301.       &ngx_http_upstream_cache_method_mask },

  302.     { ngx_string("uwsgi_cache_lock"),
  303.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
  304.       ngx_conf_set_flag_slot,
  305.       NGX_HTTP_LOC_CONF_OFFSET,
  306.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_lock),
  307.       NULL },

  308.     { ngx_string("uwsgi_cache_lock_timeout"),
  309.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  310.       ngx_conf_set_msec_slot,
  311.       NGX_HTTP_LOC_CONF_OFFSET,
  312.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_lock_timeout),
  313.       NULL },

  314.     { ngx_string("uwsgi_cache_lock_age"),
  315.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  316.       ngx_conf_set_msec_slot,
  317.       NGX_HTTP_LOC_CONF_OFFSET,
  318.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_lock_age),
  319.       NULL },

  320.     { ngx_string("uwsgi_cache_revalidate"),
  321.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
  322.       ngx_conf_set_flag_slot,
  323.       NGX_HTTP_LOC_CONF_OFFSET,
  324.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_revalidate),
  325.       NULL },

  326.     { ngx_string("uwsgi_cache_background_update"),
  327.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  328.       ngx_conf_set_flag_slot,
  329.       NGX_HTTP_LOC_CONF_OFFSET,
  330.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_background_update),
  331.       NULL },

  332. #endif

  333.     { ngx_string("uwsgi_temp_path"),
  334.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1234,
  335.       ngx_conf_set_path_slot,
  336.       NGX_HTTP_LOC_CONF_OFFSET,
  337.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.temp_path),
  338.       NULL },

  339.     { ngx_string("uwsgi_max_temp_file_size"),
  340.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  341.       ngx_conf_set_size_slot,
  342.       NGX_HTTP_LOC_CONF_OFFSET,
  343.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.max_temp_file_size_conf),
  344.       NULL },

  345.     { ngx_string("uwsgi_temp_file_write_size"),
  346.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  347.       ngx_conf_set_size_slot,
  348.       NGX_HTTP_LOC_CONF_OFFSET,
  349.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.temp_file_write_size_conf),
  350.       NULL },

  351.     { ngx_string("uwsgi_next_upstream"),
  352.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
  353.       ngx_conf_set_bitmask_slot,
  354.       NGX_HTTP_LOC_CONF_OFFSET,
  355.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.next_upstream),
  356.       &ngx_http_uwsgi_next_upstream_masks },

  357.     { ngx_string("uwsgi_next_upstream_tries"),
  358.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  359.       ngx_conf_set_num_slot,
  360.       NGX_HTTP_LOC_CONF_OFFSET,
  361.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.next_upstream_tries),
  362.       NULL },

  363.     { ngx_string("uwsgi_next_upstream_timeout"),
  364.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  365.       ngx_conf_set_msec_slot,
  366.       NGX_HTTP_LOC_CONF_OFFSET,
  367.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.next_upstream_timeout),
  368.       NULL },

  369.     { ngx_string("uwsgi_param"),
  370.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE23,
  371.       ngx_http_upstream_param_set_slot,
  372.       NGX_HTTP_LOC_CONF_OFFSET,
  373.       offsetof(ngx_http_uwsgi_loc_conf_t, params_source),
  374.       NULL },

  375.     { ngx_string("uwsgi_string"),
  376.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  377.       ngx_conf_set_str_slot,
  378.       NGX_HTTP_LOC_CONF_OFFSET,
  379.       offsetof(ngx_http_uwsgi_loc_conf_t, uwsgi_string),
  380.       NULL },

  381.     { ngx_string("uwsgi_pass_header"),
  382.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  383.       ngx_conf_set_str_array_slot,
  384.       NGX_HTTP_LOC_CONF_OFFSET,
  385.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.pass_headers),
  386.       NULL },

  387.     { ngx_string("uwsgi_hide_header"),
  388.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  389.       ngx_conf_set_str_array_slot,
  390.       NGX_HTTP_LOC_CONF_OFFSET,
  391.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.hide_headers),
  392.       NULL },

  393.     { ngx_string("uwsgi_ignore_headers"),
  394.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
  395.       ngx_conf_set_bitmask_slot,
  396.       NGX_HTTP_LOC_CONF_OFFSET,
  397.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.ignore_headers),
  398.       &ngx_http_upstream_ignore_headers_masks },

  399. #if (NGX_HTTP_SSL)

  400.     { ngx_string("uwsgi_ssl_session_reuse"),
  401.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
  402.       ngx_conf_set_flag_slot,
  403.       NGX_HTTP_LOC_CONF_OFFSET,
  404.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.ssl_session_reuse),
  405.       NULL },

  406.     { ngx_string("uwsgi_ssl_protocols"),
  407.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
  408.       ngx_conf_set_bitmask_slot,
  409.       NGX_HTTP_LOC_CONF_OFFSET,
  410.       offsetof(ngx_http_uwsgi_loc_conf_t, ssl_protocols),
  411.       &ngx_http_uwsgi_ssl_protocols },

  412.     { ngx_string("uwsgi_ssl_ciphers"),
  413.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  414.       ngx_conf_set_str_slot,
  415.       NGX_HTTP_LOC_CONF_OFFSET,
  416.       offsetof(ngx_http_uwsgi_loc_conf_t, ssl_ciphers),
  417.       NULL },

  418.     { ngx_string("uwsgi_ssl_name"),
  419.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  420.       ngx_http_set_complex_value_slot,
  421.       NGX_HTTP_LOC_CONF_OFFSET,
  422.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.ssl_name),
  423.       NULL },

  424.     { ngx_string("uwsgi_ssl_server_name"),
  425.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
  426.       ngx_conf_set_flag_slot,
  427.       NGX_HTTP_LOC_CONF_OFFSET,
  428.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.ssl_server_name),
  429.       NULL },

  430.     { ngx_string("uwsgi_ssl_verify"),
  431.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
  432.       ngx_conf_set_flag_slot,
  433.       NGX_HTTP_LOC_CONF_OFFSET,
  434.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.ssl_verify),
  435.       NULL },

  436.     { ngx_string("uwsgi_ssl_verify_depth"),
  437.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  438.       ngx_conf_set_num_slot,
  439.       NGX_HTTP_LOC_CONF_OFFSET,
  440.       offsetof(ngx_http_uwsgi_loc_conf_t, ssl_verify_depth),
  441.       NULL },

  442.     { ngx_string("uwsgi_ssl_trusted_certificate"),
  443.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  444.       ngx_conf_set_str_slot,
  445.       NGX_HTTP_LOC_CONF_OFFSET,
  446.       offsetof(ngx_http_uwsgi_loc_conf_t, ssl_trusted_certificate),
  447.       NULL },

  448.     { ngx_string("uwsgi_ssl_crl"),
  449.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  450.       ngx_conf_set_str_slot,
  451.       NGX_HTTP_LOC_CONF_OFFSET,
  452.       offsetof(ngx_http_uwsgi_loc_conf_t, ssl_crl),
  453.       NULL },

  454.     { ngx_string("uwsgi_ssl_certificate"),
  455.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  456.       ngx_http_set_complex_value_zero_slot,
  457.       NGX_HTTP_LOC_CONF_OFFSET,
  458.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.ssl_certificate),
  459.       NULL },

  460.     { ngx_string("uwsgi_ssl_certificate_key"),
  461.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  462.       ngx_http_set_complex_value_zero_slot,
  463.       NGX_HTTP_LOC_CONF_OFFSET,
  464.       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.ssl_certificate_key),
  465.       NULL },

  466.     { ngx_string("uwsgi_ssl_password_file"),
  467.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  468.       ngx_http_uwsgi_ssl_password_file,
  469.       NGX_HTTP_LOC_CONF_OFFSET,
  470.       0,
  471.       NULL },

  472.     { ngx_string("uwsgi_ssl_conf_command"),
  473.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
  474.       ngx_conf_set_keyval_slot,
  475.       NGX_HTTP_LOC_CONF_OFFSET,
  476.       offsetof(ngx_http_uwsgi_loc_conf_t, ssl_conf_commands),
  477.       &ngx_http_uwsgi_ssl_conf_command_post },

  478. #endif

  479.       ngx_null_command
  480. };


  481. static ngx_http_module_t ngx_http_uwsgi_module_ctx = {
  482.     NULL,                                  /* preconfiguration */
  483.     NULL,                                  /* postconfiguration */

  484.     ngx_http_uwsgi_create_main_conf,       /* create main configuration */
  485.     NULL,                                  /* init main configuration */

  486.     NULL,                                  /* create server configuration */
  487.     NULL,                                  /* merge server configuration */

  488.     ngx_http_uwsgi_create_loc_conf,        /* create location configuration */
  489.     ngx_http_uwsgi_merge_loc_conf          /* merge location configuration */
  490. };


  491. ngx_module_t ngx_http_uwsgi_module = {
  492.     NGX_MODULE_V1,
  493.     &ngx_http_uwsgi_module_ctx,            /* module context */
  494.     ngx_http_uwsgi_commands,               /* module directives */
  495.     NGX_HTTP_MODULE,                       /* module type */
  496.     NULL,                                  /* init master */
  497.     NULL,                                  /* init module */
  498.     NULL,                                  /* init process */
  499.     NULL,                                  /* init thread */
  500.     NULL,                                  /* exit thread */
  501.     NULL,                                  /* exit process */
  502.     NULL,                                  /* exit master */
  503.     NGX_MODULE_V1_PADDING
  504. };


  505. static ngx_str_t ngx_http_uwsgi_hide_headers[] = {
  506.     ngx_string("X-Accel-Expires"),
  507.     ngx_string("X-Accel-Redirect"),
  508.     ngx_string("X-Accel-Limit-Rate"),
  509.     ngx_string("X-Accel-Buffering"),
  510.     ngx_string("X-Accel-Charset"),
  511.     ngx_null_string
  512. };


  513. #if (NGX_HTTP_CACHE)

  514. static ngx_keyval_t  ngx_http_uwsgi_cache_headers[] = {
  515.     { ngx_string("HTTP_IF_MODIFIED_SINCE"),
  516.       ngx_string("$upstream_cache_last_modified") },
  517.     { ngx_string("HTTP_IF_UNMODIFIED_SINCE"), ngx_string("") },
  518.     { ngx_string("HTTP_IF_NONE_MATCH"), ngx_string("$upstream_cache_etag") },
  519.     { ngx_string("HTTP_IF_MATCH"), ngx_string("") },
  520.     { ngx_string("HTTP_RANGE"), ngx_string("") },
  521.     { ngx_string("HTTP_IF_RANGE"), ngx_string("") },
  522.     { ngx_null_string, ngx_null_string }
  523. };

  524. #endif


  525. static ngx_path_init_t ngx_http_uwsgi_temp_path = {
  526.     ngx_string(NGX_HTTP_UWSGI_TEMP_PATH), { 1, 2, 0 }
  527. };


  528. static ngx_int_t
  529. ngx_http_uwsgi_handler(ngx_http_request_t *r)
  530. {
  531.     ngx_int_t                    rc;
  532.     ngx_http_status_t           *status;
  533.     ngx_http_upstream_t         *u;
  534.     ngx_http_uwsgi_loc_conf_t   *uwcf;
  535. #if (NGX_HTTP_CACHE)
  536.     ngx_http_uwsgi_main_conf_t  *uwmcf;
  537. #endif

  538.     if (ngx_http_upstream_create(r) != NGX_OK) {
  539.         return NGX_HTTP_INTERNAL_SERVER_ERROR;
  540.     }

  541.     status = ngx_pcalloc(r->pool, sizeof(ngx_http_status_t));
  542.     if (status == NULL) {
  543.         return NGX_HTTP_INTERNAL_SERVER_ERROR;
  544.     }

  545.     ngx_http_set_ctx(r, status, ngx_http_uwsgi_module);

  546.     uwcf = ngx_http_get_module_loc_conf(r, ngx_http_uwsgi_module);

  547.     u = r->upstream;

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

  549. #if (NGX_HTTP_SSL)
  550.         u->ssl = uwcf->ssl;

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

  553.         } else {
  554.             ngx_str_set(&u->schema, "uwsgi://");
  555.         }
  556. #else
  557.         ngx_str_set(&u->schema, "uwsgi://");
  558. #endif

  559.     } else {
  560.         if (ngx_http_uwsgi_eval(r, uwcf) != NGX_OK) {
  561.             return NGX_HTTP_INTERNAL_SERVER_ERROR;
  562.         }
  563.     }

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

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

  566. #if (NGX_HTTP_CACHE)
  567.     uwmcf = ngx_http_get_module_main_conf(r, ngx_http_uwsgi_module);

  568.     u->caches = &uwmcf->caches;
  569.     u->create_key = ngx_http_uwsgi_create_key;
  570. #endif

  571.     u->create_request = ngx_http_uwsgi_create_request;
  572.     u->reinit_request = ngx_http_uwsgi_reinit_request;
  573.     u->process_header = ngx_http_uwsgi_process_status_line;
  574.     u->abort_request = ngx_http_uwsgi_abort_request;
  575.     u->finalize_request = ngx_http_uwsgi_finalize_request;
  576.     r->state = 0;

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

  578.     u->pipe = ngx_pcalloc(r->pool, sizeof(ngx_event_pipe_t));
  579.     if (u->pipe == NULL) {
  580.         return NGX_HTTP_INTERNAL_SERVER_ERROR;
  581.     }

  582.     u->pipe->input_filter = ngx_event_pipe_copy_input_filter;
  583.     u->pipe->input_ctx = r;

  584.     u->input_filter_init = ngx_http_uwsgi_input_filter_init;
  585.     u->input_filter = ngx_http_upstream_non_buffered_filter;
  586.     u->input_filter_ctx = r;

  587.     if (!uwcf->upstream.request_buffering
  588.         && uwcf->upstream.pass_request_body
  589.         && !r->headers_in.chunked)
  590.     {
  591.         r->request_body_no_buffering = 1;
  592.     }

  593.     rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init);

  594.     if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
  595.         return rc;
  596.     }

  597.     return NGX_DONE;
  598. }


  599. static ngx_int_t
  600. ngx_http_uwsgi_eval(ngx_http_request_t *r, ngx_http_uwsgi_loc_conf_t * uwcf)
  601. {
  602.     size_t                add;
  603.     ngx_url_t             url;
  604.     ngx_http_upstream_t  *u;

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

  606.     if (ngx_http_script_run(r, &url.url, uwcf->uwsgi_lengths->elts, 0,
  607.                             uwcf->uwsgi_values->elts)
  608.         == NULL)
  609.     {
  610.         return NGX_ERROR;
  611.     }

  612.     if (url.url.len > 8
  613.         && ngx_strncasecmp(url.url.data, (u_char *) "uwsgi://", 8) == 0)
  614.     {
  615.         add = 8;

  616.     } else if (url.url.len > 9
  617.                && ngx_strncasecmp(url.url.data, (u_char *) "suwsgi://", 9) == 0)
  618.     {

  619. #if (NGX_HTTP_SSL)
  620.         add = 9;
  621.         r->upstream->ssl = 1;
  622. #else
  623.         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  624.                       "suwsgi protocol requires SSL support");
  625.         return NGX_ERROR;
  626. #endif

  627.     } else {
  628.         add = 0;
  629.     }

  630.     u = r->upstream;

  631.     if (add) {
  632.         u->schema.len = add;
  633.         u->schema.data = url.url.data;

  634.         url.url.data += add;
  635.         url.url.len -= add;

  636.     } else {
  637.         ngx_str_set(&u->schema, "uwsgi://");
  638.     }

  639.     url.no_resolve = 1;

  640.     if (ngx_parse_url(r->pool, &url) != NGX_OK) {
  641.         if (url.err) {
  642.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  643.                           "%s in upstream \"%V\"", url.err, &url.url);
  644.         }

  645.         return NGX_ERROR;
  646.     }

  647.     u->resolved = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_resolved_t));
  648.     if (u->resolved == NULL) {
  649.         return NGX_ERROR;
  650.     }

  651.     if (url.addrs) {
  652.         u->resolved->sockaddr = url.addrs[0].sockaddr;
  653.         u->resolved->socklen = url.addrs[0].socklen;
  654.         u->resolved->name = url.addrs[0].name;
  655.         u->resolved->naddrs = 1;
  656.     }

  657.     u->resolved->host = url.host;
  658.     u->resolved->port = url.port;
  659.     u->resolved->no_port = url.no_port;

  660.     return NGX_OK;
  661. }


  662. #if (NGX_HTTP_CACHE)

  663. static ngx_int_t
  664. ngx_http_uwsgi_create_key(ngx_http_request_t *r)
  665. {
  666.     ngx_str_t                  *key;
  667.     ngx_http_uwsgi_loc_conf_t  *uwcf;

  668.     key = ngx_array_push(&r->cache->keys);
  669.     if (key == NULL) {
  670.         return NGX_ERROR;
  671.     }

  672.     uwcf = ngx_http_get_module_loc_conf(r, ngx_http_uwsgi_module);

  673.     if (ngx_http_complex_value(r, &uwcf->cache_key, key) != NGX_OK) {
  674.         return NGX_ERROR;
  675.     }

  676.     return NGX_OK;
  677. }

  678. #endif


  679. static ngx_int_t
  680. ngx_http_uwsgi_create_request(ngx_http_request_t *r)
  681. {
  682.     u_char                        ch, sep, *lowcase_key;
  683.     size_t                        key_len, val_len, len, allocated;
  684.     ngx_uint_t                    i, n, hash, skip_empty, header_params;
  685.     ngx_buf_t                    *b;
  686.     ngx_chain_t                  *cl, *body;
  687.     ngx_list_part_t              *part;
  688.     ngx_table_elt_t              *header, *hn, **ignored;
  689.     ngx_http_uwsgi_params_t      *params;
  690.     ngx_http_script_code_pt       code;
  691.     ngx_http_script_engine_t      e, le;
  692.     ngx_http_uwsgi_loc_conf_t    *uwcf;
  693.     ngx_http_script_len_code_pt   lcode;

  694.     len = 0;
  695.     header_params = 0;
  696.     ignored = NULL;

  697.     uwcf = ngx_http_get_module_loc_conf(r, ngx_http_uwsgi_module);

  698. #if (NGX_HTTP_CACHE)
  699.     params = r->upstream->cacheable ? &uwcf->params_cache : &uwcf->params;
  700. #else
  701.     params = &uwcf->params;
  702. #endif

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

  705.         ngx_http_script_flush_no_cacheable_variables(r, params->flushes);
  706.         le.flushed = 1;

  707.         le.ip = params->lengths->elts;
  708.         le.request = r;

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

  710.             lcode = *(ngx_http_script_len_code_pt *) le.ip;
  711.             key_len = lcode(&le);

  712.             lcode = *(ngx_http_script_len_code_pt *) le.ip;
  713.             skip_empty = lcode(&le);

  714.             for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode(&le)) {
  715.                 lcode = *(ngx_http_script_len_code_pt *) le.ip;
  716.             }
  717.             le.ip += sizeof(uintptr_t);

  718.             if (skip_empty && val_len == 0) {
  719.                 continue;
  720.             }

  721.             len += 2 + key_len + 2 + val_len;
  722.         }
  723.     }

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

  725.         allocated = 0;
  726.         lowcase_key = NULL;

  727.         if (ngx_http_link_multi_headers(r) != NGX_OK) {
  728.             return NGX_ERROR;
  729.         }

  730.         if (params->number || r->headers_in.multi) {
  731.             n = 0;
  732.             part = &r->headers_in.headers.part;

  733.             while (part) {
  734.                 n += part->nelts;
  735.                 part = part->next;
  736.             }

  737.             ignored = ngx_palloc(r->pool, n * sizeof(void *));
  738.             if (ignored == NULL) {
  739.                 return NGX_ERROR;
  740.             }
  741.         }

  742.         part = &r->headers_in.headers.part;
  743.         header = part->elts;

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

  745.             if (i >= part->nelts) {
  746.                 if (part->next == NULL) {
  747.                     break;
  748.                 }

  749.                 part = part->next;
  750.                 header = part->elts;
  751.                 i = 0;
  752.             }

  753.             for (n = 0; n < header_params; n++) {
  754.                 if (&header[i] == ignored[n]) {
  755.                     goto next_length;
  756.                 }
  757.             }

  758.             if (params->number) {
  759.                 if (allocated < header[i].key.len) {
  760.                     allocated = header[i].key.len + 16;
  761.                     lowcase_key = ngx_pnalloc(r->pool, allocated);
  762.                     if (lowcase_key == NULL) {
  763.                         return NGX_ERROR;
  764.                     }
  765.                 }

  766.                 hash = 0;

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

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

  771.                     } else if (ch == '-') {
  772.                         ch = '_';
  773.                     }

  774.                     hash = ngx_hash(hash, ch);
  775.                     lowcase_key[n] = ch;
  776.                 }

  777.                 if (ngx_hash_find(&params->hash, hash, lowcase_key, n)) {
  778.                     ignored[header_params++] = &header[i];
  779.                     continue;
  780.                 }
  781.             }

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

  784.             for (hn = header[i].next; hn; hn = hn->next) {
  785.                 len += hn->value.len + 2;
  786.                 ignored[header_params++] = hn;
  787.             }

  788.         next_length:

  789.             continue;
  790.         }
  791.     }

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

  793. #if 0
  794.     /* allow custom uwsgi packet */
  795.     if (len > 0 && len < 2) {
  796.         ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
  797.                       "uwsgi request is too little: %uz", len);
  798.         return NGX_ERROR;
  799.     }
  800. #endif

  801.     if (len > 65535) {
  802.         ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
  803.                       "uwsgi request is too big: %uz", len);
  804.         return NGX_ERROR;
  805.     }

  806.     b = ngx_create_temp_buf(r->pool, len + 4);
  807.     if (b == NULL) {
  808.         return NGX_ERROR;
  809.     }

  810.     cl = ngx_alloc_chain_link(r->pool);
  811.     if (cl == NULL) {
  812.         return NGX_ERROR;
  813.     }

  814.     cl->buf = b;

  815.     *b->last++ = (u_char) uwcf->modifier1;
  816.     *b->last++ = (u_char) (len & 0xff);
  817.     *b->last++ = (u_char) ((len >> 8) & 0xff);
  818.     *b->last++ = (u_char) uwcf->modifier2;

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

  821.         e.ip = params->values->elts;
  822.         e.pos = b->last;
  823.         e.request = r;
  824.         e.flushed = 1;

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

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

  827.             lcode = *(ngx_http_script_len_code_pt *) le.ip;
  828.             key_len = (u_char) lcode(&le);

  829.             lcode = *(ngx_http_script_len_code_pt *) le.ip;
  830.             skip_empty = lcode(&le);

  831.             for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode(&le)) {
  832.                 lcode = *(ngx_http_script_len_code_pt *) le.ip;
  833.             }
  834.             le.ip += sizeof(uintptr_t);

  835.             if (skip_empty && val_len == 0) {
  836.                 e.skip = 1;

  837.                 while (*(uintptr_t *) e.ip) {
  838.                     code = *(ngx_http_script_code_pt *) e.ip;
  839.                     code((ngx_http_script_engine_t *) &e);
  840.                 }
  841.                 e.ip += sizeof(uintptr_t);

  842.                 e.skip = 0;

  843.                 continue;
  844.             }

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

  847.             code = *(ngx_http_script_code_pt *) e.ip;
  848.             code((ngx_http_script_engine_t *) &e);

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

  851.             while (*(uintptr_t *) e.ip) {
  852.                 code = *(ngx_http_script_code_pt *) e.ip;
  853.                 code((ngx_http_script_engine_t *) &e);
  854.             }

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

  856.             ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  857.                            "uwsgi param: \"%*s: %*s\"",
  858.                            key_len, e.pos - (key_len + 2 + val_len),
  859.                            val_len, e.pos - val_len);
  860.         }

  861.         b->last = e.pos;
  862.     }

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

  864.         part = &r->headers_in.headers.part;
  865.         header = part->elts;

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

  867.             if (i >= part->nelts) {
  868.                 if (part->next == NULL) {
  869.                     break;
  870.                 }

  871.                 part = part->next;
  872.                 header = part->elts;
  873.                 i = 0;
  874.             }

  875.             for (n = 0; n < header_params; n++) {
  876.                 if (&header[i] == ignored[n]) {
  877.                     goto next_value;
  878.                 }
  879.             }

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

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

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

  888.                 } else if (ch == '-') {
  889.                     ch = '_';
  890.                 }

  891.                 *b->last++ = ch;
  892.             }

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

  894.             for (hn = header[i].next; hn; hn = hn->next) {
  895.                 val_len += hn->value.len + 2;
  896.             }

  897.             *b->last++ = (u_char) (val_len & 0xff);
  898.             *b->last++ = (u_char) ((val_len >> 8) & 0xff);
  899.             b->last = ngx_copy(b->last, header[i].value.data,
  900.                                header[i].value.len);

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

  902.                 if (header[i].key.len == sizeof("Cookie") - 1
  903.                     && ngx_strncasecmp(header[i].key.data, (u_char *) "Cookie",
  904.                                        sizeof("Cookie") - 1)
  905.                        == 0)
  906.                 {
  907.                     sep = ';';

  908.                 } else {
  909.                     sep = ',';
  910.                 }

  911.                 for (hn = header[i].next; hn; hn = hn->next) {
  912.                     *b->last++ = sep;
  913.                     *b->last++ = ' ';
  914.                     b->last = ngx_copy(b->last, hn->value.data, hn->value.len);
  915.                 }
  916.             }

  917.             ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  918.                            "uwsgi param: \"%*s: %*s\"",
  919.                            key_len, b->last - (key_len + 2 + val_len),
  920.                            val_len, b->last - val_len);
  921.         next_value:

  922.             continue;
  923.         }
  924.     }

  925.     b->last = ngx_copy(b->last, uwcf->uwsgi_string.data,
  926.                        uwcf->uwsgi_string.len);

  927.     if (r->request_body_no_buffering) {
  928.         r->upstream->request_bufs = cl;

  929.     } else if (uwcf->upstream.pass_request_body) {
  930.         body = r->upstream->request_bufs;
  931.         r->upstream->request_bufs = cl;

  932.         while (body) {
  933.             b = ngx_alloc_buf(r->pool);
  934.             if (b == NULL) {
  935.                 return NGX_ERROR;
  936.             }

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

  938.             cl->next = ngx_alloc_chain_link(r->pool);
  939.             if (cl->next == NULL) {
  940.                 return NGX_ERROR;
  941.             }

  942.             cl = cl->next;
  943.             cl->buf = b;

  944.             body = body->next;
  945.         }

  946.     } else {
  947.         r->upstream->request_bufs = cl;
  948.     }

  949.     b->flush = 1;
  950.     cl->next = NULL;

  951.     return NGX_OK;
  952. }


  953. static ngx_int_t
  954. ngx_http_uwsgi_reinit_request(ngx_http_request_t *r)
  955. {
  956.     ngx_http_status_t  *status;

  957.     status = ngx_http_get_module_ctx(r, ngx_http_uwsgi_module);

  958.     if (status == NULL) {
  959.         return NGX_OK;
  960.     }

  961.     status->code = 0;
  962.     status->count = 0;
  963.     status->start = NULL;
  964.     status->end = NULL;

  965.     r->upstream->process_header = ngx_http_uwsgi_process_status_line;
  966.     r->state = 0;

  967.     return NGX_OK;
  968. }


  969. static ngx_int_t
  970. ngx_http_uwsgi_process_status_line(ngx_http_request_t *r)
  971. {
  972.     size_t                 len;
  973.     ngx_int_t              rc;
  974.     ngx_http_status_t     *status;
  975.     ngx_http_upstream_t   *u;

  976.     status = ngx_http_get_module_ctx(r, ngx_http_uwsgi_module);

  977.     if (status == NULL) {
  978.         return NGX_ERROR;
  979.     }

  980.     u = r->upstream;

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

  982.     if (rc == NGX_AGAIN) {
  983.         return rc;
  984.     }

  985.     if (rc == NGX_ERROR) {
  986.         u->process_header = ngx_http_uwsgi_process_header;
  987.         return ngx_http_uwsgi_process_header(r);
  988.     }

  989.     if (u->state && u->state->status == 0) {
  990.         u->state->status = status->code;
  991.     }

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

  993.     len = status->end - status->start;
  994.     u->headers_in.status_line.len = len;

  995.     u->headers_in.status_line.data = ngx_pnalloc(r->pool, len);
  996.     if (u->headers_in.status_line.data == NULL) {
  997.         return NGX_ERROR;
  998.     }

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

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

  1003.     u->process_header = ngx_http_uwsgi_process_header;

  1004.     return ngx_http_uwsgi_process_header(r);
  1005. }


  1006. static ngx_int_t
  1007. ngx_http_uwsgi_process_header(ngx_http_request_t *r)
  1008. {
  1009.     ngx_str_t                      *status_line;
  1010.     ngx_int_t                       rc, status;
  1011.     ngx_table_elt_t                *h;
  1012.     ngx_http_upstream_t            *u;
  1013.     ngx_http_upstream_header_t     *hh;
  1014.     ngx_http_upstream_main_conf_t  *umcf;

  1015.     umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module);

  1016.     for ( ;; ) {

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

  1018.         if (rc == NGX_OK) {

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

  1020.             h = ngx_list_push(&r->upstream->headers_in.headers);
  1021.             if (h == NULL) {
  1022.                 return NGX_ERROR;
  1023.             }

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

  1025.             h->key.len = r->header_name_end - r->header_name_start;
  1026.             h->value.len = r->header_end - r->header_start;

  1027.             h->key.data = ngx_pnalloc(r->pool,
  1028.                                       h->key.len + 1 + h->value.len + 1
  1029.                                       + h->key.len);
  1030.             if (h->key.data == NULL) {
  1031.                 h->hash = 0;
  1032.                 return NGX_ERROR;
  1033.             }

  1034.             h->value.data = h->key.data + h->key.len + 1;
  1035.             h->lowcase_key = h->key.data + h->key.len + 1 + h->value.len + 1;

  1036.             ngx_memcpy(h->key.data, r->header_name_start, h->key.len);
  1037.             h->key.data[h->key.len] = '\0';
  1038.             ngx_memcpy(h->value.data, r->header_start, h->value.len);
  1039.             h->value.data[h->value.len] = '\0';

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

  1042.             } else {
  1043.                 ngx_strlow(h->lowcase_key, h->key.data, h->key.len);
  1044.             }

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

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

  1049.                 if (rc != NGX_OK) {
  1050.                     return rc;
  1051.                 }
  1052.             }

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

  1055.             continue;
  1056.         }

  1057.         if (rc == NGX_HTTP_PARSE_HEADER_DONE) {

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

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

  1061.             u = r->upstream;

  1062.             if (u->headers_in.status_n) {
  1063.                 goto done;
  1064.             }

  1065.             if (u->headers_in.status) {
  1066.                 status_line = &u->headers_in.status->value;

  1067.                 status = ngx_atoi(status_line->data, 3);
  1068.                 if (status == NGX_ERROR) {
  1069.                     ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1070.                                   "upstream sent invalid status \"%V\"",
  1071.                                   status_line);
  1072.                     return NGX_HTTP_UPSTREAM_INVALID_HEADER;
  1073.                 }

  1074.                 u->headers_in.status_n = status;

  1075.                 if (status_line->len > 3) {
  1076.                     u->headers_in.status_line = *status_line;
  1077.                 }

  1078.             } else if (u->headers_in.location) {
  1079.                 u->headers_in.status_n = 302;
  1080.                 ngx_str_set(&u->headers_in.status_line,
  1081.                             "302 Moved Temporarily");

  1082.             } else {
  1083.                 u->headers_in.status_n = 200;
  1084.                 ngx_str_set(&u->headers_in.status_line, "200 OK");
  1085.             }

  1086.             if (u->state && u->state->status == 0) {
  1087.                 u->state->status = u->headers_in.status_n;
  1088.             }

  1089.         done:

  1090.             if (u->headers_in.status_n == NGX_HTTP_SWITCHING_PROTOCOLS
  1091.                 && r->headers_in.upgrade)
  1092.             {
  1093.                 u->upgrade = 1;
  1094.             }

  1095.             return NGX_OK;
  1096.         }

  1097.         if (rc == NGX_AGAIN) {
  1098.             return NGX_AGAIN;
  1099.         }

  1100.         /* rc == NGX_HTTP_PARSE_INVALID_HEADER */

  1101.         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1102.                       "upstream sent invalid header: \"%*s\\x%02xd...\"",
  1103.                       r->header_end - r->header_name_start,
  1104.                       r->header_name_start, *r->header_end);

  1105.         return NGX_HTTP_UPSTREAM_INVALID_HEADER;
  1106.     }
  1107. }


  1108. static ngx_int_t
  1109. ngx_http_uwsgi_input_filter_init(void *data)
  1110. {
  1111.     ngx_http_request_t   *r = data;
  1112.     ngx_http_upstream_t  *u;

  1113.     u = r->upstream;

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

  1117.     if (u->headers_in.status_n == NGX_HTTP_NO_CONTENT
  1118.         || u->headers_in.status_n == NGX_HTTP_NOT_MODIFIED)
  1119.     {
  1120.         u->pipe->length = 0;
  1121.         u->length = 0;

  1122.     } else if (r->method == NGX_HTTP_HEAD) {
  1123.         u->pipe->length = -1;
  1124.         u->length = -1;

  1125.     } else {
  1126.         u->pipe->length = u->headers_in.content_length_n;
  1127.         u->length = u->headers_in.content_length_n;
  1128.     }

  1129.     return NGX_OK;
  1130. }


  1131. static void
  1132. ngx_http_uwsgi_abort_request(ngx_http_request_t *r)
  1133. {
  1134.     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  1135.                    "abort http uwsgi request");

  1136.     return;
  1137. }


  1138. static void
  1139. ngx_http_uwsgi_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
  1140. {
  1141.     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  1142.                    "finalize http uwsgi request");

  1143.     return;
  1144. }


  1145. static void *
  1146. ngx_http_uwsgi_create_main_conf(ngx_conf_t *cf)
  1147. {
  1148.     ngx_http_uwsgi_main_conf_t  *conf;

  1149.     conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_uwsgi_main_conf_t));
  1150.     if (conf == NULL) {
  1151.         return NULL;
  1152.     }

  1153. #if (NGX_HTTP_CACHE)
  1154.     if (ngx_array_init(&conf->caches, cf->pool, 4,
  1155.                        sizeof(ngx_http_file_cache_t *))
  1156.         != NGX_OK)
  1157.     {
  1158.         return NULL;
  1159.     }
  1160. #endif

  1161.     return conf;
  1162. }


  1163. static void *
  1164. ngx_http_uwsgi_create_loc_conf(ngx_conf_t *cf)
  1165. {
  1166.     ngx_http_uwsgi_loc_conf_t  *conf;

  1167.     conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_uwsgi_loc_conf_t));
  1168.     if (conf == NULL) {
  1169.         return NULL;
  1170.     }

  1171.     /*
  1172.      * set by ngx_pcalloc():
  1173.      *
  1174.      *     conf->upstream.bufs.num = 0;
  1175.      *     conf->upstream.ignore_headers = 0;
  1176.      *     conf->upstream.next_upstream = 0;
  1177.      *     conf->upstream.cache_zone = NULL;
  1178.      *     conf->upstream.cache_use_stale = 0;
  1179.      *     conf->upstream.cache_methods = 0;
  1180.      *     conf->upstream.temp_path = NULL;
  1181.      *     conf->upstream.hide_headers_hash = { NULL, 0 };
  1182.      *     conf->upstream.store_lengths = NULL;
  1183.      *     conf->upstream.store_values = NULL;
  1184.      *
  1185.      *     conf->uwsgi_string = { 0, NULL };
  1186.      *     conf->ssl = 0;
  1187.      *     conf->ssl_protocols = 0;
  1188.      *     conf->ssl_ciphers = { 0, NULL };
  1189.      *     conf->ssl_trusted_certificate = { 0, NULL };
  1190.      *     conf->ssl_crl = { 0, NULL };
  1191.      */

  1192.     conf->modifier1 = NGX_CONF_UNSET_UINT;
  1193.     conf->modifier2 = NGX_CONF_UNSET_UINT;

  1194.     conf->upstream.store = NGX_CONF_UNSET;
  1195.     conf->upstream.store_access = NGX_CONF_UNSET_UINT;
  1196.     conf->upstream.next_upstream_tries = NGX_CONF_UNSET_UINT;
  1197.     conf->upstream.buffering = NGX_CONF_UNSET;
  1198.     conf->upstream.request_buffering = NGX_CONF_UNSET;
  1199.     conf->upstream.ignore_client_abort = NGX_CONF_UNSET;
  1200.     conf->upstream.force_ranges = NGX_CONF_UNSET;

  1201.     conf->upstream.local = NGX_CONF_UNSET_PTR;
  1202.     conf->upstream.socket_keepalive = NGX_CONF_UNSET;

  1203.     conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC;
  1204.     conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC;
  1205.     conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC;
  1206.     conf->upstream.next_upstream_timeout = NGX_CONF_UNSET_MSEC;

  1207.     conf->upstream.send_lowat = NGX_CONF_UNSET_SIZE;
  1208.     conf->upstream.buffer_size = NGX_CONF_UNSET_SIZE;
  1209.     conf->upstream.limit_rate = NGX_CONF_UNSET_PTR;

  1210.     conf->upstream.busy_buffers_size_conf = NGX_CONF_UNSET_SIZE;
  1211.     conf->upstream.max_temp_file_size_conf = NGX_CONF_UNSET_SIZE;
  1212.     conf->upstream.temp_file_write_size_conf = NGX_CONF_UNSET_SIZE;

  1213.     conf->upstream.pass_request_headers = NGX_CONF_UNSET;
  1214.     conf->upstream.pass_request_body = NGX_CONF_UNSET;

  1215. #if (NGX_HTTP_CACHE)
  1216.     conf->upstream.cache = NGX_CONF_UNSET;
  1217.     conf->upstream.cache_min_uses = NGX_CONF_UNSET_UINT;
  1218.     conf->upstream.cache_max_range_offset = NGX_CONF_UNSET;
  1219.     conf->upstream.cache_bypass = NGX_CONF_UNSET_PTR;
  1220.     conf->upstream.no_cache = NGX_CONF_UNSET_PTR;
  1221.     conf->upstream.cache_valid = NGX_CONF_UNSET_PTR;
  1222.     conf->upstream.cache_lock = NGX_CONF_UNSET;
  1223.     conf->upstream.cache_lock_timeout = NGX_CONF_UNSET_MSEC;
  1224.     conf->upstream.cache_lock_age = NGX_CONF_UNSET_MSEC;
  1225.     conf->upstream.cache_revalidate = NGX_CONF_UNSET;
  1226.     conf->upstream.cache_background_update = NGX_CONF_UNSET;
  1227. #endif

  1228.     conf->upstream.hide_headers = NGX_CONF_UNSET_PTR;
  1229.     conf->upstream.pass_headers = NGX_CONF_UNSET_PTR;

  1230.     conf->upstream.intercept_errors = NGX_CONF_UNSET;

  1231. #if (NGX_HTTP_SSL)
  1232.     conf->upstream.ssl_session_reuse = NGX_CONF_UNSET;
  1233.     conf->upstream.ssl_name = NGX_CONF_UNSET_PTR;
  1234.     conf->upstream.ssl_server_name = NGX_CONF_UNSET;
  1235.     conf->upstream.ssl_verify = NGX_CONF_UNSET;
  1236.     conf->ssl_verify_depth = NGX_CONF_UNSET_UINT;
  1237.     conf->upstream.ssl_certificate = NGX_CONF_UNSET_PTR;
  1238.     conf->upstream.ssl_certificate_key = NGX_CONF_UNSET_PTR;
  1239.     conf->upstream.ssl_passwords = NGX_CONF_UNSET_PTR;
  1240.     conf->ssl_conf_commands = NGX_CONF_UNSET_PTR;
  1241. #endif

  1242.     /* "uwsgi_cyclic_temp_file" is disabled */
  1243.     conf->upstream.cyclic_temp_file = 0;

  1244.     conf->upstream.change_buffering = 1;

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

  1246.     return conf;
  1247. }


  1248. static char *
  1249. ngx_http_uwsgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
  1250. {
  1251.     ngx_http_uwsgi_loc_conf_t *prev = parent;
  1252.     ngx_http_uwsgi_loc_conf_t *conf = child;

  1253.     size_t                        size;
  1254.     ngx_int_t                     rc;
  1255.     ngx_hash_init_t               hash;
  1256.     ngx_http_core_loc_conf_t     *clcf;

  1257. #if (NGX_HTTP_CACHE)

  1258.     if (conf->upstream.store > 0) {
  1259.         conf->upstream.cache = 0;
  1260.     }

  1261.     if (conf->upstream.cache > 0) {
  1262.         conf->upstream.store = 0;
  1263.     }

  1264. #endif

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

  1267.         conf->upstream.store_lengths = prev->upstream.store_lengths;
  1268.         conf->upstream.store_values = prev->upstream.store_values;
  1269.     }

  1270.     ngx_conf_merge_uint_value(conf->upstream.store_access,
  1271.                               prev->upstream.store_access, 0600);

  1272.     ngx_conf_merge_uint_value(conf->upstream.next_upstream_tries,
  1273.                               prev->upstream.next_upstream_tries, 0);

  1274.     ngx_conf_merge_value(conf->upstream.buffering,
  1275.                               prev->upstream.buffering, 1);

  1276.     ngx_conf_merge_value(conf->upstream.request_buffering,
  1277.                               prev->upstream.request_buffering, 1);

  1278.     ngx_conf_merge_value(conf->upstream.ignore_client_abort,
  1279.                               prev->upstream.ignore_client_abort, 0);

  1280.     ngx_conf_merge_value(conf->upstream.force_ranges,
  1281.                               prev->upstream.force_ranges, 0);

  1282.     ngx_conf_merge_ptr_value(conf->upstream.local,
  1283.                               prev->upstream.local, NULL);

  1284.     ngx_conf_merge_value(conf->upstream.socket_keepalive,
  1285.                               prev->upstream.socket_keepalive, 0);

  1286.     ngx_conf_merge_msec_value(conf->upstream.connect_timeout,
  1287.                               prev->upstream.connect_timeout, 60000);

  1288.     ngx_conf_merge_msec_value(conf->upstream.send_timeout,
  1289.                               prev->upstream.send_timeout, 60000);

  1290.     ngx_conf_merge_msec_value(conf->upstream.read_timeout,
  1291.                               prev->upstream.read_timeout, 60000);

  1292.     ngx_conf_merge_msec_value(conf->upstream.next_upstream_timeout,
  1293.                               prev->upstream.next_upstream_timeout, 0);

  1294.     ngx_conf_merge_size_value(conf->upstream.send_lowat,
  1295.                               prev->upstream.send_lowat, 0);

  1296.     ngx_conf_merge_size_value(conf->upstream.buffer_size,
  1297.                               prev->upstream.buffer_size,
  1298.                               (size_t) ngx_pagesize);

  1299.     ngx_conf_merge_ptr_value(conf->upstream.limit_rate,
  1300.                               prev->upstream.limit_rate, NULL);


  1301.     ngx_conf_merge_bufs_value(conf->upstream.bufs, prev->upstream.bufs,
  1302.                               8, ngx_pagesize);

  1303.     if (conf->upstream.bufs.num < 2) {
  1304.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  1305.                            "there must be at least 2 \"uwsgi_buffers\"");
  1306.         return NGX_CONF_ERROR;
  1307.     }


  1308.     size = conf->upstream.buffer_size;
  1309.     if (size < conf->upstream.bufs.size) {
  1310.         size = conf->upstream.bufs.size;
  1311.     }


  1312.     ngx_conf_merge_size_value(conf->upstream.busy_buffers_size_conf,
  1313.                               prev->upstream.busy_buffers_size_conf,
  1314.                               NGX_CONF_UNSET_SIZE);

  1315.     if (conf->upstream.busy_buffers_size_conf == NGX_CONF_UNSET_SIZE) {
  1316.         conf->upstream.busy_buffers_size = 2 * size;
  1317.     } else {
  1318.         conf->upstream.busy_buffers_size =
  1319.             conf->upstream.busy_buffers_size_conf;
  1320.     }

  1321.     if (conf->upstream.busy_buffers_size < size) {
  1322.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  1323.             "\"uwsgi_busy_buffers_size\" must be equal to or greater "
  1324.             "than the maximum of the value of \"uwsgi_buffer_size\" and "
  1325.             "one of the \"uwsgi_buffers\"");

  1326.         return NGX_CONF_ERROR;
  1327.     }

  1328.     if (conf->upstream.busy_buffers_size
  1329.         > (conf->upstream.bufs.num - 1) * conf->upstream.bufs.size)
  1330.     {
  1331.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  1332.             "\"uwsgi_busy_buffers_size\" must be less than "
  1333.             "the size of all \"uwsgi_buffers\" minus one buffer");

  1334.         return NGX_CONF_ERROR;
  1335.     }


  1336.     ngx_conf_merge_size_value(conf->upstream.temp_file_write_size_conf,
  1337.                               prev->upstream.temp_file_write_size_conf,
  1338.                               NGX_CONF_UNSET_SIZE);

  1339.     if (conf->upstream.temp_file_write_size_conf == NGX_CONF_UNSET_SIZE) {
  1340.         conf->upstream.temp_file_write_size = 2 * size;
  1341.     } else {
  1342.         conf->upstream.temp_file_write_size =
  1343.             conf->upstream.temp_file_write_size_conf;
  1344.     }

  1345.     if (conf->upstream.temp_file_write_size < size) {
  1346.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  1347.             "\"uwsgi_temp_file_write_size\" must be equal to or greater than "
  1348.             "the maximum of the value of \"uwsgi_buffer_size\" and "
  1349.             "one of the \"uwsgi_buffers\"");

  1350.         return NGX_CONF_ERROR;
  1351.     }


  1352.     ngx_conf_merge_size_value(conf->upstream.max_temp_file_size_conf,
  1353.                               prev->upstream.max_temp_file_size_conf,
  1354.                               NGX_CONF_UNSET_SIZE);

  1355.     if (conf->upstream.max_temp_file_size_conf == NGX_CONF_UNSET_SIZE) {
  1356.         conf->upstream.max_temp_file_size = 1024 * 1024 * 1024;
  1357.     } else {
  1358.         conf->upstream.max_temp_file_size =
  1359.             conf->upstream.max_temp_file_size_conf;
  1360.     }

  1361.     if (conf->upstream.max_temp_file_size != 0
  1362.         && conf->upstream.max_temp_file_size < size)
  1363.     {
  1364.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  1365.             "\"uwsgi_max_temp_file_size\" must be equal to zero to disable "
  1366.             "temporary files usage or must be equal to or greater than "
  1367.             "the maximum of the value of \"uwsgi_buffer_size\" and "
  1368.             "one of the \"uwsgi_buffers\"");

  1369.         return NGX_CONF_ERROR;
  1370.     }


  1371.     ngx_conf_merge_bitmask_value(conf->upstream.ignore_headers,
  1372.                                  prev->upstream.ignore_headers,
  1373.                                  NGX_CONF_BITMASK_SET);


  1374.     ngx_conf_merge_bitmask_value(conf->upstream.next_upstream,
  1375.                                  prev->upstream.next_upstream,
  1376.                                  (NGX_CONF_BITMASK_SET
  1377.                                   |NGX_HTTP_UPSTREAM_FT_ERROR
  1378.                                   |NGX_HTTP_UPSTREAM_FT_TIMEOUT));

  1379.     if (conf->upstream.next_upstream & NGX_HTTP_UPSTREAM_FT_OFF) {
  1380.         conf->upstream.next_upstream = NGX_CONF_BITMASK_SET
  1381.                                        |NGX_HTTP_UPSTREAM_FT_OFF;
  1382.     }

  1383.     if (ngx_conf_merge_path_value(cf, &conf->upstream.temp_path,
  1384.                                   prev->upstream.temp_path,
  1385.                                   &ngx_http_uwsgi_temp_path)
  1386.         != NGX_OK)
  1387.     {
  1388.         return NGX_CONF_ERROR;
  1389.     }

  1390. #if (NGX_HTTP_CACHE)

  1391.     if (conf->upstream.cache == NGX_CONF_UNSET) {
  1392.         ngx_conf_merge_value(conf->upstream.cache,
  1393.                               prev->upstream.cache, 0);

  1394.         conf->upstream.cache_zone = prev->upstream.cache_zone;
  1395.         conf->upstream.cache_value = prev->upstream.cache_value;
  1396.     }

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

  1399.         shm_zone = conf->upstream.cache_zone;

  1400.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  1401.                            "\"uwsgi_cache\" zone \"%V\" is unknown",
  1402.                            &shm_zone->shm.name);

  1403.         return NGX_CONF_ERROR;
  1404.     }

  1405.     ngx_conf_merge_uint_value(conf->upstream.cache_min_uses,
  1406.                               prev->upstream.cache_min_uses, 1);

  1407.     ngx_conf_merge_off_value(conf->upstream.cache_max_range_offset,
  1408.                               prev->upstream.cache_max_range_offset,
  1409.                               NGX_MAX_OFF_T_VALUE);

  1410.     ngx_conf_merge_bitmask_value(conf->upstream.cache_use_stale,
  1411.                               prev->upstream.cache_use_stale,
  1412.                               (NGX_CONF_BITMASK_SET
  1413.                                |NGX_HTTP_UPSTREAM_FT_OFF));

  1414.     if (conf->upstream.cache_use_stale & NGX_HTTP_UPSTREAM_FT_OFF) {
  1415.         conf->upstream.cache_use_stale = NGX_CONF_BITMASK_SET
  1416.                                          |NGX_HTTP_UPSTREAM_FT_OFF;
  1417.     }

  1418.     if (conf->upstream.cache_use_stale & NGX_HTTP_UPSTREAM_FT_ERROR) {
  1419.         conf->upstream.cache_use_stale |= NGX_HTTP_UPSTREAM_FT_NOLIVE;
  1420.     }

  1421.     if (conf->upstream.cache_methods == 0) {
  1422.         conf->upstream.cache_methods = prev->upstream.cache_methods;
  1423.     }

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

  1425.     ngx_conf_merge_ptr_value(conf->upstream.cache_bypass,
  1426.                              prev->upstream.cache_bypass, NULL);

  1427.     ngx_conf_merge_ptr_value(conf->upstream.no_cache,
  1428.                              prev->upstream.no_cache, NULL);

  1429.     ngx_conf_merge_ptr_value(conf->upstream.cache_valid,
  1430.                              prev->upstream.cache_valid, NULL);

  1431.     if (conf->cache_key.value.data == NULL) {
  1432.         conf->cache_key = prev->cache_key;
  1433.     }

  1434.     if (conf->upstream.cache && conf->cache_key.value.data == NULL) {
  1435.         ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
  1436.                            "no \"uwsgi_cache_key\" for \"uwsgi_cache\"");
  1437.     }

  1438.     ngx_conf_merge_value(conf->upstream.cache_lock,
  1439.                               prev->upstream.cache_lock, 0);

  1440.     ngx_conf_merge_msec_value(conf->upstream.cache_lock_timeout,
  1441.                               prev->upstream.cache_lock_timeout, 5000);

  1442.     ngx_conf_merge_msec_value(conf->upstream.cache_lock_age,
  1443.                               prev->upstream.cache_lock_age, 5000);

  1444.     ngx_conf_merge_value(conf->upstream.cache_revalidate,
  1445.                               prev->upstream.cache_revalidate, 0);

  1446.     ngx_conf_merge_value(conf->upstream.cache_background_update,
  1447.                               prev->upstream.cache_background_update, 0);

  1448. #endif

  1449.     ngx_conf_merge_value(conf->upstream.pass_request_headers,
  1450.                          prev->upstream.pass_request_headers, 1);
  1451.     ngx_conf_merge_value(conf->upstream.pass_request_body,
  1452.                          prev->upstream.pass_request_body, 1);

  1453.     ngx_conf_merge_value(conf->upstream.intercept_errors,
  1454.                          prev->upstream.intercept_errors, 0);

  1455. #if (NGX_HTTP_SSL)

  1456.     if (ngx_http_uwsgi_merge_ssl(cf, conf, prev) != NGX_OK) {
  1457.         return NGX_CONF_ERROR;
  1458.     }

  1459.     ngx_conf_merge_value(conf->upstream.ssl_session_reuse,
  1460.                               prev->upstream.ssl_session_reuse, 1);

  1461.     ngx_conf_merge_bitmask_value(conf->ssl_protocols, prev->ssl_protocols,
  1462.                               (NGX_CONF_BITMASK_SET|NGX_SSL_DEFAULT_PROTOCOLS));

  1463.     ngx_conf_merge_str_value(conf->ssl_ciphers, prev->ssl_ciphers,
  1464.                              "DEFAULT");

  1465.     ngx_conf_merge_ptr_value(conf->upstream.ssl_name,
  1466.                               prev->upstream.ssl_name, NULL);
  1467.     ngx_conf_merge_value(conf->upstream.ssl_server_name,
  1468.                               prev->upstream.ssl_server_name, 0);
  1469.     ngx_conf_merge_value(conf->upstream.ssl_verify,
  1470.                               prev->upstream.ssl_verify, 0);
  1471.     ngx_conf_merge_uint_value(conf->ssl_verify_depth,
  1472.                               prev->ssl_verify_depth, 1);
  1473.     ngx_conf_merge_str_value(conf->ssl_trusted_certificate,
  1474.                               prev->ssl_trusted_certificate, "");
  1475.     ngx_conf_merge_str_value(conf->ssl_crl, prev->ssl_crl, "");

  1476.     ngx_conf_merge_ptr_value(conf->upstream.ssl_certificate,
  1477.                               prev->upstream.ssl_certificate, NULL);
  1478.     ngx_conf_merge_ptr_value(conf->upstream.ssl_certificate_key,
  1479.                               prev->upstream.ssl_certificate_key, NULL);
  1480.     ngx_conf_merge_ptr_value(conf->upstream.ssl_passwords,
  1481.                               prev->upstream.ssl_passwords, NULL);

  1482.     ngx_conf_merge_ptr_value(conf->ssl_conf_commands,
  1483.                               prev->ssl_conf_commands, NULL);

  1484.     if (conf->ssl && ngx_http_uwsgi_set_ssl(cf, conf) != NGX_OK) {
  1485.         return NGX_CONF_ERROR;
  1486.     }

  1487. #endif

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

  1489.     hash.max_size = 512;
  1490.     hash.bucket_size = ngx_align(64, ngx_cacheline_size);
  1491.     hash.name = "uwsgi_hide_headers_hash";

  1492.     if (ngx_http_upstream_hide_headers_hash(cf, &conf->upstream,
  1493.             &prev->upstream, ngx_http_uwsgi_hide_headers, &hash)
  1494.         != NGX_OK)
  1495.     {
  1496.         return NGX_CONF_ERROR;
  1497.     }

  1498.     clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);

  1499.     if (clcf->noname
  1500.         && conf->upstream.upstream == NULL && conf->uwsgi_lengths == NULL)
  1501.     {
  1502.         conf->upstream.upstream = prev->upstream.upstream;

  1503.         conf->uwsgi_lengths = prev->uwsgi_lengths;
  1504.         conf->uwsgi_values = prev->uwsgi_values;

  1505. #if (NGX_HTTP_SSL)
  1506.         conf->ssl = prev->ssl;
  1507. #endif
  1508.     }

  1509.     if (clcf->lmt_excpt && clcf->handler == NULL
  1510.         && (conf->upstream.upstream || conf->uwsgi_lengths))
  1511.     {
  1512.         clcf->handler = ngx_http_uwsgi_handler;
  1513.     }

  1514.     ngx_conf_merge_uint_value(conf->modifier1, prev->modifier1, 0);
  1515.     ngx_conf_merge_uint_value(conf->modifier2, prev->modifier2, 0);

  1516.     if (conf->params_source == NULL) {
  1517.         conf->params = prev->params;
  1518. #if (NGX_HTTP_CACHE)
  1519.         conf->params_cache = prev->params_cache;
  1520. #endif
  1521.         conf->params_source = prev->params_source;
  1522.     }

  1523.     rc = ngx_http_uwsgi_init_params(cf, conf, &conf->params, NULL);
  1524.     if (rc != NGX_OK) {
  1525.         return NGX_CONF_ERROR;
  1526.     }

  1527. #if (NGX_HTTP_CACHE)

  1528.     if (conf->upstream.cache) {
  1529.         rc = ngx_http_uwsgi_init_params(cf, conf, &conf->params_cache,
  1530.                                         ngx_http_uwsgi_cache_headers);
  1531.         if (rc != NGX_OK) {
  1532.             return NGX_CONF_ERROR;
  1533.         }
  1534.     }

  1535. #endif

  1536.     /*
  1537.      * special handling to preserve conf->params in the "http" section
  1538.      * to inherit it to all servers
  1539.      */

  1540.     if (prev->params.hash.buckets == NULL
  1541.         && conf->params_source == prev->params_source)
  1542.     {
  1543.         prev->params = conf->params;
  1544. #if (NGX_HTTP_CACHE)
  1545.         prev->params_cache = conf->params_cache;
  1546. #endif
  1547.     }

  1548.     return NGX_CONF_OK;
  1549. }


  1550. static ngx_int_t
  1551. ngx_http_uwsgi_init_params(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *conf,
  1552.     ngx_http_uwsgi_params_t *params, ngx_keyval_t *default_params)
  1553. {
  1554.     u_char                       *p;
  1555.     size_t                        size;
  1556.     uintptr_t                    *code;
  1557.     ngx_uint_t                    i, nsrc;
  1558.     ngx_array_t                   headers_names, params_merged;
  1559.     ngx_keyval_t                 *h;
  1560.     ngx_hash_key_t               *hk;
  1561.     ngx_hash_init_t               hash;
  1562.     ngx_http_upstream_param_t    *src, *s;
  1563.     ngx_http_script_compile_t     sc;
  1564.     ngx_http_script_copy_code_t  *copy;

  1565.     if (params->hash.buckets) {
  1566.         return NGX_OK;
  1567.     }

  1568.     if (conf->params_source == NULL && default_params == NULL) {
  1569.         params->hash.buckets = (void *) 1;
  1570.         return NGX_OK;
  1571.     }

  1572.     params->lengths = ngx_array_create(cf->pool, 64, 1);
  1573.     if (params->lengths == NULL) {
  1574.         return NGX_ERROR;
  1575.     }

  1576.     params->values = ngx_array_create(cf->pool, 512, 1);
  1577.     if (params->values == NULL) {
  1578.         return NGX_ERROR;
  1579.     }

  1580.     if (ngx_array_init(&headers_names, cf->temp_pool, 4, sizeof(ngx_hash_key_t))
  1581.         != NGX_OK)
  1582.     {
  1583.         return NGX_ERROR;
  1584.     }

  1585.     if (conf->params_source) {
  1586.         src = conf->params_source->elts;
  1587.         nsrc = conf->params_source->nelts;

  1588.     } else {
  1589.         src = NULL;
  1590.         nsrc = 0;
  1591.     }

  1592.     if (default_params) {
  1593.         if (ngx_array_init(&params_merged, cf->temp_pool, 4,
  1594.                            sizeof(ngx_http_upstream_param_t))
  1595.             != NGX_OK)
  1596.         {
  1597.             return NGX_ERROR;
  1598.         }

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

  1600.             s = ngx_array_push(&params_merged);
  1601.             if (s == NULL) {
  1602.                 return NGX_ERROR;
  1603.             }

  1604.             *s = src[i];
  1605.         }

  1606.         h = default_params;

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

  1608.             src = params_merged.elts;
  1609.             nsrc = params_merged.nelts;

  1610.             for (i = 0; i < nsrc; i++) {
  1611.                 if (ngx_strcasecmp(h->key.data, src[i].key.data) == 0) {
  1612.                     goto next;
  1613.                 }
  1614.             }

  1615.             s = ngx_array_push(&params_merged);
  1616.             if (s == NULL) {
  1617.                 return NGX_ERROR;
  1618.             }

  1619.             s->key = h->key;
  1620.             s->value = h->value;
  1621.             s->skip_empty = 1;

  1622.         next:

  1623.             h++;
  1624.         }

  1625.         src = params_merged.elts;
  1626.         nsrc = params_merged.nelts;
  1627.     }

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

  1629.         if (src[i].key.len > sizeof("HTTP_") - 1
  1630.             && ngx_strncmp(src[i].key.data, "HTTP_", sizeof("HTTP_") - 1) == 0)
  1631.         {
  1632.             hk = ngx_array_push(&headers_names);
  1633.             if (hk == NULL) {
  1634.                 return NGX_ERROR;
  1635.             }

  1636.             hk->key.len = src[i].key.len - 5;
  1637.             hk->key.data = src[i].key.data + 5;
  1638.             hk->key_hash = ngx_hash_key_lc(hk->key.data, hk->key.len);
  1639.             hk->value = (void *) 1;

  1640.             if (src[i].value.len == 0) {
  1641.                 continue;
  1642.             }
  1643.         }

  1644.         copy = ngx_array_push_n(params->lengths,
  1645.                                 sizeof(ngx_http_script_copy_code_t));
  1646.         if (copy == NULL) {
  1647.             return NGX_ERROR;
  1648.         }

  1649.         copy->code = (ngx_http_script_code_pt) (void *)
  1650.                                                  ngx_http_script_copy_len_code;
  1651.         copy->len = src[i].key.len;

  1652.         copy = ngx_array_push_n(params->lengths,
  1653.                                 sizeof(ngx_http_script_copy_code_t));
  1654.         if (copy == NULL) {
  1655.             return NGX_ERROR;
  1656.         }

  1657.         copy->code = (ngx_http_script_code_pt) (void *)
  1658.                                                  ngx_http_script_copy_len_code;
  1659.         copy->len = src[i].skip_empty;


  1660.         size = (sizeof(ngx_http_script_copy_code_t)
  1661.                 + src[i].key.len + sizeof(uintptr_t) - 1)
  1662.                & ~(sizeof(uintptr_t) - 1);

  1663.         copy = ngx_array_push_n(params->values, size);
  1664.         if (copy == NULL) {
  1665.             return NGX_ERROR;
  1666.         }

  1667.         copy->code = ngx_http_script_copy_code;
  1668.         copy->len = src[i].key.len;

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


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

  1672.         sc.cf = cf;
  1673.         sc.source = &src[i].value;
  1674.         sc.flushes = &params->flushes;
  1675.         sc.lengths = &params->lengths;
  1676.         sc.values = &params->values;

  1677.         if (ngx_http_script_compile(&sc) != NGX_OK) {
  1678.             return NGX_ERROR;
  1679.         }

  1680.         code = ngx_array_push_n(params->lengths, sizeof(uintptr_t));
  1681.         if (code == NULL) {
  1682.             return NGX_ERROR;
  1683.         }

  1684.         *code = (uintptr_t) NULL;


  1685.         code = ngx_array_push_n(params->values, sizeof(uintptr_t));
  1686.         if (code == NULL) {
  1687.             return NGX_ERROR;
  1688.         }

  1689.         *code = (uintptr_t) NULL;
  1690.     }

  1691.     code = ngx_array_push_n(params->lengths, sizeof(uintptr_t));
  1692.     if (code == NULL) {
  1693.         return NGX_ERROR;
  1694.     }

  1695.     *code = (uintptr_t) NULL;

  1696.     params->number = headers_names.nelts;

  1697.     hash.hash = &params->hash;
  1698.     hash.key = ngx_hash_key_lc;
  1699.     hash.max_size = 512;
  1700.     hash.bucket_size = 64;
  1701.     hash.name = "uwsgi_params_hash";
  1702.     hash.pool = cf->pool;
  1703.     hash.temp_pool = NULL;

  1704.     return ngx_hash_init(&hash, headers_names.elts, headers_names.nelts);
  1705. }


  1706. static char *
  1707. ngx_http_uwsgi_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  1708. {
  1709.     ngx_http_uwsgi_loc_conf_t *uwcf = conf;

  1710.     size_t                      add;
  1711.     ngx_url_t                   u;
  1712.     ngx_str_t                  *value, *url;
  1713.     ngx_uint_t                  n;
  1714.     ngx_http_core_loc_conf_t   *clcf;
  1715.     ngx_http_script_compile_t   sc;

  1716.     if (uwcf->upstream.upstream || uwcf->uwsgi_lengths) {
  1717.         return "is duplicate";
  1718.     }

  1719.     clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
  1720.     clcf->handler = ngx_http_uwsgi_handler;

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

  1722.     url = &value[1];

  1723.     n = ngx_http_script_variables_count(url);

  1724.     if (n) {

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

  1726.         sc.cf = cf;
  1727.         sc.source = url;
  1728.         sc.lengths = &uwcf->uwsgi_lengths;
  1729.         sc.values = &uwcf->uwsgi_values;
  1730.         sc.variables = n;
  1731.         sc.complete_lengths = 1;
  1732.         sc.complete_values = 1;

  1733.         if (ngx_http_script_compile(&sc) != NGX_OK) {
  1734.             return NGX_CONF_ERROR;
  1735.         }

  1736. #if (NGX_HTTP_SSL)
  1737.         uwcf->ssl = 1;
  1738. #endif

  1739.         return NGX_CONF_OK;
  1740.     }

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

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

  1744. #if (NGX_HTTP_SSL)
  1745.         add = 9;
  1746.         uwcf->ssl = 1;
  1747. #else
  1748.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  1749.                            "suwsgi protocol requires SSL support");
  1750.         return NGX_CONF_ERROR;
  1751. #endif

  1752.     } else {
  1753.         add = 0;
  1754.     }

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

  1756.     u.url.len = url->len - add;
  1757.     u.url.data = url->data + add;
  1758.     u.no_resolve = 1;

  1759.     uwcf->upstream.upstream = ngx_http_upstream_add(cf, &u, 0);
  1760.     if (uwcf->upstream.upstream == NULL) {
  1761.         return NGX_CONF_ERROR;
  1762.     }

  1763.     if (clcf->name.len && clcf->name.data[clcf->name.len - 1] == '/') {
  1764.         clcf->auto_redirect = 1;
  1765.     }

  1766.     return NGX_CONF_OK;
  1767. }


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

  1772.     ngx_str_t                  *value;
  1773.     ngx_http_script_compile_t   sc;

  1774.     if (uwcf->upstream.store != NGX_CONF_UNSET) {
  1775.         return "is duplicate";
  1776.     }

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

  1778.     if (ngx_strcmp(value[1].data, "off") == 0) {
  1779.         uwcf->upstream.store = 0;
  1780.         return NGX_CONF_OK;
  1781.     }

  1782.     if (value[1].len == 0) {
  1783.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "empty path");
  1784.         return NGX_CONF_ERROR;
  1785.     }

  1786. #if (NGX_HTTP_CACHE)

  1787.     if (uwcf->upstream.cache > 0) {
  1788.         return "is incompatible with \"uwsgi_cache\"";
  1789.     }

  1790. #endif

  1791.     uwcf->upstream.store = 1;

  1792.     if (ngx_strcmp(value[1].data, "on") == 0) {
  1793.         return NGX_CONF_OK;
  1794.     }

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

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

  1798.     sc.cf = cf;
  1799.     sc.source = &value[1];
  1800.     sc.lengths = &uwcf->upstream.store_lengths;
  1801.     sc.values = &uwcf->upstream.store_values;
  1802.     sc.variables = ngx_http_script_variables_count(&value[1]);
  1803.     sc.complete_lengths = 1;
  1804.     sc.complete_values = 1;

  1805.     if (ngx_http_script_compile(&sc) != NGX_OK) {
  1806.         return NGX_CONF_ERROR;
  1807.     }

  1808.     return NGX_CONF_OK;
  1809. }


  1810. #if (NGX_HTTP_CACHE)

  1811. static char *
  1812. ngx_http_uwsgi_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  1813. {
  1814.     ngx_http_uwsgi_loc_conf_t *uwcf = conf;

  1815.     ngx_str_t                         *value;
  1816.     ngx_http_complex_value_t           cv;
  1817.     ngx_http_compile_complex_value_t   ccv;

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

  1819.     if (uwcf->upstream.cache != NGX_CONF_UNSET) {
  1820.         return "is duplicate";
  1821.     }

  1822.     if (ngx_strcmp(value[1].data, "off") == 0) {
  1823.         uwcf->upstream.cache = 0;
  1824.         return NGX_CONF_OK;
  1825.     }

  1826.     if (uwcf->upstream.store > 0) {
  1827.         return "is incompatible with \"uwsgi_store\"";
  1828.     }

  1829.     uwcf->upstream.cache = 1;

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

  1831.     ccv.cf = cf;
  1832.     ccv.value = &value[1];
  1833.     ccv.complex_value = &cv;

  1834.     if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
  1835.         return NGX_CONF_ERROR;
  1836.     }

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

  1838.         uwcf->upstream.cache_value = ngx_palloc(cf->pool,
  1839.                                              sizeof(ngx_http_complex_value_t));
  1840.         if (uwcf->upstream.cache_value == NULL) {
  1841.             return NGX_CONF_ERROR;
  1842.         }

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

  1844.         return NGX_CONF_OK;
  1845.     }

  1846.     uwcf->upstream.cache_zone = ngx_shared_memory_add(cf, &value[1], 0,
  1847.                                                       &ngx_http_uwsgi_module);
  1848.     if (uwcf->upstream.cache_zone == NULL) {
  1849.         return NGX_CONF_ERROR;
  1850.     }

  1851.     return NGX_CONF_OK;
  1852. }


  1853. static char *
  1854. ngx_http_uwsgi_cache_key(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  1855. {
  1856.     ngx_http_uwsgi_loc_conf_t *uwcf = conf;

  1857.     ngx_str_t                         *value;
  1858.     ngx_http_compile_complex_value_t   ccv;

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

  1860.     if (uwcf->cache_key.value.data) {
  1861.         return "is duplicate";
  1862.     }

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

  1864.     ccv.cf = cf;
  1865.     ccv.value = &value[1];
  1866.     ccv.complex_value = &uwcf->cache_key;

  1867.     if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
  1868.         return NGX_CONF_ERROR;
  1869.     }

  1870.     return NGX_CONF_OK;
  1871. }

  1872. #endif


  1873. #if (NGX_HTTP_SSL)

  1874. static char *
  1875. ngx_http_uwsgi_ssl_password_file(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.     if (uwcf->upstream.ssl_passwords != NGX_CONF_UNSET_PTR) {
  1880.         return "is duplicate";
  1881.     }

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

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

  1884.     if (uwcf->upstream.ssl_passwords == NULL) {
  1885.         return NGX_CONF_ERROR;
  1886.     }

  1887.     return NGX_CONF_OK;
  1888. }


  1889. static char *
  1890. ngx_http_uwsgi_ssl_conf_command_check(ngx_conf_t *cf, void *post, void *data)
  1891. {
  1892. #ifndef SSL_CONF_FLAG_FILE
  1893.     return "is not supported on this platform";
  1894. #else
  1895.     return NGX_CONF_OK;
  1896. #endif
  1897. }


  1898. static ngx_int_t
  1899. ngx_http_uwsgi_merge_ssl(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *conf,
  1900.     ngx_http_uwsgi_loc_conf_t *prev)
  1901. {
  1902.     ngx_uint_t  preserve;

  1903.     if (conf->ssl_protocols == 0
  1904.         && conf->ssl_ciphers.data == NULL
  1905.         && conf->upstream.ssl_certificate == NGX_CONF_UNSET_PTR
  1906.         && conf->upstream.ssl_certificate_key == NGX_CONF_UNSET_PTR
  1907.         && conf->upstream.ssl_passwords == NGX_CONF_UNSET_PTR
  1908.         && conf->upstream.ssl_verify == NGX_CONF_UNSET
  1909.         && conf->ssl_verify_depth == NGX_CONF_UNSET_UINT
  1910.         && conf->ssl_trusted_certificate.data == NULL
  1911.         && conf->ssl_crl.data == NULL
  1912.         && conf->upstream.ssl_session_reuse == NGX_CONF_UNSET
  1913.         && conf->ssl_conf_commands == NGX_CONF_UNSET_PTR)
  1914.     {
  1915.         if (prev->upstream.ssl) {
  1916.             conf->upstream.ssl = prev->upstream.ssl;
  1917.             return NGX_OK;
  1918.         }

  1919.         preserve = 1;

  1920.     } else {
  1921.         preserve = 0;
  1922.     }

  1923.     conf->upstream.ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t));
  1924.     if (conf->upstream.ssl == NULL) {
  1925.         return NGX_ERROR;
  1926.     }

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

  1928.     /*
  1929.      * special handling to preserve conf->upstream.ssl
  1930.      * in the "http" section to inherit it to all servers
  1931.      */

  1932.     if (preserve) {
  1933.         prev->upstream.ssl = conf->upstream.ssl;
  1934.     }

  1935.     return NGX_OK;
  1936. }


  1937. static ngx_int_t
  1938. ngx_http_uwsgi_set_ssl(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *uwcf)
  1939. {
  1940.     ngx_pool_cleanup_t  *cln;

  1941.     if (uwcf->upstream.ssl->ctx) {
  1942.         return NGX_OK;
  1943.     }

  1944.     if (ngx_ssl_create(uwcf->upstream.ssl, uwcf->ssl_protocols, NULL)
  1945.         != NGX_OK)
  1946.     {
  1947.         return NGX_ERROR;
  1948.     }

  1949.     cln = ngx_pool_cleanup_add(cf->pool, 0);
  1950.     if (cln == NULL) {
  1951.         ngx_ssl_cleanup_ctx(uwcf->upstream.ssl);
  1952.         return NGX_ERROR;
  1953.     }

  1954.     cln->handler = ngx_ssl_cleanup_ctx;
  1955.     cln->data = uwcf->upstream.ssl;

  1956.     if (ngx_ssl_ciphers(cf, uwcf->upstream.ssl, &uwcf->ssl_ciphers, 0)
  1957.         != NGX_OK)
  1958.     {
  1959.         return NGX_ERROR;
  1960.     }

  1961.     if (uwcf->upstream.ssl_certificate
  1962.         && uwcf->upstream.ssl_certificate->value.len)
  1963.     {
  1964.         if (uwcf->upstream.ssl_certificate_key == NULL) {
  1965.             ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
  1966.                           "no \"uwsgi_ssl_certificate_key\" is defined "
  1967.                           "for certificate \"%V\"",
  1968.                           &uwcf->upstream.ssl_certificate->value);
  1969.             return NGX_ERROR;
  1970.         }

  1971.         if (uwcf->upstream.ssl_certificate->lengths
  1972.             || uwcf->upstream.ssl_certificate_key->lengths)
  1973.         {
  1974.             uwcf->upstream.ssl_passwords =
  1975.                   ngx_ssl_preserve_passwords(cf, uwcf->upstream.ssl_passwords);
  1976.             if (uwcf->upstream.ssl_passwords == NULL) {
  1977.                 return NGX_ERROR;
  1978.             }

  1979.         } else {
  1980.             if (ngx_ssl_certificate(cf, uwcf->upstream.ssl,
  1981.                                     &uwcf->upstream.ssl_certificate->value,
  1982.                                     &uwcf->upstream.ssl_certificate_key->value,
  1983.                                     uwcf->upstream.ssl_passwords)
  1984.                 != NGX_OK)
  1985.             {
  1986.                 return NGX_ERROR;
  1987.             }
  1988.         }
  1989.     }

  1990.     if (uwcf->upstream.ssl_verify) {
  1991.         if (uwcf->ssl_trusted_certificate.len == 0) {
  1992.             ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
  1993.                       "no uwsgi_ssl_trusted_certificate for uwsgi_ssl_verify");
  1994.             return NGX_ERROR;
  1995.         }

  1996.         if (ngx_ssl_trusted_certificate(cf, uwcf->upstream.ssl,
  1997.                                         &uwcf->ssl_trusted_certificate,
  1998.                                         uwcf->ssl_verify_depth)
  1999.             != NGX_OK)
  2000.         {
  2001.             return NGX_ERROR;
  2002.         }

  2003.         if (ngx_ssl_crl(cf, uwcf->upstream.ssl, &uwcf->ssl_crl) != NGX_OK) {
  2004.             return NGX_ERROR;
  2005.         }
  2006.     }

  2007.     if (ngx_ssl_client_session_cache(cf, uwcf->upstream.ssl,
  2008.                                      uwcf->upstream.ssl_session_reuse)
  2009.         != NGX_OK)
  2010.     {
  2011.         return NGX_ERROR;
  2012.     }

  2013.     if (ngx_ssl_conf_commands(cf, uwcf->upstream.ssl, uwcf->ssl_conf_commands)
  2014.         != NGX_OK)
  2015.     {
  2016.         return NGX_ERROR;
  2017.     }

  2018.     return NGX_OK;
  2019. }

  2020. #endif