src/http/ngx_http_core_module.c - nginx

Global variables defined

Data types defined

Functions defined

Macros defined

Source code


  1. /*
  2. * Copyright (C) Igor Sysoev
  3. * Copyright (C) Nginx, Inc.
  4. */


  5. #include <ngx_config.h>
  6. #include <ngx_core.h>
  7. #include <ngx_http.h>


  8. typedef struct {
  9.     u_char    *name;
  10.     uint32_t   method;
  11. } ngx_http_method_name_t;


  12. #define NGX_HTTP_REQUEST_BODY_FILE_OFF    0
  13. #define NGX_HTTP_REQUEST_BODY_FILE_ON     1
  14. #define NGX_HTTP_REQUEST_BODY_FILE_CLEAN  2


  15. static ngx_int_t ngx_http_core_auth_delay(ngx_http_request_t *r);
  16. static void ngx_http_core_auth_delay_handler(ngx_http_request_t *r);

  17. static ngx_int_t ngx_http_core_find_location(ngx_http_request_t *r);
  18. static ngx_int_t ngx_http_core_find_static_location(ngx_http_request_t *r,
  19.     ngx_http_location_tree_node_t *node);

  20. static ngx_int_t ngx_http_core_preconfiguration(ngx_conf_t *cf);
  21. static ngx_int_t ngx_http_core_postconfiguration(ngx_conf_t *cf);
  22. static void *ngx_http_core_create_main_conf(ngx_conf_t *cf);
  23. static char *ngx_http_core_init_main_conf(ngx_conf_t *cf, void *conf);
  24. static void *ngx_http_core_create_srv_conf(ngx_conf_t *cf);
  25. static char *ngx_http_core_merge_srv_conf(ngx_conf_t *cf,
  26.     void *parent, void *child);
  27. static void *ngx_http_core_create_loc_conf(ngx_conf_t *cf);
  28. static char *ngx_http_core_merge_loc_conf(ngx_conf_t *cf,
  29.     void *parent, void *child);

  30. static char *ngx_http_core_server(ngx_conf_t *cf, ngx_command_t *cmd,
  31.     void *dummy);
  32. static char *ngx_http_core_location(ngx_conf_t *cf, ngx_command_t *cmd,
  33.     void *dummy);
  34. static ngx_int_t ngx_http_core_regex_location(ngx_conf_t *cf,
  35.     ngx_http_core_loc_conf_t *clcf, ngx_str_t *regex, ngx_uint_t caseless);

  36. static char *ngx_http_core_types(ngx_conf_t *cf, ngx_command_t *cmd,
  37.     void *conf);
  38. static char *ngx_http_core_type(ngx_conf_t *cf, ngx_command_t *dummy,
  39.     void *conf);

  40. static char *ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd,
  41.     void *conf);
  42. static char *ngx_http_core_server_name(ngx_conf_t *cf, ngx_command_t *cmd,
  43.     void *conf);
  44. static char *ngx_http_core_root(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
  45. static char *ngx_http_core_limit_except(ngx_conf_t *cf, ngx_command_t *cmd,
  46.     void *conf);
  47. static char *ngx_http_core_set_aio(ngx_conf_t *cf, ngx_command_t *cmd,
  48.     void *conf);
  49. static char *ngx_http_core_directio(ngx_conf_t *cf, ngx_command_t *cmd,
  50.     void *conf);
  51. static char *ngx_http_core_error_page(ngx_conf_t *cf, ngx_command_t *cmd,
  52.     void *conf);
  53. static char *ngx_http_core_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd,
  54.     void *conf);
  55. static char *ngx_http_core_error_log(ngx_conf_t *cf, ngx_command_t *cmd,
  56.     void *conf);
  57. static char *ngx_http_core_keepalive(ngx_conf_t *cf, ngx_command_t *cmd,
  58.     void *conf);
  59. static char *ngx_http_core_internal(ngx_conf_t *cf, ngx_command_t *cmd,
  60.     void *conf);
  61. static char *ngx_http_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd,
  62.     void *conf);
  63. #if (NGX_HTTP_GZIP)
  64. static ngx_int_t ngx_http_gzip_accept_encoding(ngx_str_t *ae);
  65. static ngx_uint_t ngx_http_gzip_quantity(u_char *p, u_char *last);
  66. static char *ngx_http_gzip_disable(ngx_conf_t *cf, ngx_command_t *cmd,
  67.     void *conf);
  68. #endif
  69. static ngx_int_t ngx_http_get_forwarded_addr_internal(ngx_http_request_t *r,
  70.     ngx_addr_t *addr, u_char *xff, size_t xfflen, ngx_array_t *proxies,
  71.     int recursive);
  72. #if (NGX_HAVE_OPENAT)
  73. static char *ngx_http_disable_symlinks(ngx_conf_t *cf, ngx_command_t *cmd,
  74.     void *conf);
  75. #endif

  76. static char *ngx_http_core_lowat_check(ngx_conf_t *cf, void *post, void *data);
  77. static char *ngx_http_core_pool_size(ngx_conf_t *cf, void *post, void *data);

  78. static ngx_conf_post_t  ngx_http_core_lowat_post =
  79.     { ngx_http_core_lowat_check };

  80. static ngx_conf_post_handler_pt  ngx_http_core_pool_size_p =
  81.     ngx_http_core_pool_size;


  82. static ngx_conf_enum_t  ngx_http_core_request_body_in_file[] = {
  83.     { ngx_string("off"), NGX_HTTP_REQUEST_BODY_FILE_OFF },
  84.     { ngx_string("on"), NGX_HTTP_REQUEST_BODY_FILE_ON },
  85.     { ngx_string("clean"), NGX_HTTP_REQUEST_BODY_FILE_CLEAN },
  86.     { ngx_null_string, 0 }
  87. };


  88. static ngx_conf_enum_t  ngx_http_core_satisfy[] = {
  89.     { ngx_string("all"), NGX_HTTP_SATISFY_ALL },
  90.     { ngx_string("any"), NGX_HTTP_SATISFY_ANY },
  91.     { ngx_null_string, 0 }
  92. };


  93. static ngx_conf_enum_t  ngx_http_core_lingering_close[] = {
  94.     { ngx_string("off"), NGX_HTTP_LINGERING_OFF },
  95.     { ngx_string("on"), NGX_HTTP_LINGERING_ON },
  96.     { ngx_string("always"), NGX_HTTP_LINGERING_ALWAYS },
  97.     { ngx_null_string, 0 }
  98. };


  99. static ngx_conf_enum_t  ngx_http_core_server_tokens[] = {
  100.     { ngx_string("off"), NGX_HTTP_SERVER_TOKENS_OFF },
  101.     { ngx_string("on"), NGX_HTTP_SERVER_TOKENS_ON },
  102.     { ngx_string("build"), NGX_HTTP_SERVER_TOKENS_BUILD },
  103.     { ngx_null_string, 0 }
  104. };


  105. static ngx_conf_enum_t  ngx_http_core_if_modified_since[] = {
  106.     { ngx_string("off"), NGX_HTTP_IMS_OFF },
  107.     { ngx_string("exact"), NGX_HTTP_IMS_EXACT },
  108.     { ngx_string("before"), NGX_HTTP_IMS_BEFORE },
  109.     { ngx_null_string, 0 }
  110. };


  111. static ngx_conf_bitmask_t  ngx_http_core_keepalive_disable[] = {
  112.     { ngx_string("none"), NGX_HTTP_KEEPALIVE_DISABLE_NONE },
  113.     { ngx_string("msie6"), NGX_HTTP_KEEPALIVE_DISABLE_MSIE6 },
  114.     { ngx_string("safari"), NGX_HTTP_KEEPALIVE_DISABLE_SAFARI },
  115.     { ngx_null_string, 0 }
  116. };


  117. static ngx_path_init_t  ngx_http_client_temp_path = {
  118.     ngx_string(NGX_HTTP_CLIENT_TEMP_PATH), { 0, 0, 0 }
  119. };


  120. #if (NGX_HTTP_GZIP)

  121. static ngx_conf_enum_t  ngx_http_gzip_http_version[] = {
  122.     { ngx_string("1.0"), NGX_HTTP_VERSION_10 },
  123.     { ngx_string("1.1"), NGX_HTTP_VERSION_11 },
  124.     { ngx_null_string, 0 }
  125. };


  126. static ngx_conf_bitmask_t  ngx_http_gzip_proxied_mask[] = {
  127.     { ngx_string("off"), NGX_HTTP_GZIP_PROXIED_OFF },
  128.     { ngx_string("expired"), NGX_HTTP_GZIP_PROXIED_EXPIRED },
  129.     { ngx_string("no-cache"), NGX_HTTP_GZIP_PROXIED_NO_CACHE },
  130.     { ngx_string("no-store"), NGX_HTTP_GZIP_PROXIED_NO_STORE },
  131.     { ngx_string("private"), NGX_HTTP_GZIP_PROXIED_PRIVATE },
  132.     { ngx_string("no_last_modified"), NGX_HTTP_GZIP_PROXIED_NO_LM },
  133.     { ngx_string("no_etag"), NGX_HTTP_GZIP_PROXIED_NO_ETAG },
  134.     { ngx_string("auth"), NGX_HTTP_GZIP_PROXIED_AUTH },
  135.     { ngx_string("any"), NGX_HTTP_GZIP_PROXIED_ANY },
  136.     { ngx_null_string, 0 }
  137. };


  138. static ngx_str_t  ngx_http_gzip_no_cache = ngx_string("no-cache");
  139. static ngx_str_t  ngx_http_gzip_no_store = ngx_string("no-store");
  140. static ngx_str_t  ngx_http_gzip_private = ngx_string("private");

  141. #endif


  142. static ngx_command_t  ngx_http_core_commands[] = {

  143.     { ngx_string("variables_hash_max_size"),
  144.       NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
  145.       ngx_conf_set_num_slot,
  146.       NGX_HTTP_MAIN_CONF_OFFSET,
  147.       offsetof(ngx_http_core_main_conf_t, variables_hash_max_size),
  148.       NULL },

  149.     { ngx_string("variables_hash_bucket_size"),
  150.       NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
  151.       ngx_conf_set_num_slot,
  152.       NGX_HTTP_MAIN_CONF_OFFSET,
  153.       offsetof(ngx_http_core_main_conf_t, variables_hash_bucket_size),
  154.       NULL },

  155.     { ngx_string("server_names_hash_max_size"),
  156.       NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
  157.       ngx_conf_set_num_slot,
  158.       NGX_HTTP_MAIN_CONF_OFFSET,
  159.       offsetof(ngx_http_core_main_conf_t, server_names_hash_max_size),
  160.       NULL },

  161.     { ngx_string("server_names_hash_bucket_size"),
  162.       NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
  163.       ngx_conf_set_num_slot,
  164.       NGX_HTTP_MAIN_CONF_OFFSET,
  165.       offsetof(ngx_http_core_main_conf_t, server_names_hash_bucket_size),
  166.       NULL },

  167.     { ngx_string("server"),
  168.       NGX_HTTP_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
  169.       ngx_http_core_server,
  170.       0,
  171.       0,
  172.       NULL },

  173.     { ngx_string("connection_pool_size"),
  174.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
  175.       ngx_conf_set_size_slot,
  176.       NGX_HTTP_SRV_CONF_OFFSET,
  177.       offsetof(ngx_http_core_srv_conf_t, connection_pool_size),
  178.       &ngx_http_core_pool_size_p },

  179.     { ngx_string("request_pool_size"),
  180.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
  181.       ngx_conf_set_size_slot,
  182.       NGX_HTTP_SRV_CONF_OFFSET,
  183.       offsetof(ngx_http_core_srv_conf_t, request_pool_size),
  184.       &ngx_http_core_pool_size_p },

  185.     { ngx_string("client_header_timeout"),
  186.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
  187.       ngx_conf_set_msec_slot,
  188.       NGX_HTTP_SRV_CONF_OFFSET,
  189.       offsetof(ngx_http_core_srv_conf_t, client_header_timeout),
  190.       NULL },

  191.     { ngx_string("client_header_buffer_size"),
  192.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
  193.       ngx_conf_set_size_slot,
  194.       NGX_HTTP_SRV_CONF_OFFSET,
  195.       offsetof(ngx_http_core_srv_conf_t, client_header_buffer_size),
  196.       NULL },

  197.     { ngx_string("large_client_header_buffers"),
  198.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE2,
  199.       ngx_conf_set_bufs_slot,
  200.       NGX_HTTP_SRV_CONF_OFFSET,
  201.       offsetof(ngx_http_core_srv_conf_t, large_client_header_buffers),
  202.       NULL },

  203.     { ngx_string("max_headers"),
  204.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
  205.       ngx_conf_set_num_slot,
  206.       NGX_HTTP_SRV_CONF_OFFSET,
  207.       offsetof(ngx_http_core_srv_conf_t, max_headers),
  208.       NULL },

  209.     { ngx_string("ignore_invalid_headers"),
  210.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
  211.       ngx_conf_set_flag_slot,
  212.       NGX_HTTP_SRV_CONF_OFFSET,
  213.       offsetof(ngx_http_core_srv_conf_t, ignore_invalid_headers),
  214.       NULL },

  215.     { ngx_string("merge_slashes"),
  216.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
  217.       ngx_conf_set_flag_slot,
  218.       NGX_HTTP_SRV_CONF_OFFSET,
  219.       offsetof(ngx_http_core_srv_conf_t, merge_slashes),
  220.       NULL },

  221.     { ngx_string("underscores_in_headers"),
  222.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
  223.       ngx_conf_set_flag_slot,
  224.       NGX_HTTP_SRV_CONF_OFFSET,
  225.       offsetof(ngx_http_core_srv_conf_t, underscores_in_headers),
  226.       NULL },

  227.     { ngx_string("location"),
  228.       NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_BLOCK|NGX_CONF_TAKE12,
  229.       ngx_http_core_location,
  230.       NGX_HTTP_SRV_CONF_OFFSET,
  231.       0,
  232.       NULL },

  233.     { ngx_string("listen"),
  234.       NGX_HTTP_SRV_CONF|NGX_CONF_1MORE,
  235.       ngx_http_core_listen,
  236.       NGX_HTTP_SRV_CONF_OFFSET,
  237.       0,
  238.       NULL },

  239.     { ngx_string("server_name"),
  240.       NGX_HTTP_SRV_CONF|NGX_CONF_1MORE,
  241.       ngx_http_core_server_name,
  242.       NGX_HTTP_SRV_CONF_OFFSET,
  243.       0,
  244.       NULL },

  245.     { ngx_string("types_hash_max_size"),
  246.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  247.       ngx_conf_set_num_slot,
  248.       NGX_HTTP_LOC_CONF_OFFSET,
  249.       offsetof(ngx_http_core_loc_conf_t, types_hash_max_size),
  250.       NULL },

  251.     { ngx_string("types_hash_bucket_size"),
  252.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  253.       ngx_conf_set_num_slot,
  254.       NGX_HTTP_LOC_CONF_OFFSET,
  255.       offsetof(ngx_http_core_loc_conf_t, types_hash_bucket_size),
  256.       NULL },

  257.     { ngx_string("types"),
  258.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF
  259.                                           |NGX_CONF_BLOCK|NGX_CONF_NOARGS,
  260.       ngx_http_core_types,
  261.       NGX_HTTP_LOC_CONF_OFFSET,
  262.       0,
  263.       NULL },

  264.     { ngx_string("default_type"),
  265.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  266.       ngx_conf_set_str_slot,
  267.       NGX_HTTP_LOC_CONF_OFFSET,
  268.       offsetof(ngx_http_core_loc_conf_t, default_type),
  269.       NULL },

  270.     { ngx_string("root"),
  271.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
  272.                         |NGX_CONF_TAKE1,
  273.       ngx_http_core_root,
  274.       NGX_HTTP_LOC_CONF_OFFSET,
  275.       0,
  276.       NULL },

  277.     { ngx_string("alias"),
  278.       NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  279.       ngx_http_core_root,
  280.       NGX_HTTP_LOC_CONF_OFFSET,
  281.       0,
  282.       NULL },

  283.     { ngx_string("limit_except"),
  284.       NGX_HTTP_LOC_CONF|NGX_CONF_BLOCK|NGX_CONF_1MORE,
  285.       ngx_http_core_limit_except,
  286.       NGX_HTTP_LOC_CONF_OFFSET,
  287.       0,
  288.       NULL },

  289.     { ngx_string("client_max_body_size"),
  290.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  291.       ngx_conf_set_off_slot,
  292.       NGX_HTTP_LOC_CONF_OFFSET,
  293.       offsetof(ngx_http_core_loc_conf_t, client_max_body_size),
  294.       NULL },

  295.     { ngx_string("client_body_buffer_size"),
  296.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  297.       ngx_conf_set_size_slot,
  298.       NGX_HTTP_LOC_CONF_OFFSET,
  299.       offsetof(ngx_http_core_loc_conf_t, client_body_buffer_size),
  300.       NULL },

  301.     { ngx_string("client_body_timeout"),
  302.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  303.       ngx_conf_set_msec_slot,
  304.       NGX_HTTP_LOC_CONF_OFFSET,
  305.       offsetof(ngx_http_core_loc_conf_t, client_body_timeout),
  306.       NULL },

  307.     { ngx_string("client_body_temp_path"),
  308.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1234,
  309.       ngx_conf_set_path_slot,
  310.       NGX_HTTP_LOC_CONF_OFFSET,
  311.       offsetof(ngx_http_core_loc_conf_t, client_body_temp_path),
  312.       NULL },

  313.     { ngx_string("client_body_in_file_only"),
  314.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  315.       ngx_conf_set_enum_slot,
  316.       NGX_HTTP_LOC_CONF_OFFSET,
  317.       offsetof(ngx_http_core_loc_conf_t, client_body_in_file_only),
  318.       &ngx_http_core_request_body_in_file },

  319.     { ngx_string("client_body_in_single_buffer"),
  320.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
  321.       ngx_conf_set_flag_slot,
  322.       NGX_HTTP_LOC_CONF_OFFSET,
  323.       offsetof(ngx_http_core_loc_conf_t, client_body_in_single_buffer),
  324.       NULL },

  325.     { ngx_string("sendfile"),
  326.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
  327.                         |NGX_CONF_FLAG,
  328.       ngx_conf_set_flag_slot,
  329.       NGX_HTTP_LOC_CONF_OFFSET,
  330.       offsetof(ngx_http_core_loc_conf_t, sendfile),
  331.       NULL },

  332.     { ngx_string("sendfile_max_chunk"),
  333.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  334.       ngx_conf_set_size_slot,
  335.       NGX_HTTP_LOC_CONF_OFFSET,
  336.       offsetof(ngx_http_core_loc_conf_t, sendfile_max_chunk),
  337.       NULL },

  338.     { ngx_string("subrequest_output_buffer_size"),
  339.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  340.       ngx_conf_set_size_slot,
  341.       NGX_HTTP_LOC_CONF_OFFSET,
  342.       offsetof(ngx_http_core_loc_conf_t, subrequest_output_buffer_size),
  343.       NULL },

  344.     { ngx_string("aio"),
  345.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  346.       ngx_http_core_set_aio,
  347.       NGX_HTTP_LOC_CONF_OFFSET,
  348.       0,
  349.       NULL },

  350.     { ngx_string("aio_write"),
  351.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
  352.       ngx_conf_set_flag_slot,
  353.       NGX_HTTP_LOC_CONF_OFFSET,
  354.       offsetof(ngx_http_core_loc_conf_t, aio_write),
  355.       NULL },

  356.     { ngx_string("read_ahead"),
  357.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  358.       ngx_conf_set_size_slot,
  359.       NGX_HTTP_LOC_CONF_OFFSET,
  360.       offsetof(ngx_http_core_loc_conf_t, read_ahead),
  361.       NULL },

  362.     { ngx_string("directio"),
  363.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  364.       ngx_http_core_directio,
  365.       NGX_HTTP_LOC_CONF_OFFSET,
  366.       0,
  367.       NULL },

  368.     { ngx_string("directio_alignment"),
  369.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  370.       ngx_conf_set_off_slot,
  371.       NGX_HTTP_LOC_CONF_OFFSET,
  372.       offsetof(ngx_http_core_loc_conf_t, directio_alignment),
  373.       NULL },

  374.     { ngx_string("tcp_nopush"),
  375.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
  376.       ngx_conf_set_flag_slot,
  377.       NGX_HTTP_LOC_CONF_OFFSET,
  378.       offsetof(ngx_http_core_loc_conf_t, tcp_nopush),
  379.       NULL },

  380.     { ngx_string("tcp_nodelay"),
  381.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
  382.       ngx_conf_set_flag_slot,
  383.       NGX_HTTP_LOC_CONF_OFFSET,
  384.       offsetof(ngx_http_core_loc_conf_t, tcp_nodelay),
  385.       NULL },

  386.     { ngx_string("send_timeout"),
  387.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  388.       ngx_conf_set_msec_slot,
  389.       NGX_HTTP_LOC_CONF_OFFSET,
  390.       offsetof(ngx_http_core_loc_conf_t, send_timeout),
  391.       NULL },

  392.     { ngx_string("send_lowat"),
  393.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  394.       ngx_conf_set_size_slot,
  395.       NGX_HTTP_LOC_CONF_OFFSET,
  396.       offsetof(ngx_http_core_loc_conf_t, send_lowat),
  397.       &ngx_http_core_lowat_post },

  398.     { ngx_string("postpone_output"),
  399.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  400.       ngx_conf_set_size_slot,
  401.       NGX_HTTP_LOC_CONF_OFFSET,
  402.       offsetof(ngx_http_core_loc_conf_t, postpone_output),
  403.       NULL },

  404.     { ngx_string("limit_rate"),
  405.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
  406.                         |NGX_CONF_TAKE1,
  407.       ngx_http_set_complex_value_size_slot,
  408.       NGX_HTTP_LOC_CONF_OFFSET,
  409.       offsetof(ngx_http_core_loc_conf_t, limit_rate),
  410.       NULL },

  411.     { ngx_string("limit_rate_after"),
  412.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
  413.                         |NGX_CONF_TAKE1,
  414.       ngx_http_set_complex_value_size_slot,
  415.       NGX_HTTP_LOC_CONF_OFFSET,
  416.       offsetof(ngx_http_core_loc_conf_t, limit_rate_after),
  417.       NULL },

  418.     { ngx_string("keepalive_time"),
  419.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  420.       ngx_conf_set_msec_slot,
  421.       NGX_HTTP_LOC_CONF_OFFSET,
  422.       offsetof(ngx_http_core_loc_conf_t, keepalive_time),
  423.       NULL },

  424.     { ngx_string("keepalive_timeout"),
  425.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12,
  426.       ngx_http_core_keepalive,
  427.       NGX_HTTP_LOC_CONF_OFFSET,
  428.       0,
  429.       NULL },

  430.     { ngx_string("keepalive_min_timeout"),
  431.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  432.       ngx_conf_set_msec_slot,
  433.       NGX_HTTP_LOC_CONF_OFFSET,
  434.       offsetof(ngx_http_core_loc_conf_t, keepalive_min_timeout),
  435.       NULL },

  436.     { ngx_string("keepalive_requests"),
  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_core_loc_conf_t, keepalive_requests),
  441.       NULL },

  442.     { ngx_string("keepalive_disable"),
  443.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12,
  444.       ngx_conf_set_bitmask_slot,
  445.       NGX_HTTP_LOC_CONF_OFFSET,
  446.       offsetof(ngx_http_core_loc_conf_t, keepalive_disable),
  447.       &ngx_http_core_keepalive_disable },

  448.     { ngx_string("satisfy"),
  449.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  450.       ngx_conf_set_enum_slot,
  451.       NGX_HTTP_LOC_CONF_OFFSET,
  452.       offsetof(ngx_http_core_loc_conf_t, satisfy),
  453.       &ngx_http_core_satisfy },

  454.     { ngx_string("auth_delay"),
  455.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  456.       ngx_conf_set_msec_slot,
  457.       NGX_HTTP_LOC_CONF_OFFSET,
  458.       offsetof(ngx_http_core_loc_conf_t, auth_delay),
  459.       NULL },

  460.     { ngx_string("internal"),
  461.       NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,
  462.       ngx_http_core_internal,
  463.       NGX_HTTP_LOC_CONF_OFFSET,
  464.       0,
  465.       NULL },

  466.     { ngx_string("lingering_close"),
  467.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  468.       ngx_conf_set_enum_slot,
  469.       NGX_HTTP_LOC_CONF_OFFSET,
  470.       offsetof(ngx_http_core_loc_conf_t, lingering_close),
  471.       &ngx_http_core_lingering_close },

  472.     { ngx_string("lingering_time"),
  473.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  474.       ngx_conf_set_msec_slot,
  475.       NGX_HTTP_LOC_CONF_OFFSET,
  476.       offsetof(ngx_http_core_loc_conf_t, lingering_time),
  477.       NULL },

  478.     { ngx_string("lingering_timeout"),
  479.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  480.       ngx_conf_set_msec_slot,
  481.       NGX_HTTP_LOC_CONF_OFFSET,
  482.       offsetof(ngx_http_core_loc_conf_t, lingering_timeout),
  483.       NULL },

  484.     { ngx_string("reset_timedout_connection"),
  485.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
  486.       ngx_conf_set_flag_slot,
  487.       NGX_HTTP_LOC_CONF_OFFSET,
  488.       offsetof(ngx_http_core_loc_conf_t, reset_timedout_connection),
  489.       NULL },

  490.     { ngx_string("absolute_redirect"),
  491.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
  492.       ngx_conf_set_flag_slot,
  493.       NGX_HTTP_LOC_CONF_OFFSET,
  494.       offsetof(ngx_http_core_loc_conf_t, absolute_redirect),
  495.       NULL },

  496.     { ngx_string("server_name_in_redirect"),
  497.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
  498.       ngx_conf_set_flag_slot,
  499.       NGX_HTTP_LOC_CONF_OFFSET,
  500.       offsetof(ngx_http_core_loc_conf_t, server_name_in_redirect),
  501.       NULL },

  502.     { ngx_string("port_in_redirect"),
  503.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
  504.       ngx_conf_set_flag_slot,
  505.       NGX_HTTP_LOC_CONF_OFFSET,
  506.       offsetof(ngx_http_core_loc_conf_t, port_in_redirect),
  507.       NULL },

  508.     { ngx_string("msie_padding"),
  509.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
  510.       ngx_conf_set_flag_slot,
  511.       NGX_HTTP_LOC_CONF_OFFSET,
  512.       offsetof(ngx_http_core_loc_conf_t, msie_padding),
  513.       NULL },

  514.     { ngx_string("msie_refresh"),
  515.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
  516.       ngx_conf_set_flag_slot,
  517.       NGX_HTTP_LOC_CONF_OFFSET,
  518.       offsetof(ngx_http_core_loc_conf_t, msie_refresh),
  519.       NULL },

  520.     { ngx_string("log_not_found"),
  521.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
  522.       ngx_conf_set_flag_slot,
  523.       NGX_HTTP_LOC_CONF_OFFSET,
  524.       offsetof(ngx_http_core_loc_conf_t, log_not_found),
  525.       NULL },

  526.     { ngx_string("log_subrequest"),
  527.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
  528.       ngx_conf_set_flag_slot,
  529.       NGX_HTTP_LOC_CONF_OFFSET,
  530.       offsetof(ngx_http_core_loc_conf_t, log_subrequest),
  531.       NULL },

  532.     { ngx_string("recursive_error_pages"),
  533.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
  534.       ngx_conf_set_flag_slot,
  535.       NGX_HTTP_LOC_CONF_OFFSET,
  536.       offsetof(ngx_http_core_loc_conf_t, recursive_error_pages),
  537.       NULL },

  538.     { ngx_string("server_tokens"),
  539.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  540.       ngx_conf_set_enum_slot,
  541.       NGX_HTTP_LOC_CONF_OFFSET,
  542.       offsetof(ngx_http_core_loc_conf_t, server_tokens),
  543.       &ngx_http_core_server_tokens },

  544.     { ngx_string("if_modified_since"),
  545.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  546.       ngx_conf_set_enum_slot,
  547.       NGX_HTTP_LOC_CONF_OFFSET,
  548.       offsetof(ngx_http_core_loc_conf_t, if_modified_since),
  549.       &ngx_http_core_if_modified_since },

  550.     { ngx_string("max_ranges"),
  551.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  552.       ngx_conf_set_num_slot,
  553.       NGX_HTTP_LOC_CONF_OFFSET,
  554.       offsetof(ngx_http_core_loc_conf_t, max_ranges),
  555.       NULL },

  556.     { ngx_string("chunked_transfer_encoding"),
  557.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
  558.       ngx_conf_set_flag_slot,
  559.       NGX_HTTP_LOC_CONF_OFFSET,
  560.       offsetof(ngx_http_core_loc_conf_t, chunked_transfer_encoding),
  561.       NULL },

  562.     { ngx_string("etag"),
  563.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
  564.       ngx_conf_set_flag_slot,
  565.       NGX_HTTP_LOC_CONF_OFFSET,
  566.       offsetof(ngx_http_core_loc_conf_t, etag),
  567.       NULL },

  568.     { ngx_string("early_hints"),
  569.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
  570.       ngx_http_set_predicate_slot,
  571.       NGX_HTTP_LOC_CONF_OFFSET,
  572.       offsetof(ngx_http_core_loc_conf_t, early_hints),
  573.       NULL },

  574.     { ngx_string("error_page"),
  575.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
  576.                         |NGX_CONF_2MORE,
  577.       ngx_http_core_error_page,
  578.       NGX_HTTP_LOC_CONF_OFFSET,
  579.       0,
  580.       NULL },

  581.     { ngx_string("post_action"),
  582.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
  583.                         |NGX_CONF_TAKE1,
  584.       ngx_conf_set_str_slot,
  585.       NGX_HTTP_LOC_CONF_OFFSET,
  586.       offsetof(ngx_http_core_loc_conf_t, post_action),
  587.       NULL },

  588.     { ngx_string("error_log"),
  589.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
  590.       ngx_http_core_error_log,
  591.       NGX_HTTP_LOC_CONF_OFFSET,
  592.       0,
  593.       NULL },

  594.     { ngx_string("open_file_cache"),
  595.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12,
  596.       ngx_http_core_open_file_cache,
  597.       NGX_HTTP_LOC_CONF_OFFSET,
  598.       offsetof(ngx_http_core_loc_conf_t, open_file_cache),
  599.       NULL },

  600.     { ngx_string("open_file_cache_valid"),
  601.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  602.       ngx_conf_set_sec_slot,
  603.       NGX_HTTP_LOC_CONF_OFFSET,
  604.       offsetof(ngx_http_core_loc_conf_t, open_file_cache_valid),
  605.       NULL },

  606.     { ngx_string("open_file_cache_min_uses"),
  607.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  608.       ngx_conf_set_num_slot,
  609.       NGX_HTTP_LOC_CONF_OFFSET,
  610.       offsetof(ngx_http_core_loc_conf_t, open_file_cache_min_uses),
  611.       NULL },

  612.     { ngx_string("open_file_cache_errors"),
  613.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
  614.       ngx_conf_set_flag_slot,
  615.       NGX_HTTP_LOC_CONF_OFFSET,
  616.       offsetof(ngx_http_core_loc_conf_t, open_file_cache_errors),
  617.       NULL },

  618.     { ngx_string("open_file_cache_events"),
  619.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
  620.       ngx_conf_set_flag_slot,
  621.       NGX_HTTP_LOC_CONF_OFFSET,
  622.       offsetof(ngx_http_core_loc_conf_t, open_file_cache_events),
  623.       NULL },

  624.     { ngx_string("resolver"),
  625.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
  626.       ngx_http_core_resolver,
  627.       NGX_HTTP_LOC_CONF_OFFSET,
  628.       0,
  629.       NULL },

  630.     { ngx_string("resolver_timeout"),
  631.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  632.       ngx_conf_set_msec_slot,
  633.       NGX_HTTP_LOC_CONF_OFFSET,
  634.       offsetof(ngx_http_core_loc_conf_t, resolver_timeout),
  635.       NULL },

  636. #if (NGX_HTTP_GZIP)

  637.     { ngx_string("gzip_vary"),
  638.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
  639.       ngx_conf_set_flag_slot,
  640.       NGX_HTTP_LOC_CONF_OFFSET,
  641.       offsetof(ngx_http_core_loc_conf_t, gzip_vary),
  642.       NULL },

  643.     { ngx_string("gzip_http_version"),
  644.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  645.       ngx_conf_set_enum_slot,
  646.       NGX_HTTP_LOC_CONF_OFFSET,
  647.       offsetof(ngx_http_core_loc_conf_t, gzip_http_version),
  648.       &ngx_http_gzip_http_version },

  649.     { ngx_string("gzip_proxied"),
  650.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
  651.       ngx_conf_set_bitmask_slot,
  652.       NGX_HTTP_LOC_CONF_OFFSET,
  653.       offsetof(ngx_http_core_loc_conf_t, gzip_proxied),
  654.       &ngx_http_gzip_proxied_mask },

  655.     { ngx_string("gzip_disable"),
  656.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
  657.       ngx_http_gzip_disable,
  658.       NGX_HTTP_LOC_CONF_OFFSET,
  659.       0,
  660.       NULL },

  661. #endif

  662. #if (NGX_HAVE_OPENAT)

  663.     { ngx_string("disable_symlinks"),
  664.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12,
  665.       ngx_http_disable_symlinks,
  666.       NGX_HTTP_LOC_CONF_OFFSET,
  667.       0,
  668.       NULL },

  669. #endif

  670.       ngx_null_command
  671. };


  672. static ngx_http_module_t  ngx_http_core_module_ctx = {
  673.     ngx_http_core_preconfiguration,        /* preconfiguration */
  674.     ngx_http_core_postconfiguration,       /* postconfiguration */

  675.     ngx_http_core_create_main_conf,        /* create main configuration */
  676.     ngx_http_core_init_main_conf,          /* init main configuration */

  677.     ngx_http_core_create_srv_conf,         /* create server configuration */
  678.     ngx_http_core_merge_srv_conf,          /* merge server configuration */

  679.     ngx_http_core_create_loc_conf,         /* create location configuration */
  680.     ngx_http_core_merge_loc_conf           /* merge location configuration */
  681. };


  682. ngx_module_t  ngx_http_core_module = {
  683.     NGX_MODULE_V1,
  684.     &ngx_http_core_module_ctx,             /* module context */
  685.     ngx_http_core_commands,                /* module directives */
  686.     NGX_HTTP_MODULE,                       /* module type */
  687.     NULL,                                  /* init master */
  688.     NULL,                                  /* init module */
  689.     NULL,                                  /* init process */
  690.     NULL,                                  /* init thread */
  691.     NULL,                                  /* exit thread */
  692.     NULL,                                  /* exit process */
  693.     NULL,                                  /* exit master */
  694.     NGX_MODULE_V1_PADDING
  695. };


  696. ngx_str_t  ngx_http_core_get_method = { 3, (u_char *) "GET" };


  697. void
  698. ngx_http_handler(ngx_http_request_t *r)
  699. {
  700.     ngx_http_core_main_conf_t  *cmcf;

  701.     r->connection->log->action = NULL;

  702.     if (!r->internal) {
  703.         switch (r->headers_in.connection_type) {
  704.         case 0:
  705.             r->keepalive = (r->http_version > NGX_HTTP_VERSION_10);
  706.             break;

  707.         case NGX_HTTP_CONNECTION_CLOSE:
  708.             r->keepalive = 0;
  709.             break;

  710.         case NGX_HTTP_CONNECTION_KEEP_ALIVE:
  711.             r->keepalive = 1;
  712.             break;
  713.         }

  714.         r->lingering_close = (r->headers_in.content_length_n > 0
  715.                               || r->headers_in.chunked);
  716.         r->phase_handler = 0;

  717.     } else {
  718.         cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
  719.         r->phase_handler = cmcf->phase_engine.server_rewrite_index;
  720.     }

  721.     r->valid_location = 1;
  722. #if (NGX_HTTP_GZIP)
  723.     r->gzip_tested = 0;
  724.     r->gzip_ok = 0;
  725.     r->gzip_vary = 0;
  726. #endif

  727.     r->write_event_handler = ngx_http_core_run_phases;
  728.     ngx_http_core_run_phases(r);
  729. }


  730. void
  731. ngx_http_core_run_phases(ngx_http_request_t *r)
  732. {
  733.     ngx_int_t                   rc;
  734.     ngx_http_phase_handler_t   *ph;
  735.     ngx_http_core_main_conf_t  *cmcf;

  736.     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);

  737.     ph = cmcf->phase_engine.handlers;

  738.     while (ph[r->phase_handler].checker) {

  739.         rc = ph[r->phase_handler].checker(r, &ph[r->phase_handler]);

  740.         if (rc == NGX_OK) {
  741.             return;
  742.         }
  743.     }
  744. }


  745. ngx_int_t
  746. ngx_http_core_generic_phase(ngx_http_request_t *r, ngx_http_phase_handler_t *ph)
  747. {
  748.     ngx_int_t  rc;

  749.     /*
  750.      * generic phase checker,
  751.      * used by the post read and pre-access phases
  752.      */

  753.     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  754.                    "generic phase: %ui", r->phase_handler);

  755.     rc = ph->handler(r);

  756.     if (rc == NGX_OK) {
  757.         r->phase_handler = ph->next;
  758.         return NGX_AGAIN;
  759.     }

  760.     if (rc == NGX_DECLINED) {
  761.         r->phase_handler++;
  762.         return NGX_AGAIN;
  763.     }

  764.     if (rc == NGX_AGAIN || rc == NGX_DONE) {
  765.         return NGX_OK;
  766.     }

  767.     /* rc == NGX_ERROR || rc == NGX_HTTP_...  */

  768.     ngx_http_finalize_request(r, rc);

  769.     return NGX_OK;
  770. }


  771. ngx_int_t
  772. ngx_http_core_rewrite_phase(ngx_http_request_t *r, ngx_http_phase_handler_t *ph)
  773. {
  774.     ngx_int_t  rc;

  775.     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  776.                    "rewrite phase: %ui", r->phase_handler);

  777.     rc = ph->handler(r);

  778.     if (rc == NGX_DECLINED) {
  779.         r->phase_handler++;
  780.         return NGX_AGAIN;
  781.     }

  782.     if (rc == NGX_DONE) {
  783.         return NGX_OK;
  784.     }

  785.     /* NGX_OK, NGX_AGAIN, NGX_ERROR, NGX_HTTP_...  */

  786.     ngx_http_finalize_request(r, rc);

  787.     return NGX_OK;
  788. }


  789. ngx_int_t
  790. ngx_http_core_find_config_phase(ngx_http_request_t *r,
  791.     ngx_http_phase_handler_t *ph)
  792. {
  793.     u_char                    *p;
  794.     size_t                     len;
  795.     ngx_int_t                  rc;
  796.     ngx_http_core_loc_conf_t  *clcf;

  797.     r->content_handler = NULL;
  798.     r->uri_changed = 0;

  799.     rc = ngx_http_core_find_location(r);

  800.     if (rc == NGX_ERROR) {
  801.         ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
  802.         return NGX_OK;
  803.     }

  804.     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

  805.     if (!r->internal && clcf->internal) {
  806.         ngx_http_finalize_request(r, NGX_HTTP_NOT_FOUND);
  807.         return NGX_OK;
  808.     }

  809.     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  810.                    "using configuration \"%s%V\"",
  811.                    (clcf->noname ? "*" : (clcf->exact_match ? "=" : "")),
  812.                    &clcf->name);

  813.     ngx_http_update_location_config(r);

  814.     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  815.                    "http cl:%O max:%O",
  816.                    r->headers_in.content_length_n, clcf->client_max_body_size);

  817.     if (r->headers_in.content_length_n != -1
  818.         && !r->discard_body
  819.         && clcf->client_max_body_size
  820.         && clcf->client_max_body_size < r->headers_in.content_length_n)
  821.     {
  822.         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  823.                       "client intended to send too large body: %O bytes",
  824.                       r->headers_in.content_length_n);

  825.         r->expect_tested = 1;
  826.         (void) ngx_http_discard_request_body(r);
  827.         ngx_http_finalize_request(r, NGX_HTTP_REQUEST_ENTITY_TOO_LARGE);
  828.         return NGX_OK;
  829.     }

  830.     if (rc == NGX_DONE) {
  831.         ngx_http_clear_location(r);

  832.         r->headers_out.location = ngx_list_push(&r->headers_out.headers);
  833.         if (r->headers_out.location == NULL) {
  834.             ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
  835.             return NGX_OK;
  836.         }

  837.         r->headers_out.location->hash = 1;
  838.         r->headers_out.location->next = NULL;
  839.         ngx_str_set(&r->headers_out.location->key, "Location");

  840.         if (r->args.len == 0) {
  841.             r->headers_out.location->value = clcf->escaped_name;

  842.         } else {
  843.             len = clcf->escaped_name.len + 1 + r->args.len;
  844.             p = ngx_pnalloc(r->pool, len);

  845.             if (p == NULL) {
  846.                 ngx_http_clear_location(r);
  847.                 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
  848.                 return NGX_OK;
  849.             }

  850.             r->headers_out.location->value.len = len;
  851.             r->headers_out.location->value.data = p;

  852.             p = ngx_cpymem(p, clcf->escaped_name.data, clcf->escaped_name.len);
  853.             *p++ = '?';
  854.             ngx_memcpy(p, r->args.data, r->args.len);
  855.         }

  856.         ngx_http_finalize_request(r, NGX_HTTP_MOVED_PERMANENTLY);
  857.         return NGX_OK;
  858.     }

  859.     r->phase_handler++;
  860.     return NGX_AGAIN;
  861. }


  862. ngx_int_t
  863. ngx_http_core_post_rewrite_phase(ngx_http_request_t *r,
  864.     ngx_http_phase_handler_t *ph)
  865. {
  866.     ngx_http_core_srv_conf_t  *cscf;

  867.     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  868.                    "post rewrite phase: %ui", r->phase_handler);

  869.     if (!r->uri_changed) {
  870.         r->phase_handler++;
  871.         return NGX_AGAIN;
  872.     }

  873.     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  874.                    "uri changes: %d", r->uri_changes);

  875.     /*
  876.      * gcc before 3.3 compiles the broken code for
  877.      *     if (r->uri_changes-- == 0)
  878.      * if the r->uri_changes is defined as
  879.      *     unsigned  uri_changes:4
  880.      */

  881.     r->uri_changes--;

  882.     if (r->uri_changes == 0) {
  883.         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  884.                       "rewrite or internal redirection cycle "
  885.                       "while processing \"%V\"", &r->uri);

  886.         ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
  887.         return NGX_OK;
  888.     }

  889.     r->phase_handler = ph->next;

  890.     cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
  891.     r->loc_conf = cscf->ctx->loc_conf;

  892.     return NGX_AGAIN;
  893. }


  894. ngx_int_t
  895. ngx_http_core_access_phase(ngx_http_request_t *r, ngx_http_phase_handler_t *ph)
  896. {
  897.     ngx_int_t                  rc;
  898.     ngx_table_elt_t           *h;
  899.     ngx_http_core_loc_conf_t  *clcf;

  900.     if (r != r->main) {
  901.         r->phase_handler = ph->next;
  902.         return NGX_AGAIN;
  903.     }

  904.     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  905.                    "access phase: %ui", r->phase_handler);

  906.     rc = ph->handler(r);

  907.     if (rc == NGX_DECLINED) {
  908.         r->phase_handler++;
  909.         return NGX_AGAIN;
  910.     }

  911.     if (rc == NGX_AGAIN || rc == NGX_DONE) {
  912.         return NGX_OK;
  913.     }

  914.     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

  915.     if (clcf->satisfy == NGX_HTTP_SATISFY_ALL) {

  916.         if (rc == NGX_OK) {
  917.             r->phase_handler++;
  918.             return NGX_AGAIN;
  919.         }

  920.     } else {
  921.         if (rc == NGX_OK) {
  922.             r->access_code = 0;

  923.             h = ngx_http_proxy_auth(r) ? r->headers_out.proxy_authenticate
  924.                                        : r->headers_out.www_authenticate;

  925.             for ( /* void */ ; h; h = h->next) {
  926.                 h->hash = 0;
  927.             }

  928.             r->phase_handler = ph->next;
  929.             return NGX_AGAIN;
  930.         }

  931.         if (rc == NGX_HTTP_FORBIDDEN
  932.             || rc == NGX_HTTP_UNAUTHORIZED
  933.             || rc == NGX_HTTP_PROXY_AUTH_REQUIRED)
  934.         {
  935.             if (r->access_code != NGX_HTTP_UNAUTHORIZED
  936.                 && r->access_code != NGX_HTTP_PROXY_AUTH_REQUIRED)
  937.             {
  938.                 r->access_code = rc;
  939.             }

  940.             r->phase_handler++;
  941.             return NGX_AGAIN;
  942.         }
  943.     }

  944.     /* rc == NGX_ERROR || rc == NGX_HTTP_...  */

  945.     if (rc == NGX_HTTP_UNAUTHORIZED || rc == NGX_HTTP_PROXY_AUTH_REQUIRED) {
  946.         r->access_code = rc;
  947.         return ngx_http_core_auth_delay(r);
  948.     }

  949.     ngx_http_finalize_request(r, rc);
  950.     return NGX_OK;
  951. }


  952. ngx_int_t
  953. ngx_http_core_post_access_phase(ngx_http_request_t *r,
  954.     ngx_http_phase_handler_t *ph)
  955. {
  956.     ngx_int_t  access_code;

  957.     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  958.                    "post access phase: %ui", r->phase_handler);

  959.     access_code = r->access_code;

  960.     if (access_code) {
  961.         if (access_code == NGX_HTTP_FORBIDDEN) {
  962.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  963.                           "access forbidden by rule");
  964.         }

  965.         if (access_code == NGX_HTTP_UNAUTHORIZED
  966.             || access_code == NGX_HTTP_PROXY_AUTH_REQUIRED)
  967.         {
  968.             return ngx_http_core_auth_delay(r);
  969.         }

  970.         r->access_code = 0;

  971.         ngx_http_finalize_request(r, access_code);
  972.         return NGX_OK;
  973.     }

  974.     r->phase_handler++;
  975.     return NGX_AGAIN;
  976. }


  977. static ngx_int_t
  978. ngx_http_core_auth_delay(ngx_http_request_t *r)
  979. {
  980.     ngx_int_t                  access_code;
  981.     ngx_http_core_loc_conf_t  *clcf;

  982.     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

  983.     if (clcf->auth_delay == 0) {
  984.         access_code = r->access_code;
  985.         r->access_code = 0;

  986.         ngx_http_finalize_request(r, access_code);
  987.         return NGX_OK;
  988.     }

  989.     ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
  990.                   "delaying unauthorized request");

  991.     if (r->connection->read->ready) {
  992.         ngx_post_event(r->connection->read, &ngx_posted_events);

  993.     } else {
  994.         if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) {
  995.             return NGX_HTTP_INTERNAL_SERVER_ERROR;
  996.         }
  997.     }

  998.     r->read_event_handler = ngx_http_test_reading;
  999.     r->write_event_handler = ngx_http_core_auth_delay_handler;

  1000.     r->connection->write->delayed = 1;
  1001.     ngx_add_timer(r->connection->write, clcf->auth_delay);

  1002.     /*
  1003.      * trigger an additional event loop iteration
  1004.      * to ensure constant-time processing
  1005.      */

  1006.     ngx_post_event(r->connection->write, &ngx_posted_next_events);

  1007.     return NGX_OK;
  1008. }


  1009. static void
  1010. ngx_http_core_auth_delay_handler(ngx_http_request_t *r)
  1011. {
  1012.     ngx_int_t     access_code;
  1013.     ngx_event_t  *wev;

  1014.     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  1015.                    "auth delay handler");

  1016.     wev = r->connection->write;

  1017.     if (wev->delayed) {

  1018.         if (ngx_handle_write_event(wev, 0) != NGX_OK) {
  1019.             ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
  1020.         }

  1021.         return;
  1022.     }

  1023.     access_code = r->access_code;
  1024.     r->access_code = 0;

  1025.     ngx_http_finalize_request(r, access_code);
  1026. }


  1027. ngx_int_t
  1028. ngx_http_core_content_phase(ngx_http_request_t *r,
  1029.     ngx_http_phase_handler_t *ph)
  1030. {
  1031.     size_t     root;
  1032.     ngx_int_t  rc;
  1033.     ngx_str_t  path;

  1034.     if (r->content_handler) {
  1035.         r->write_event_handler = ngx_http_request_empty_handler;
  1036.         ngx_http_finalize_request(r, r->content_handler(r));
  1037.         return NGX_OK;
  1038.     }

  1039.     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  1040.                    "content phase: %ui", r->phase_handler);

  1041.     rc = ph->handler(r);

  1042.     if (rc != NGX_DECLINED) {
  1043.         ngx_http_finalize_request(r, rc);
  1044.         return NGX_OK;
  1045.     }

  1046.     /* rc == NGX_DECLINED */

  1047.     ph++;

  1048.     if (ph->checker) {
  1049.         r->phase_handler++;
  1050.         return NGX_AGAIN;
  1051.     }

  1052.     /* no content handler was found */

  1053.     if (r->uri.data[r->uri.len - 1] == '/') {

  1054.         if (ngx_http_map_uri_to_path(r, &path, &root, 0) != NULL) {
  1055.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1056.                           "directory index of \"%s\" is forbidden", path.data);
  1057.         }

  1058.         ngx_http_finalize_request(r, NGX_HTTP_FORBIDDEN);
  1059.         return NGX_OK;
  1060.     }

  1061.     ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "no handler found");

  1062.     ngx_http_finalize_request(r, NGX_HTTP_NOT_FOUND);
  1063.     return NGX_OK;
  1064. }


  1065. void
  1066. ngx_http_update_location_config(ngx_http_request_t *r)
  1067. {
  1068.     ngx_http_core_loc_conf_t  *clcf;

  1069.     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

  1070.     if (r->method & clcf->limit_except) {
  1071.         r->loc_conf = clcf->limit_except_loc_conf;
  1072.         clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
  1073.     }

  1074.     if (r == r->main) {
  1075.         ngx_set_connection_log(r->connection, clcf->error_log);
  1076.     }

  1077.     if ((ngx_io.flags & NGX_IO_SENDFILE) && clcf->sendfile) {
  1078.         r->connection->sendfile = 1;

  1079.     } else {
  1080.         r->connection->sendfile = 0;
  1081.     }

  1082.     if (clcf->client_body_in_file_only) {
  1083.         r->request_body_in_file_only = 1;
  1084.         r->request_body_in_persistent_file = 1;
  1085.         r->request_body_in_clean_file =
  1086.             clcf->client_body_in_file_only == NGX_HTTP_REQUEST_BODY_FILE_CLEAN;
  1087.         r->request_body_file_log_level = NGX_LOG_NOTICE;

  1088.     } else {
  1089.         r->request_body_file_log_level = NGX_LOG_WARN;
  1090.     }

  1091.     r->request_body_in_single_buf = clcf->client_body_in_single_buffer;

  1092.     if (r->keepalive) {
  1093.         if (clcf->keepalive_timeout == 0) {
  1094.             r->keepalive = 0;

  1095.         } else if (r->connection->requests >= clcf->keepalive_requests) {
  1096.             r->keepalive = 0;

  1097.         } else if (ngx_current_msec - r->connection->start_time
  1098.                    > clcf->keepalive_time)
  1099.         {
  1100.             r->keepalive = 0;

  1101.         } else if (r->headers_in.msie6
  1102.                    && r->method == NGX_HTTP_POST
  1103.                    && (clcf->keepalive_disable
  1104.                        & NGX_HTTP_KEEPALIVE_DISABLE_MSIE6))
  1105.         {
  1106.             /*
  1107.              * MSIE may wait for some time if an response for
  1108.              * a POST request was sent over a keepalive connection
  1109.              */
  1110.             r->keepalive = 0;

  1111.         } else if (r->headers_in.safari
  1112.                    && (clcf->keepalive_disable
  1113.                        & NGX_HTTP_KEEPALIVE_DISABLE_SAFARI))
  1114.         {
  1115.             /*
  1116.              * Safari may send a POST request to a closed keepalive
  1117.              * connection and may stall for some time, see
  1118.              *     https://bugs.webkit.org/show_bug.cgi?id=5760
  1119.              */
  1120.             r->keepalive = 0;
  1121.         }
  1122.     }

  1123.     if (!clcf->tcp_nopush) {
  1124.         /* disable TCP_NOPUSH/TCP_CORK use */
  1125.         r->connection->tcp_nopush = NGX_TCP_NOPUSH_DISABLED;
  1126.     }

  1127.     if (clcf->handler) {
  1128.         r->content_handler = clcf->handler;
  1129.     }
  1130. }


  1131. /*
  1132. * NGX_OK       - exact or regex match
  1133. * NGX_DONE     - auto redirect
  1134. * NGX_AGAIN    - inclusive match
  1135. * NGX_ERROR    - regex error
  1136. * NGX_DECLINED - no match
  1137. */

  1138. static ngx_int_t
  1139. ngx_http_core_find_location(ngx_http_request_t *r)
  1140. {
  1141.     ngx_int_t                  rc;
  1142.     ngx_http_core_loc_conf_t  *pclcf;
  1143. #if (NGX_PCRE)
  1144.     ngx_int_t                  n;
  1145.     ngx_uint_t                 noregex;
  1146.     ngx_http_core_loc_conf_t  *clcf, **clcfp;

  1147.     noregex = 0;
  1148. #endif

  1149.     pclcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

  1150.     rc = ngx_http_core_find_static_location(r, pclcf->static_locations);

  1151.     if (rc == NGX_AGAIN) {

  1152. #if (NGX_PCRE)
  1153.         clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

  1154.         noregex = clcf->noregex;
  1155. #endif

  1156.         /* look up nested locations */

  1157.         rc = ngx_http_core_find_location(r);
  1158.     }

  1159.     if (rc == NGX_OK || rc == NGX_DONE) {
  1160.         return rc;
  1161.     }

  1162.     /* rc == NGX_DECLINED or rc == NGX_AGAIN in nested location */

  1163. #if (NGX_PCRE)

  1164.     if (noregex == 0 && pclcf->regex_locations) {

  1165.         for (clcfp = pclcf->regex_locations; *clcfp; clcfp++) {

  1166.             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  1167.                            "test location: ~ \"%V\"", &(*clcfp)->name);

  1168.             n = ngx_http_regex_exec(r, (*clcfp)->regex, &r->uri);

  1169.             if (n == NGX_OK) {
  1170.                 r->loc_conf = (*clcfp)->loc_conf;

  1171.                 /* look up nested locations */

  1172.                 rc = ngx_http_core_find_location(r);

  1173.                 return (rc == NGX_ERROR) ? rc : NGX_OK;
  1174.             }

  1175.             if (n == NGX_DECLINED) {
  1176.                 continue;
  1177.             }

  1178.             return NGX_ERROR;
  1179.         }
  1180.     }
  1181. #endif

  1182.     return rc;
  1183. }


  1184. /*
  1185. * NGX_OK       - exact match
  1186. * NGX_DONE     - auto redirect
  1187. * NGX_AGAIN    - inclusive match
  1188. * NGX_DECLINED - no match
  1189. */

  1190. static ngx_int_t
  1191. ngx_http_core_find_static_location(ngx_http_request_t *r,
  1192.     ngx_http_location_tree_node_t *node)
  1193. {
  1194.     u_char     *uri;
  1195.     size_t      len, n;
  1196.     ngx_int_t   rc, rv;

  1197.     len = r->uri.len;
  1198.     uri = r->uri.data;

  1199.     rv = NGX_DECLINED;

  1200.     for ( ;; ) {

  1201.         if (node == NULL) {
  1202.             return rv;
  1203.         }

  1204.         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  1205.                        "test location: \"%*s\"",
  1206.                        (size_t) node->len, node->name);

  1207.         n = (len <= (size_t) node->len) ? len : node->len;

  1208.         rc = ngx_filename_cmp(uri, node->name, n);

  1209.         if (rc != 0) {
  1210.             node = (rc < 0) ? node->left : node->right;

  1211.             continue;
  1212.         }

  1213.         if (len > (size_t) node->len) {

  1214.             if (node->inclusive) {

  1215.                 r->loc_conf = node->inclusive->loc_conf;
  1216.                 rv = NGX_AGAIN;

  1217.                 node = node->tree;
  1218.                 uri += n;
  1219.                 len -= n;

  1220.                 continue;
  1221.             }

  1222.             /* exact only */

  1223.             node = node->right;

  1224.             continue;
  1225.         }

  1226.         if (len == (size_t) node->len) {

  1227.             if (node->exact) {
  1228.                 r->loc_conf = node->exact->loc_conf;
  1229.                 return NGX_OK;

  1230.             } else {
  1231.                 r->loc_conf = node->inclusive->loc_conf;
  1232.                 return NGX_AGAIN;
  1233.             }
  1234.         }

  1235.         /* len < node->len */

  1236.         if (len + 1 == (size_t) node->len && node->auto_redirect) {

  1237.             r->loc_conf = (node->exact) ? node->exact->loc_conf:
  1238.                                           node->inclusive->loc_conf;
  1239.             rv = NGX_DONE;
  1240.         }

  1241.         node = node->left;
  1242.     }
  1243. }


  1244. void *
  1245. ngx_http_test_content_type(ngx_http_request_t *r, ngx_hash_t *types_hash)
  1246. {
  1247.     u_char      c, *lowcase;
  1248.     size_t      len;
  1249.     ngx_uint_t  i, hash;

  1250.     if (types_hash->size == 0) {
  1251.         return (void *) 4;
  1252.     }

  1253.     if (r->headers_out.content_type.len == 0) {
  1254.         return NULL;
  1255.     }

  1256.     len = r->headers_out.content_type_len;

  1257.     if (r->headers_out.content_type_lowcase == NULL) {

  1258.         lowcase = ngx_pnalloc(r->pool, len);
  1259.         if (lowcase == NULL) {
  1260.             return NULL;
  1261.         }

  1262.         r->headers_out.content_type_lowcase = lowcase;

  1263.         hash = 0;

  1264.         for (i = 0; i < len; i++) {
  1265.             c = ngx_tolower(r->headers_out.content_type.data[i]);
  1266.             hash = ngx_hash(hash, c);
  1267.             lowcase[i] = c;
  1268.         }

  1269.         r->headers_out.content_type_hash = hash;
  1270.     }

  1271.     return ngx_hash_find(types_hash, r->headers_out.content_type_hash,
  1272.                          r->headers_out.content_type_lowcase, len);
  1273. }


  1274. ngx_int_t
  1275. ngx_http_set_content_type(ngx_http_request_t *r)
  1276. {
  1277.     u_char                     c, *exten;
  1278.     ngx_str_t                 *type;
  1279.     ngx_uint_t                 i, hash;
  1280.     ngx_http_core_loc_conf_t  *clcf;

  1281.     if (r->headers_out.content_type.len) {
  1282.         return NGX_OK;
  1283.     }

  1284.     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

  1285.     if (r->exten.len) {

  1286.         hash = 0;

  1287.         for (i = 0; i < r->exten.len; i++) {
  1288.             c = r->exten.data[i];

  1289.             if (c >= 'A' && c <= 'Z') {

  1290.                 exten = ngx_pnalloc(r->pool, r->exten.len);
  1291.                 if (exten == NULL) {
  1292.                     return NGX_ERROR;
  1293.                 }

  1294.                 hash = ngx_hash_strlow(exten, r->exten.data, r->exten.len);

  1295.                 r->exten.data = exten;

  1296.                 break;
  1297.             }

  1298.             hash = ngx_hash(hash, c);
  1299.         }

  1300.         type = ngx_hash_find(&clcf->types_hash, hash,
  1301.                              r->exten.data, r->exten.len);

  1302.         if (type) {
  1303.             r->headers_out.content_type_len = type->len;
  1304.             r->headers_out.content_type = *type;

  1305.             return NGX_OK;
  1306.         }
  1307.     }

  1308.     r->headers_out.content_type_len = clcf->default_type.len;
  1309.     r->headers_out.content_type = clcf->default_type;

  1310.     return NGX_OK;
  1311. }


  1312. void
  1313. ngx_http_set_exten(ngx_http_request_t *r)
  1314. {
  1315.     ngx_int_t  i;

  1316.     ngx_str_null(&r->exten);

  1317.     for (i = r->uri.len - 1; i > 1; i--) {
  1318.         if (r->uri.data[i] == '.' && r->uri.data[i - 1] != '/') {

  1319.             r->exten.len = r->uri.len - i - 1;
  1320.             r->exten.data = &r->uri.data[i + 1];

  1321.             return;

  1322.         } else if (r->uri.data[i] == '/') {
  1323.             return;
  1324.         }
  1325.     }

  1326.     return;
  1327. }


  1328. ngx_int_t
  1329. ngx_http_set_etag(ngx_http_request_t *r)
  1330. {
  1331.     ngx_table_elt_t           *etag;
  1332.     ngx_http_core_loc_conf_t  *clcf;

  1333.     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

  1334.     if (!clcf->etag) {
  1335.         return NGX_OK;
  1336.     }

  1337.     etag = ngx_list_push(&r->headers_out.headers);
  1338.     if (etag == NULL) {
  1339.         return NGX_ERROR;
  1340.     }

  1341.     etag->hash = 1;
  1342.     etag->next = NULL;
  1343.     ngx_str_set(&etag->key, "ETag");

  1344.     etag->value.data = ngx_pnalloc(r->pool, NGX_OFF_T_LEN + NGX_TIME_T_LEN + 3);
  1345.     if (etag->value.data == NULL) {
  1346.         etag->hash = 0;
  1347.         return NGX_ERROR;
  1348.     }

  1349.     etag->value.len = ngx_sprintf(etag->value.data, "\"%xT-%xO\"",
  1350.                                   r->headers_out.last_modified_time,
  1351.                                   r->headers_out.content_length_n)
  1352.                       - etag->value.data;

  1353.     r->headers_out.etag = etag;

  1354.     return NGX_OK;
  1355. }


  1356. void
  1357. ngx_http_weak_etag(ngx_http_request_t *r)
  1358. {
  1359.     size_t            len;
  1360.     u_char           *p;
  1361.     ngx_table_elt_t  *etag;

  1362.     etag = r->headers_out.etag;

  1363.     if (etag == NULL) {
  1364.         return;
  1365.     }

  1366.     if (etag->value.len > 2
  1367.         && etag->value.data[0] == 'W'
  1368.         && etag->value.data[1] == '/')
  1369.     {
  1370.         return;
  1371.     }

  1372.     if (etag->value.len < 1 || etag->value.data[0] != '"') {
  1373.         r->headers_out.etag->hash = 0;
  1374.         r->headers_out.etag = NULL;
  1375.         return;
  1376.     }

  1377.     p = ngx_pnalloc(r->pool, etag->value.len + 2);
  1378.     if (p == NULL) {
  1379.         r->headers_out.etag->hash = 0;
  1380.         r->headers_out.etag = NULL;
  1381.         return;
  1382.     }

  1383.     len = ngx_sprintf(p, "W/%V", &etag->value) - p;

  1384.     etag->value.data = p;
  1385.     etag->value.len = len;
  1386. }


  1387. ngx_int_t
  1388. ngx_http_send_response(ngx_http_request_t *r, ngx_uint_t status,
  1389.     ngx_str_t *ct, ngx_http_complex_value_t *cv)
  1390. {
  1391.     ngx_int_t     rc;
  1392.     ngx_str_t     val;
  1393.     ngx_buf_t    *b;
  1394.     ngx_chain_t   out;

  1395.     rc = ngx_http_discard_request_body(r);

  1396.     if (rc != NGX_OK) {
  1397.         return rc;
  1398.     }

  1399.     r->headers_out.status = status;

  1400.     if (ngx_http_complex_value(r, cv, &val) != NGX_OK) {
  1401.         return NGX_HTTP_INTERNAL_SERVER_ERROR;
  1402.     }

  1403.     if (status == NGX_HTTP_MOVED_PERMANENTLY
  1404.         || status == NGX_HTTP_MOVED_TEMPORARILY
  1405.         || status == NGX_HTTP_SEE_OTHER
  1406.         || status == NGX_HTTP_TEMPORARY_REDIRECT
  1407.         || status == NGX_HTTP_PERMANENT_REDIRECT)
  1408.     {
  1409.         ngx_http_clear_location(r);

  1410.         r->headers_out.location = ngx_list_push(&r->headers_out.headers);
  1411.         if (r->headers_out.location == NULL) {
  1412.             return NGX_HTTP_INTERNAL_SERVER_ERROR;
  1413.         }

  1414.         r->headers_out.location->hash = 1;
  1415.         r->headers_out.location->next = NULL;
  1416.         ngx_str_set(&r->headers_out.location->key, "Location");
  1417.         r->headers_out.location->value = val;

  1418.         return status;
  1419.     }

  1420.     r->headers_out.content_length_n = val.len;

  1421.     if (ct) {
  1422.         r->headers_out.content_type_len = ct->len;
  1423.         r->headers_out.content_type = *ct;

  1424.     } else {
  1425.         if (ngx_http_set_content_type(r) != NGX_OK) {
  1426.             return NGX_HTTP_INTERNAL_SERVER_ERROR;
  1427.         }
  1428.     }

  1429.     b = ngx_calloc_buf(r->pool);
  1430.     if (b == NULL) {
  1431.         return NGX_HTTP_INTERNAL_SERVER_ERROR;
  1432.     }

  1433.     b->pos = val.data;
  1434.     b->last = val.data + val.len;
  1435.     b->memory = val.len ? 1 : 0;
  1436.     b->last_buf = (r == r->main) ? 1 : 0;
  1437.     b->last_in_chain = 1;
  1438.     b->sync = (b->last_buf || b->memory) ? 0 : 1;

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

  1441.     rc = ngx_http_send_header(r);

  1442.     if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
  1443.         return rc;
  1444.     }

  1445.     return ngx_http_output_filter(r, &out);
  1446. }


  1447. ngx_int_t
  1448. ngx_http_send_header(ngx_http_request_t *r)
  1449. {
  1450.     if (r->post_action) {
  1451.         return NGX_OK;
  1452.     }

  1453.     if (r->header_sent) {
  1454.         ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
  1455.                       "header already sent");
  1456.         return NGX_ERROR;
  1457.     }

  1458.     if (r->err_status) {
  1459.         r->headers_out.status = r->err_status;
  1460.         r->headers_out.status_line.len = 0;
  1461.     }

  1462.     return ngx_http_top_header_filter(r);
  1463. }


  1464. ngx_int_t
  1465. ngx_http_send_early_hints(ngx_http_request_t *r)
  1466. {
  1467.     ngx_int_t                  rc;
  1468.     ngx_http_core_loc_conf_t  *clcf;

  1469.     if (r->post_action) {
  1470.         return NGX_OK;
  1471.     }

  1472.     if (r->header_sent) {
  1473.         ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
  1474.                       "header already sent");
  1475.         return NGX_ERROR;
  1476.     }

  1477.     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

  1478.     rc = ngx_http_test_predicates(r, clcf->early_hints);

  1479.     if (rc != NGX_DECLINED) {
  1480.         return rc;
  1481.     }

  1482.     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  1483.                    "http send early hints \"%V?%V\"", &r->uri, &r->args);

  1484.     return ngx_http_top_early_hints_filter(r);
  1485. }


  1486. ngx_int_t
  1487. ngx_http_output_filter(ngx_http_request_t *r, ngx_chain_t *in)
  1488. {
  1489.     ngx_int_t          rc;
  1490.     ngx_connection_t  *c;

  1491.     c = r->connection;

  1492.     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
  1493.                    "http output filter \"%V?%V\"", &r->uri, &r->args);

  1494.     rc = ngx_http_top_body_filter(r, in);

  1495.     if (rc == NGX_ERROR) {
  1496.         /* NGX_ERROR may be returned by any filter */
  1497.         c->error = 1;
  1498.     }

  1499.     return rc;
  1500. }


  1501. u_char *
  1502. ngx_http_map_uri_to_path(ngx_http_request_t *r, ngx_str_t *path,
  1503.     size_t *root_length, size_t reserved)
  1504. {
  1505.     u_char                    *last;
  1506.     size_t                     alias;
  1507.     ngx_http_core_loc_conf_t  *clcf;

  1508.     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

  1509.     alias = clcf->alias;

  1510.     if (alias && !r->valid_location) {
  1511.         ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
  1512.                       "\"alias\" cannot be used in location \"%V\" "
  1513.                       "where URI was rewritten", &clcf->name);
  1514.         return NULL;
  1515.     }

  1516.     if (clcf->root_lengths == NULL) {

  1517.         *root_length = clcf->root.len;

  1518.         path->len = clcf->root.len + reserved + r->uri.len - alias + 1;

  1519.         path->data = ngx_pnalloc(r->pool, path->len);
  1520.         if (path->data == NULL) {
  1521.             return NULL;
  1522.         }

  1523.         last = ngx_copy(path->data, clcf->root.data, clcf->root.len);

  1524.     } else {

  1525.         if (alias == NGX_MAX_SIZE_T_VALUE) {
  1526.             reserved += r->add_uri_to_alias ? r->uri.len + 1 : 1;

  1527.         } else {
  1528.             reserved += r->uri.len - alias + 1;
  1529.         }

  1530.         if (ngx_http_script_run(r, path, clcf->root_lengths->elts, reserved,
  1531.                                 clcf->root_values->elts)
  1532.             == NULL)
  1533.         {
  1534.             return NULL;
  1535.         }

  1536.         if (ngx_get_full_name(r->pool, (ngx_str_t *) &ngx_cycle->prefix, path)
  1537.             != NGX_OK)
  1538.         {
  1539.             return NULL;
  1540.         }

  1541.         *root_length = path->len - reserved;
  1542.         last = path->data + *root_length;

  1543.         if (alias == NGX_MAX_SIZE_T_VALUE) {
  1544.             if (!r->add_uri_to_alias) {
  1545.                 *last = '\0';
  1546.                 return last;
  1547.             }

  1548.             alias = 0;
  1549.         }
  1550.     }

  1551.     last = ngx_copy(last, r->uri.data + alias, r->uri.len - alias);
  1552.     *last = '\0';

  1553.     return last;
  1554. }


  1555. ngx_int_t
  1556. ngx_http_auth_basic_user(ngx_http_request_t *r)
  1557. {
  1558.     ngx_str_t         auth, encoded;
  1559.     ngx_uint_t        len;
  1560.     ngx_table_elt_t  *h;

  1561.     if (r->headers_in.user.len == 0 && r->headers_in.user.data != NULL) {
  1562.         return NGX_DECLINED;
  1563.     }

  1564.     h = ngx_http_proxy_auth(r) ? r->headers_in.proxy_authorization
  1565.                                : r->headers_in.authorization;

  1566.     if (h == NULL) {
  1567.         r->headers_in.user.data = (u_char *) "";
  1568.         return NGX_DECLINED;
  1569.     }

  1570.     encoded = h->value;

  1571.     if (encoded.len < sizeof("Basic ") - 1
  1572.         || ngx_strncasecmp(encoded.data, (u_char *) "Basic ",
  1573.                            sizeof("Basic ") - 1)
  1574.            != 0)
  1575.     {
  1576.         r->headers_in.user.data = (u_char *) "";
  1577.         return NGX_DECLINED;
  1578.     }

  1579.     encoded.len -= sizeof("Basic ") - 1;
  1580.     encoded.data += sizeof("Basic ") - 1;

  1581.     while (encoded.len && encoded.data[0] == ' ') {
  1582.         encoded.len--;
  1583.         encoded.data++;
  1584.     }

  1585.     if (encoded.len == 0) {
  1586.         r->headers_in.user.data = (u_char *) "";
  1587.         return NGX_DECLINED;
  1588.     }

  1589.     auth.len = ngx_base64_decoded_length(encoded.len);
  1590.     auth.data = ngx_pnalloc(r->pool, auth.len + 1);
  1591.     if (auth.data == NULL) {
  1592.         return NGX_ERROR;
  1593.     }

  1594.     if (ngx_decode_base64(&auth, &encoded) != NGX_OK) {
  1595.         r->headers_in.user.data = (u_char *) "";
  1596.         return NGX_DECLINED;
  1597.     }

  1598.     auth.data[auth.len] = '\0';

  1599.     for (len = 0; len < auth.len; len++) {
  1600.         if (auth.data[len] == ':') {
  1601.             break;
  1602.         }
  1603.     }

  1604.     if (len == 0 || len == auth.len) {
  1605.         r->headers_in.user.data = (u_char *) "";
  1606.         return NGX_DECLINED;
  1607.     }

  1608.     r->headers_in.user.len = len;
  1609.     r->headers_in.user.data = auth.data;
  1610.     r->headers_in.passwd.len = auth.len - len - 1;
  1611.     r->headers_in.passwd.data = &auth.data[len + 1];

  1612.     return NGX_OK;
  1613. }


  1614. #if (NGX_HTTP_GZIP)

  1615. ngx_int_t
  1616. ngx_http_gzip_ok(ngx_http_request_t *r)
  1617. {
  1618.     time_t                     date, expires;
  1619.     ngx_uint_t                 p;
  1620.     ngx_table_elt_t           *e, *d, *ae, *cc;
  1621.     ngx_http_core_loc_conf_t  *clcf;

  1622.     r->gzip_tested = 1;

  1623.     if (r != r->main) {
  1624.         return NGX_DECLINED;
  1625.     }

  1626.     ae = r->headers_in.accept_encoding;
  1627.     if (ae == NULL) {
  1628.         return NGX_DECLINED;
  1629.     }

  1630.     if (ae->value.len < sizeof("gzip") - 1) {
  1631.         return NGX_DECLINED;
  1632.     }

  1633.     /*
  1634.      * test first for the most common case "gzip,...":
  1635.      *   MSIE:    "gzip, deflate"
  1636.      *   Firefox: "gzip,deflate"
  1637.      *   Chrome:  "gzip,deflate,sdch"
  1638.      *   Safari:  "gzip, deflate"
  1639.      *   Opera:   "gzip, deflate"
  1640.      */

  1641.     if (ngx_memcmp(ae->value.data, "gzip,", 5) != 0
  1642.         && ngx_http_gzip_accept_encoding(&ae->value) != NGX_OK)
  1643.     {
  1644.         return NGX_DECLINED;
  1645.     }

  1646.     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

  1647.     if (r->headers_in.msie6 && clcf->gzip_disable_msie6) {
  1648.         return NGX_DECLINED;
  1649.     }

  1650.     if (r->http_version < clcf->gzip_http_version) {
  1651.         return NGX_DECLINED;
  1652.     }

  1653.     if (r->headers_in.via == NULL) {
  1654.         goto ok;
  1655.     }

  1656.     p = clcf->gzip_proxied;

  1657.     if (p & NGX_HTTP_GZIP_PROXIED_OFF) {
  1658.         return NGX_DECLINED;
  1659.     }

  1660.     if (p & NGX_HTTP_GZIP_PROXIED_ANY) {
  1661.         goto ok;
  1662.     }

  1663.     if (r->headers_in.authorization && (p & NGX_HTTP_GZIP_PROXIED_AUTH)) {
  1664.         goto ok;
  1665.     }

  1666.     e = r->headers_out.expires;

  1667.     if (e) {

  1668.         if (!(p & NGX_HTTP_GZIP_PROXIED_EXPIRED)) {
  1669.             return NGX_DECLINED;
  1670.         }

  1671.         expires = ngx_parse_http_time(e->value.data, e->value.len);
  1672.         if (expires == NGX_ERROR) {
  1673.             return NGX_DECLINED;
  1674.         }

  1675.         d = r->headers_out.date;

  1676.         if (d) {
  1677.             date = ngx_parse_http_time(d->value.data, d->value.len);
  1678.             if (date == NGX_ERROR) {
  1679.                 return NGX_DECLINED;
  1680.             }

  1681.         } else {
  1682.             date = ngx_time();
  1683.         }

  1684.         if (expires < date) {
  1685.             goto ok;
  1686.         }

  1687.         return NGX_DECLINED;
  1688.     }

  1689.     cc = r->headers_out.cache_control;

  1690.     if (cc) {

  1691.         if ((p & NGX_HTTP_GZIP_PROXIED_NO_CACHE)
  1692.             && ngx_http_parse_multi_header_lines(r, cc, &ngx_http_gzip_no_cache,
  1693.                                                  NULL)
  1694.                != NULL)
  1695.         {
  1696.             goto ok;
  1697.         }

  1698.         if ((p & NGX_HTTP_GZIP_PROXIED_NO_STORE)
  1699.             && ngx_http_parse_multi_header_lines(r, cc, &ngx_http_gzip_no_store,
  1700.                                                  NULL)
  1701.                != NULL)
  1702.         {
  1703.             goto ok;
  1704.         }

  1705.         if ((p & NGX_HTTP_GZIP_PROXIED_PRIVATE)
  1706.             && ngx_http_parse_multi_header_lines(r, cc, &ngx_http_gzip_private,
  1707.                                                  NULL)
  1708.                != NULL)
  1709.         {
  1710.             goto ok;
  1711.         }

  1712.         return NGX_DECLINED;
  1713.     }

  1714.     if ((p & NGX_HTTP_GZIP_PROXIED_NO_LM) && r->headers_out.last_modified) {
  1715.         return NGX_DECLINED;
  1716.     }

  1717.     if ((p & NGX_HTTP_GZIP_PROXIED_NO_ETAG) && r->headers_out.etag) {
  1718.         return NGX_DECLINED;
  1719.     }

  1720. ok:

  1721. #if (NGX_PCRE)

  1722.     if (clcf->gzip_disable && r->headers_in.user_agent) {

  1723.         if (ngx_regex_exec_array(clcf->gzip_disable,
  1724.                                  &r->headers_in.user_agent->value,
  1725.                                  r->connection->log)
  1726.             != NGX_DECLINED)
  1727.         {
  1728.             return NGX_DECLINED;
  1729.         }
  1730.     }

  1731. #endif

  1732.     r->gzip_ok = 1;

  1733.     return NGX_OK;
  1734. }


  1735. /*
  1736. * gzip is enabled for the following quantities:
  1737. *     "gzip; q=0.001" ... "gzip; q=1.000"
  1738. * gzip is disabled for the following quantities:
  1739. *     "gzip; q=0" ... "gzip; q=0.000", and for any invalid cases
  1740. */

  1741. static ngx_int_t
  1742. ngx_http_gzip_accept_encoding(ngx_str_t *ae)
  1743. {
  1744.     u_char  *p, *start, *last;

  1745.     start = ae->data;
  1746.     last = start + ae->len;

  1747.     for ( ;; ) {
  1748.         p = ngx_strcasestrn(start, "gzip", 4 - 1);
  1749.         if (p == NULL) {
  1750.             return NGX_DECLINED;
  1751.         }

  1752.         if (p == start || (*(p - 1) == ',' || *(p - 1) == ' ')) {
  1753.             break;
  1754.         }

  1755.         start = p + 4;
  1756.     }

  1757.     p += 4;

  1758.     while (p < last) {
  1759.         switch (*p++) {
  1760.         case ',':
  1761.             return NGX_OK;
  1762.         case ';':
  1763.             goto quantity;
  1764.         case ' ':
  1765.             continue;
  1766.         default:
  1767.             return NGX_DECLINED;
  1768.         }
  1769.     }

  1770.     return NGX_OK;

  1771. quantity:

  1772.     while (p < last) {
  1773.         switch (*p++) {
  1774.         case 'q':
  1775.         case 'Q':
  1776.             goto equal;
  1777.         case ' ':
  1778.             continue;
  1779.         default:
  1780.             return NGX_DECLINED;
  1781.         }
  1782.     }

  1783.     return NGX_OK;

  1784. equal:

  1785.     if (p + 2 > last || *p++ != '=') {
  1786.         return NGX_DECLINED;
  1787.     }

  1788.     if (ngx_http_gzip_quantity(p, last) == 0) {
  1789.         return NGX_DECLINED;
  1790.     }

  1791.     return NGX_OK;
  1792. }


  1793. static ngx_uint_t
  1794. ngx_http_gzip_quantity(u_char *p, u_char *last)
  1795. {
  1796.     u_char      c;
  1797.     ngx_uint_t  n, q;

  1798.     c = *p++;

  1799.     if (c != '0' && c != '1') {
  1800.         return 0;
  1801.     }

  1802.     q = (c - '0') * 100;

  1803.     if (p == last) {
  1804.         return q;
  1805.     }

  1806.     c = *p++;

  1807.     if (c == ',' || c == ' ') {
  1808.         return q;
  1809.     }

  1810.     if (c != '.') {
  1811.         return 0;
  1812.     }

  1813.     n = 0;

  1814.     while (p < last) {
  1815.         c = *p++;

  1816.         if (c == ',' || c == ' ') {
  1817.             break;
  1818.         }

  1819.         if (c >= '0' && c <= '9') {
  1820.             q += c - '0';
  1821.             n++;
  1822.             continue;
  1823.         }

  1824.         return 0;
  1825.     }

  1826.     if (q > 100 || n > 3) {
  1827.         return 0;
  1828.     }

  1829.     return q;
  1830. }

  1831. #endif


  1832. ngx_int_t
  1833. ngx_http_subrequest(ngx_http_request_t *r,
  1834.     ngx_str_t *uri, ngx_str_t *args, ngx_http_request_t **psr,
  1835.     ngx_http_post_subrequest_t *ps, ngx_uint_t flags)
  1836. {
  1837.     ngx_time_t                    *tp;
  1838.     ngx_connection_t              *c;
  1839.     ngx_http_request_t            *sr;
  1840.     ngx_http_core_srv_conf_t      *cscf;
  1841.     ngx_http_posted_request_t     *posted;
  1842.     ngx_http_postponed_request_t  *pr, *p;

  1843.     if (r->subrequests == 0) {
  1844.         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1845.                       "subrequests cycle while processing \"%V\"", uri);
  1846.         return NGX_ERROR;
  1847.     }

  1848.     /*
  1849.      * 1000 is reserved for other purposes.
  1850.      */
  1851.     if (r->main->count >= 65535 - 1000) {
  1852.         ngx_log_error(NGX_LOG_CRIT, r->connection->log, 0,
  1853.                       "request reference counter overflow "
  1854.                       "while processing \"%V\"", uri);
  1855.         return NGX_ERROR;
  1856.     }

  1857.     if (r->subrequest_in_memory) {
  1858.         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1859.                       "nested in-memory subrequest \"%V\"", uri);
  1860.         return NGX_ERROR;
  1861.     }

  1862.     sr = ngx_pcalloc(r->pool, sizeof(ngx_http_request_t));
  1863.     if (sr == NULL) {
  1864.         return NGX_ERROR;
  1865.     }

  1866.     sr->signature = NGX_HTTP_MODULE;

  1867.     c = r->connection;
  1868.     sr->connection = c;

  1869.     sr->ctx = ngx_pcalloc(r->pool, sizeof(void *) * ngx_http_max_module);
  1870.     if (sr->ctx == NULL) {
  1871.         return NGX_ERROR;
  1872.     }

  1873.     if (ngx_list_init(&sr->headers_out.headers, r->pool, 20,
  1874.                       sizeof(ngx_table_elt_t))
  1875.         != NGX_OK)
  1876.     {
  1877.         return NGX_ERROR;
  1878.     }

  1879.     if (ngx_list_init(&sr->headers_out.trailers, r->pool, 4,
  1880.                       sizeof(ngx_table_elt_t))
  1881.         != NGX_OK)
  1882.     {
  1883.         return NGX_ERROR;
  1884.     }

  1885.     posted = ngx_palloc(r->pool, sizeof(ngx_http_posted_request_t));
  1886.     if (posted == NULL) {
  1887.         return NGX_ERROR;
  1888.     }

  1889.     cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
  1890.     sr->main_conf = cscf->ctx->main_conf;
  1891.     sr->srv_conf = cscf->ctx->srv_conf;
  1892.     sr->loc_conf = cscf->ctx->loc_conf;

  1893.     sr->pool = r->pool;

  1894.     sr->headers_in = r->headers_in;

  1895.     ngx_http_clear_content_length(sr);
  1896.     ngx_http_clear_accept_ranges(sr);
  1897.     ngx_http_clear_last_modified(sr);

  1898.     sr->request_body = r->request_body;

  1899. #if (NGX_HTTP_V2)
  1900.     sr->stream = r->stream;
  1901. #endif

  1902.     sr->method = NGX_HTTP_GET;
  1903.     sr->http_version = r->http_version;

  1904.     sr->port = r->port;

  1905.     sr->request_line = r->request_line;
  1906.     sr->uri = *uri;

  1907.     if (args) {
  1908.         sr->args = *args;
  1909.     }

  1910.     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
  1911.                    "http subrequest \"%V?%V\"", uri, &sr->args);

  1912.     sr->subrequest_in_memory = (flags & NGX_HTTP_SUBREQUEST_IN_MEMORY) != 0;
  1913.     sr->waited = (flags & NGX_HTTP_SUBREQUEST_WAITED) != 0;
  1914.     sr->background = (flags & NGX_HTTP_SUBREQUEST_BACKGROUND) != 0;

  1915.     sr->unparsed_uri = r->unparsed_uri;
  1916.     sr->method_name = ngx_http_core_get_method;
  1917.     sr->http_protocol = r->http_protocol;
  1918.     sr->schema = r->schema;

  1919.     ngx_http_set_exten(sr);

  1920.     sr->main = r->main;
  1921.     sr->parent = r;
  1922.     sr->post_subrequest = ps;
  1923.     sr->read_event_handler = ngx_http_request_empty_handler;
  1924.     sr->write_event_handler = ngx_http_handler;

  1925.     sr->variables = r->variables;

  1926.     sr->log_handler = r->log_handler;

  1927.     if (sr->subrequest_in_memory) {
  1928.         sr->filter_need_in_memory = 1;
  1929.     }

  1930.     if (!sr->background) {
  1931.         pr = ngx_palloc(r->pool, sizeof(ngx_http_postponed_request_t));
  1932.         if (pr == NULL) {
  1933.             return NGX_ERROR;
  1934.         }

  1935.         pr->request = sr;
  1936.         pr->out = NULL;
  1937.         pr->next = NULL;

  1938.         if (c->data == r && r->postponed == NULL) {
  1939.             c->data = sr;
  1940.         }

  1941.         if (r->postponed) {
  1942.             for (p = r->postponed; p->next; p = p->next) { /* void */ }
  1943.             p->next = pr;

  1944.         } else {
  1945.             r->postponed = pr;
  1946.         }
  1947.     }

  1948.     sr->internal = 1;

  1949.     sr->discard_body = r->discard_body;
  1950.     sr->expect_tested = 1;
  1951.     sr->main_filter_need_in_memory = r->main_filter_need_in_memory;

  1952.     sr->uri_changes = NGX_HTTP_MAX_URI_CHANGES + 1;
  1953.     sr->subrequests = r->subrequests - 1;

  1954.     tp = ngx_timeofday();
  1955.     sr->start_sec = tp->sec;
  1956.     sr->start_msec = tp->msec;

  1957.     r->main->count++;

  1958.     *psr = sr;

  1959.     if (flags & NGX_HTTP_SUBREQUEST_CLONE) {
  1960.         sr->method = r->method;
  1961.         sr->method_name = r->method_name;
  1962.         sr->loc_conf = r->loc_conf;
  1963.         sr->valid_location = r->valid_location;
  1964.         sr->valid_unparsed_uri = r->valid_unparsed_uri;
  1965.         sr->content_handler = r->content_handler;
  1966.         sr->phase_handler = r->phase_handler;
  1967.         sr->write_event_handler = ngx_http_core_run_phases;

  1968. #if (NGX_PCRE)
  1969.         sr->ncaptures = r->ncaptures;
  1970.         sr->captures = r->captures;
  1971.         sr->captures_data = r->captures_data;
  1972.         sr->realloc_captures = 1;
  1973.         r->realloc_captures = 1;
  1974. #endif

  1975.         ngx_http_update_location_config(sr);
  1976.     }

  1977.     return ngx_http_post_request(sr, posted);
  1978. }


  1979. ngx_int_t
  1980. ngx_http_internal_redirect(ngx_http_request_t *r,
  1981.     ngx_str_t *uri, ngx_str_t *args)
  1982. {
  1983.     ngx_http_core_srv_conf_t  *cscf;

  1984.     r->uri_changes--;

  1985.     if (r->uri_changes == 0) {
  1986.         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1987.                       "rewrite or internal redirection cycle "
  1988.                       "while internally redirecting to \"%V\"", uri);

  1989.         r->main->count++;
  1990.         ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
  1991.         return NGX_DONE;
  1992.     }

  1993.     r->uri = *uri;

  1994.     if (args) {
  1995.         r->args = *args;

  1996.     } else {
  1997.         ngx_str_null(&r->args);
  1998.     }

  1999.     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  2000.                    "internal redirect: \"%V?%V\"", uri, &r->args);

  2001.     ngx_http_set_exten(r);

  2002.     /* clear the modules contexts */
  2003.     ngx_memzero(r->ctx, sizeof(void *) * ngx_http_max_module);

  2004.     cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
  2005.     r->loc_conf = cscf->ctx->loc_conf;

  2006.     ngx_http_update_location_config(r);

  2007. #if (NGX_HTTP_CACHE)
  2008.     r->cache = NULL;
  2009. #endif

  2010.     r->internal = 1;
  2011.     r->valid_unparsed_uri = 0;
  2012.     r->add_uri_to_alias = 0;
  2013.     r->main->count++;

  2014.     ngx_http_handler(r);

  2015.     return NGX_DONE;
  2016. }


  2017. ngx_int_t
  2018. ngx_http_named_location(ngx_http_request_t *r, ngx_str_t *name)
  2019. {
  2020.     ngx_http_core_srv_conf_t    *cscf;
  2021.     ngx_http_core_loc_conf_t   **clcfp;
  2022.     ngx_http_core_main_conf_t   *cmcf;

  2023.     r->main->count++;
  2024.     r->uri_changes--;

  2025.     if (r->uri_changes == 0) {
  2026.         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2027.                       "rewrite or internal redirection cycle "
  2028.                       "while redirect to named location \"%V\"", name);

  2029.         ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
  2030.         return NGX_DONE;
  2031.     }

  2032.     if (r->uri.len == 0) {
  2033.         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2034.                       "empty URI in redirect to named location \"%V\"", name);

  2035.         ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
  2036.         return NGX_DONE;
  2037.     }

  2038.     cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);

  2039.     if (cscf->named_locations) {

  2040.         for (clcfp = cscf->named_locations; *clcfp; clcfp++) {

  2041.             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  2042.                            "test location: \"%V\"", &(*clcfp)->name);

  2043.             if (name->len != (*clcfp)->name.len
  2044.                 || ngx_strncmp(name->data, (*clcfp)->name.data, name->len) != 0)
  2045.             {
  2046.                 continue;
  2047.             }

  2048.             ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  2049.                            "using location: %V \"%V?%V\"",
  2050.                            name, &r->uri, &r->args);

  2051.             r->internal = 1;
  2052.             r->content_handler = NULL;
  2053.             r->uri_changed = 0;
  2054.             r->loc_conf = (*clcfp)->loc_conf;

  2055.             /* clear the modules contexts */
  2056.             ngx_memzero(r->ctx, sizeof(void *) * ngx_http_max_module);

  2057.             ngx_http_update_location_config(r);

  2058.             cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);

  2059.             r->phase_handler = cmcf->phase_engine.location_rewrite_index;

  2060.             r->write_event_handler = ngx_http_core_run_phases;
  2061.             ngx_http_core_run_phases(r);

  2062.             return NGX_DONE;
  2063.         }
  2064.     }

  2065.     ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2066.                   "could not find named location \"%V\"", name);

  2067.     ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);

  2068.     return NGX_DONE;
  2069. }


  2070. ngx_http_cleanup_t *
  2071. ngx_http_cleanup_add(ngx_http_request_t *r, size_t size)
  2072. {
  2073.     ngx_http_cleanup_t  *cln;

  2074.     r = r->main;

  2075.     cln = ngx_palloc(r->pool, sizeof(ngx_http_cleanup_t));
  2076.     if (cln == NULL) {
  2077.         return NULL;
  2078.     }

  2079.     if (size) {
  2080.         cln->data = ngx_palloc(r->pool, size);
  2081.         if (cln->data == NULL) {
  2082.             return NULL;
  2083.         }

  2084.     } else {
  2085.         cln->data = NULL;
  2086.     }

  2087.     cln->handler = NULL;
  2088.     cln->next = r->cleanup;

  2089.     r->cleanup = cln;

  2090.     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  2091.                    "http cleanup add: %p", cln);

  2092.     return cln;
  2093. }


  2094. ngx_int_t
  2095. ngx_http_set_disable_symlinks(ngx_http_request_t *r,
  2096.     ngx_http_core_loc_conf_t *clcf, ngx_str_t *path, ngx_open_file_info_t *of)
  2097. {
  2098. #if (NGX_HAVE_OPENAT)
  2099.     u_char     *p;
  2100.     ngx_str_t   from;

  2101.     of->disable_symlinks = clcf->disable_symlinks;

  2102.     if (clcf->disable_symlinks_from == NULL) {
  2103.         return NGX_OK;
  2104.     }

  2105.     if (ngx_http_complex_value(r, clcf->disable_symlinks_from, &from)
  2106.         != NGX_OK)
  2107.     {
  2108.         return NGX_ERROR;
  2109.     }

  2110.     if (from.len == 0
  2111.         || from.len > path->len
  2112.         || ngx_memcmp(path->data, from.data, from.len) != 0)
  2113.     {
  2114.         return NGX_OK;
  2115.     }

  2116.     if (from.len == path->len) {
  2117.         of->disable_symlinks = NGX_DISABLE_SYMLINKS_OFF;
  2118.         return NGX_OK;
  2119.     }

  2120.     p = path->data + from.len;

  2121.     if (*p == '/') {
  2122.         of->disable_symlinks_from = from.len;
  2123.         return NGX_OK;
  2124.     }

  2125.     p--;

  2126.     if (*p == '/') {
  2127.         of->disable_symlinks_from = from.len - 1;
  2128.     }
  2129. #endif

  2130.     return NGX_OK;
  2131. }


  2132. ngx_int_t
  2133. ngx_http_get_forwarded_addr(ngx_http_request_t *r, ngx_addr_t *addr,
  2134.     ngx_table_elt_t *headers, ngx_str_t *value, ngx_array_t *proxies,
  2135.     int recursive)
  2136. {
  2137.     ngx_int_t         rc;
  2138.     ngx_uint_t        found;
  2139.     ngx_table_elt_t  *h, *next;

  2140.     if (headers == NULL) {
  2141.         return ngx_http_get_forwarded_addr_internal(r, addr, value->data,
  2142.                                                     value->len, proxies,
  2143.                                                     recursive);
  2144.     }

  2145.     /* revert headers order */

  2146.     for (h = headers, headers = NULL; h; h = next) {
  2147.         next = h->next;
  2148.         h->next = headers;
  2149.         headers = h;
  2150.     }

  2151.     /* iterate over all headers in reverse order */

  2152.     rc = NGX_DECLINED;

  2153.     found = 0;

  2154.     for (h = headers; h; h = h->next) {
  2155.         rc = ngx_http_get_forwarded_addr_internal(r, addr, h->value.data,
  2156.                                                   h->value.len, proxies,
  2157.                                                   recursive);

  2158.         if (!recursive) {
  2159.             break;
  2160.         }

  2161.         if (rc == NGX_DECLINED && found) {
  2162.             rc = NGX_DONE;
  2163.             break;
  2164.         }

  2165.         if (rc != NGX_OK) {
  2166.             break;
  2167.         }

  2168.         found = 1;
  2169.     }

  2170.     /* restore headers order */

  2171.     for (h = headers, headers = NULL; h; h = next) {
  2172.         next = h->next;
  2173.         h->next = headers;
  2174.         headers = h;
  2175.     }

  2176.     return rc;
  2177. }


  2178. static ngx_int_t
  2179. ngx_http_get_forwarded_addr_internal(ngx_http_request_t *r, ngx_addr_t *addr,
  2180.     u_char *xff, size_t xfflen, ngx_array_t *proxies, int recursive)
  2181. {
  2182.     u_char      *p;
  2183.     ngx_addr_t   paddr;
  2184.     ngx_uint_t   found;

  2185.     found = 0;

  2186.     do {

  2187.         if (ngx_cidr_match(addr->sockaddr, proxies) != NGX_OK) {
  2188.             return found ? NGX_DONE : NGX_DECLINED;
  2189.         }

  2190.         for (p = xff + xfflen - 1; p > xff; p--, xfflen--) {
  2191.             if (*p != ' ' && *p != ',') {
  2192.                 break;
  2193.             }
  2194.         }

  2195.         for ( /* void */ ; p > xff; p--) {
  2196.             if (*p == ' ' || *p == ',') {
  2197.                 p++;
  2198.                 break;
  2199.             }
  2200.         }

  2201.         if (ngx_parse_addr_port(r->pool, &paddr, p, xfflen - (p - xff))
  2202.             != NGX_OK)
  2203.         {
  2204.             return found ? NGX_DONE : NGX_DECLINED;
  2205.         }

  2206.         *addr = paddr;
  2207.         found = 1;
  2208.         xfflen = p - 1 - xff;

  2209.     } while (recursive && p > xff);

  2210.     return NGX_OK;
  2211. }


  2212. ngx_int_t
  2213. ngx_http_link_multi_headers(ngx_http_request_t *r)
  2214. {
  2215.     ngx_uint_t        i, j;
  2216.     ngx_list_part_t  *part, *ppart;
  2217.     ngx_table_elt_t  *header, *pheader, **ph;

  2218.     if (r->headers_in.multi_linked) {
  2219.         return NGX_OK;
  2220.     }

  2221.     r->headers_in.multi_linked = 1;

  2222.     part = &r->headers_in.headers.part;
  2223.     header = part->elts;

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

  2225.         if (i >= part->nelts) {
  2226.             if (part->next == NULL) {
  2227.                 break;
  2228.             }

  2229.             part = part->next;
  2230.             header = part->elts;
  2231.             i = 0;
  2232.         }

  2233.         header[i].next = NULL;

  2234.         /*
  2235.          * search for previous headers with the same name;
  2236.          * if there are any, link to them
  2237.          */

  2238.         ppart = &r->headers_in.headers.part;
  2239.         pheader = ppart->elts;

  2240.         for (j = 0; /* void */; j++) {

  2241.             if (j >= ppart->nelts) {
  2242.                 if (ppart->next == NULL) {
  2243.                     break;
  2244.                 }

  2245.                 ppart = ppart->next;
  2246.                 pheader = ppart->elts;
  2247.                 j = 0;
  2248.             }

  2249.             if (part == ppart && i == j) {
  2250.                 break;
  2251.             }

  2252.             if (header[i].key.len == pheader[j].key.len
  2253.                 && ngx_strncasecmp(header[i].key.data, pheader[j].key.data,
  2254.                                    header[i].key.len)
  2255.                    == 0)
  2256.             {
  2257.                 ph = &pheader[j].next;
  2258.                 while (*ph) { ph = &(*ph)->next; }
  2259.                 *ph = &header[i];

  2260.                 r->headers_in.multi = 1;

  2261.                 break;
  2262.             }
  2263.         }
  2264.     }

  2265.     return NGX_OK;
  2266. }


  2267. static char *
  2268. ngx_http_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
  2269. {
  2270.     char                        *rv;
  2271.     void                        *mconf;
  2272.     size_t                       len;
  2273.     u_char                      *p;
  2274.     ngx_uint_t                   i;
  2275.     ngx_conf_t                   pcf;
  2276.     ngx_http_module_t           *module;
  2277.     struct sockaddr_in          *sin;
  2278.     ngx_http_conf_ctx_t         *ctx, *http_ctx;
  2279.     ngx_http_listen_opt_t        lsopt;
  2280.     ngx_http_core_srv_conf_t    *cscf, **cscfp;
  2281.     ngx_http_core_main_conf_t   *cmcf;

  2282.     ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
  2283.     if (ctx == NULL) {
  2284.         return NGX_CONF_ERROR;
  2285.     }

  2286.     http_ctx = cf->ctx;
  2287.     ctx->main_conf = http_ctx->main_conf;

  2288.     /* the server{}'s srv_conf */

  2289.     ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
  2290.     if (ctx->srv_conf == NULL) {
  2291.         return NGX_CONF_ERROR;
  2292.     }

  2293.     /* the server{}'s loc_conf */

  2294.     ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
  2295.     if (ctx->loc_conf == NULL) {
  2296.         return NGX_CONF_ERROR;
  2297.     }

  2298.     for (i = 0; cf->cycle->modules[i]; i++) {
  2299.         if (cf->cycle->modules[i]->type != NGX_HTTP_MODULE) {
  2300.             continue;
  2301.         }

  2302.         module = cf->cycle->modules[i]->ctx;

  2303.         if (module->create_srv_conf) {
  2304.             mconf = module->create_srv_conf(cf);
  2305.             if (mconf == NULL) {
  2306.                 return NGX_CONF_ERROR;
  2307.             }

  2308.             ctx->srv_conf[cf->cycle->modules[i]->ctx_index] = mconf;
  2309.         }

  2310.         if (module->create_loc_conf) {
  2311.             mconf = module->create_loc_conf(cf);
  2312.             if (mconf == NULL) {
  2313.                 return NGX_CONF_ERROR;
  2314.             }

  2315.             ctx->loc_conf[cf->cycle->modules[i]->ctx_index] = mconf;
  2316.         }
  2317.     }


  2318.     /* the server configuration context */

  2319.     cscf = ctx->srv_conf[ngx_http_core_module.ctx_index];
  2320.     cscf->ctx = ctx;


  2321.     cmcf = ctx->main_conf[ngx_http_core_module.ctx_index];

  2322.     cscfp = ngx_array_push(&cmcf->servers);
  2323.     if (cscfp == NULL) {
  2324.         return NGX_CONF_ERROR;
  2325.     }

  2326.     *cscfp = cscf;


  2327.     /* parse inside server{} */

  2328.     pcf = *cf;
  2329.     cf->ctx = ctx;
  2330.     cf->cmd_type = NGX_HTTP_SRV_CONF;

  2331.     rv = ngx_conf_parse(cf, NULL);

  2332.     *cf = pcf;

  2333.     if (rv == NGX_CONF_OK && !cscf->listen) {
  2334.         ngx_memzero(&lsopt, sizeof(ngx_http_listen_opt_t));

  2335.         p = ngx_pcalloc(cf->pool, sizeof(struct sockaddr_in));
  2336.         if (p == NULL) {
  2337.             return NGX_CONF_ERROR;
  2338.         }

  2339.         lsopt.sockaddr = (struct sockaddr *) p;

  2340.         sin = (struct sockaddr_in *) p;

  2341.         sin->sin_family = AF_INET;
  2342. #if (NGX_WIN32)
  2343.         sin->sin_port = htons(80);
  2344. #else
  2345.         sin->sin_port = htons((getuid() == 0) ? 80 : 8000);
  2346. #endif
  2347.         sin->sin_addr.s_addr = INADDR_ANY;

  2348.         lsopt.socklen = sizeof(struct sockaddr_in);

  2349.         lsopt.backlog = NGX_LISTEN_BACKLOG;
  2350.         lsopt.type = SOCK_STREAM;
  2351.         lsopt.rcvbuf = -1;
  2352.         lsopt.sndbuf = -1;
  2353. #if (NGX_HAVE_SETFIB)
  2354.         lsopt.setfib = -1;
  2355. #endif
  2356. #if (NGX_HAVE_TCP_FASTOPEN)
  2357.         lsopt.fastopen = -1;
  2358. #endif
  2359.         lsopt.wildcard = 1;

  2360.         len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1;

  2361.         p = ngx_pnalloc(cf->pool, len);
  2362.         if (p == NULL) {
  2363.             return NGX_CONF_ERROR;
  2364.         }

  2365.         lsopt.addr_text.data = p;
  2366.         lsopt.addr_text.len = ngx_sock_ntop(lsopt.sockaddr, lsopt.socklen, p,
  2367.                                             len, 1);

  2368.         if (ngx_http_add_listen(cf, cscf, &lsopt) != NGX_OK) {
  2369.             return NGX_CONF_ERROR;
  2370.         }
  2371.     }

  2372.     return rv;
  2373. }


  2374. static char *
  2375. ngx_http_core_location(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
  2376. {
  2377.     char                      *rv;
  2378.     u_char                    *mod;
  2379.     size_t                     len;
  2380.     ngx_str_t                 *value, *name;
  2381.     ngx_uint_t                 i;
  2382.     ngx_conf_t                 save;
  2383.     ngx_http_module_t         *module;
  2384.     ngx_http_conf_ctx_t       *ctx, *pctx;
  2385.     ngx_http_core_loc_conf_t  *clcf, *pclcf;

  2386.     ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
  2387.     if (ctx == NULL) {
  2388.         return NGX_CONF_ERROR;
  2389.     }

  2390.     pctx = cf->ctx;
  2391.     ctx->main_conf = pctx->main_conf;
  2392.     ctx->srv_conf = pctx->srv_conf;

  2393.     ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
  2394.     if (ctx->loc_conf == NULL) {
  2395.         return NGX_CONF_ERROR;
  2396.     }

  2397.     for (i = 0; cf->cycle->modules[i]; i++) {
  2398.         if (cf->cycle->modules[i]->type != NGX_HTTP_MODULE) {
  2399.             continue;
  2400.         }

  2401.         module = cf->cycle->modules[i]->ctx;

  2402.         if (module->create_loc_conf) {
  2403.             ctx->loc_conf[cf->cycle->modules[i]->ctx_index] =
  2404.                                                    module->create_loc_conf(cf);
  2405.             if (ctx->loc_conf[cf->cycle->modules[i]->ctx_index] == NULL) {
  2406.                 return NGX_CONF_ERROR;
  2407.             }
  2408.         }
  2409.     }

  2410.     clcf = ctx->loc_conf[ngx_http_core_module.ctx_index];
  2411.     clcf->loc_conf = ctx->loc_conf;

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

  2413.     if (cf->args->nelts == 3) {

  2414.         len = value[1].len;
  2415.         mod = value[1].data;
  2416.         name = &value[2];

  2417.         if (len == 1 && mod[0] == '=') {

  2418.             clcf->name = *name;
  2419.             clcf->exact_match = 1;

  2420.         } else if (len == 2 && mod[0] == '^' && mod[1] == '~') {

  2421.             clcf->name = *name;
  2422.             clcf->noregex = 1;

  2423.         } else if (len == 1 && mod[0] == '~') {

  2424.             if (ngx_http_core_regex_location(cf, clcf, name, 0) != NGX_OK) {
  2425.                 return NGX_CONF_ERROR;
  2426.             }

  2427.         } else if (len == 2 && mod[0] == '~' && mod[1] == '*') {

  2428.             if (ngx_http_core_regex_location(cf, clcf, name, 1) != NGX_OK) {
  2429.                 return NGX_CONF_ERROR;
  2430.             }

  2431.         } else {
  2432.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  2433.                                "invalid location modifier \"%V\"", &value[1]);
  2434.             return NGX_CONF_ERROR;
  2435.         }

  2436.     } else {

  2437.         name = &value[1];

  2438.         if (name->data[0] == '=') {

  2439.             clcf->name.len = name->len - 1;
  2440.             clcf->name.data = name->data + 1;
  2441.             clcf->exact_match = 1;

  2442.         } else if (name->data[0] == '^' && name->data[1] == '~') {

  2443.             clcf->name.len = name->len - 2;
  2444.             clcf->name.data = name->data + 2;
  2445.             clcf->noregex = 1;

  2446.         } else if (name->data[0] == '~') {

  2447.             name->len--;
  2448.             name->data++;

  2449.             if (name->data[0] == '*') {

  2450.                 name->len--;
  2451.                 name->data++;

  2452.                 if (ngx_http_core_regex_location(cf, clcf, name, 1) != NGX_OK) {
  2453.                     return NGX_CONF_ERROR;
  2454.                 }

  2455.             } else {
  2456.                 if (ngx_http_core_regex_location(cf, clcf, name, 0) != NGX_OK) {
  2457.                     return NGX_CONF_ERROR;
  2458.                 }
  2459.             }

  2460.         } else {

  2461.             clcf->name = *name;

  2462.             if (name->data[0] == '@') {
  2463.                 clcf->named = 1;
  2464.             }
  2465.         }
  2466.     }

  2467.     pclcf = pctx->loc_conf[ngx_http_core_module.ctx_index];

  2468.     if (cf->cmd_type == NGX_HTTP_LOC_CONF) {

  2469.         /* nested location */

  2470. #if 0
  2471.         clcf->prev_location = pclcf;
  2472. #endif

  2473.         if (pclcf->exact_match) {
  2474.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  2475.                                "location \"%V\" cannot be inside "
  2476.                                "the exact location \"%V\"",
  2477.                                &clcf->name, &pclcf->name);
  2478.             return NGX_CONF_ERROR;
  2479.         }

  2480.         if (pclcf->named) {
  2481.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  2482.                                "location \"%V\" cannot be inside "
  2483.                                "the named location \"%V\"",
  2484.                                &clcf->name, &pclcf->name);
  2485.             return NGX_CONF_ERROR;
  2486.         }

  2487.         if (clcf->named) {
  2488.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  2489.                                "named location \"%V\" can be "
  2490.                                "on the server level only",
  2491.                                &clcf->name);
  2492.             return NGX_CONF_ERROR;
  2493.         }

  2494.         len = pclcf->name.len;

  2495. #if (NGX_PCRE)
  2496.         if (clcf->regex == NULL
  2497.             && ngx_filename_cmp(clcf->name.data, pclcf->name.data, len) != 0)
  2498. #else
  2499.         if (ngx_filename_cmp(clcf->name.data, pclcf->name.data, len) != 0)
  2500. #endif
  2501.         {
  2502.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  2503.                                "location \"%V\" is outside location \"%V\"",
  2504.                                &clcf->name, &pclcf->name);
  2505.             return NGX_CONF_ERROR;
  2506.         }
  2507.     }

  2508.     if (ngx_http_add_location(cf, &pclcf->locations, clcf) != NGX_OK) {
  2509.         return NGX_CONF_ERROR;
  2510.     }

  2511.     save = *cf;
  2512.     cf->ctx = ctx;
  2513.     cf->cmd_type = NGX_HTTP_LOC_CONF;

  2514.     rv = ngx_conf_parse(cf, NULL);

  2515.     *cf = save;

  2516.     return rv;
  2517. }


  2518. static ngx_int_t
  2519. ngx_http_core_regex_location(ngx_conf_t *cf, ngx_http_core_loc_conf_t *clcf,
  2520.     ngx_str_t *regex, ngx_uint_t caseless)
  2521. {
  2522. #if (NGX_PCRE)
  2523.     ngx_regex_compile_t  rc;
  2524.     u_char               errstr[NGX_MAX_CONF_ERRSTR];

  2525.     ngx_memzero(&rc, sizeof(ngx_regex_compile_t));

  2526.     rc.pattern = *regex;
  2527.     rc.err.len = NGX_MAX_CONF_ERRSTR;
  2528.     rc.err.data = errstr;

  2529. #if (NGX_HAVE_CASELESS_FILESYSTEM)
  2530.     rc.options = NGX_REGEX_CASELESS;
  2531. #else
  2532.     rc.options = caseless ? NGX_REGEX_CASELESS : 0;
  2533. #endif

  2534.     clcf->regex = ngx_http_regex_compile(cf, &rc);
  2535.     if (clcf->regex == NULL) {
  2536.         return NGX_ERROR;
  2537.     }

  2538.     clcf->name = *regex;

  2539.     return NGX_OK;

  2540. #else

  2541.     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  2542.                        "using regex \"%V\" requires PCRE library",
  2543.                        regex);
  2544.     return NGX_ERROR;

  2545. #endif
  2546. }


  2547. static char *
  2548. ngx_http_core_types(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  2549. {
  2550.     ngx_http_core_loc_conf_t *clcf = conf;

  2551.     char        *rv;
  2552.     ngx_conf_t   save;

  2553.     if (clcf->types == NULL) {
  2554.         clcf->types = ngx_array_create(cf->pool, 64, sizeof(ngx_hash_key_t));
  2555.         if (clcf->types == NULL) {
  2556.             return NGX_CONF_ERROR;
  2557.         }
  2558.     }

  2559.     save = *cf;
  2560.     cf->handler = ngx_http_core_type;
  2561.     cf->handler_conf = conf;

  2562.     rv = ngx_conf_parse(cf, NULL);

  2563.     *cf = save;

  2564.     return rv;
  2565. }


  2566. static char *
  2567. ngx_http_core_type(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
  2568. {
  2569.     ngx_http_core_loc_conf_t *clcf = conf;

  2570.     ngx_str_t       *value, *content_type, *old;
  2571.     ngx_uint_t       i, n, hash;
  2572.     ngx_hash_key_t  *type;

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

  2574.     if (ngx_strcmp(value[0].data, "include") == 0) {
  2575.         if (cf->args->nelts != 2) {
  2576.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  2577.                                "invalid number of arguments"
  2578.                                " in \"include\" directive");
  2579.             return NGX_CONF_ERROR;
  2580.         }

  2581.         return ngx_conf_include(cf, dummy, conf);
  2582.     }

  2583.     content_type = ngx_palloc(cf->pool, sizeof(ngx_str_t));
  2584.     if (content_type == NULL) {
  2585.         return NGX_CONF_ERROR;
  2586.     }

  2587.     *content_type = value[0];

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

  2589.         hash = ngx_hash_strlow(value[i].data, value[i].data, value[i].len);

  2590.         type = clcf->types->elts;
  2591.         for (n = 0; n < clcf->types->nelts; n++) {
  2592.             if (ngx_strcmp(value[i].data, type[n].key.data) == 0) {
  2593.                 old = type[n].value;
  2594.                 type[n].value = content_type;

  2595.                 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
  2596.                                    "duplicate extension \"%V\", "
  2597.                                    "content type: \"%V\", "
  2598.                                    "previous content type: \"%V\"",
  2599.                                    &value[i], content_type, old);
  2600.                 goto next;
  2601.             }
  2602.         }


  2603.         type = ngx_array_push(clcf->types);
  2604.         if (type == NULL) {
  2605.             return NGX_CONF_ERROR;
  2606.         }

  2607.         type->key = value[i];
  2608.         type->key_hash = hash;
  2609.         type->value = content_type;

  2610.     next:
  2611.         continue;
  2612.     }

  2613.     return NGX_CONF_OK;
  2614. }


  2615. static ngx_int_t
  2616. ngx_http_core_preconfiguration(ngx_conf_t *cf)
  2617. {
  2618.     return ngx_http_variables_add_core_vars(cf);
  2619. }


  2620. static ngx_int_t
  2621. ngx_http_core_postconfiguration(ngx_conf_t *cf)
  2622. {
  2623.     ngx_http_top_request_body_filter = ngx_http_request_body_save_filter;

  2624.     return NGX_OK;
  2625. }


  2626. static void *
  2627. ngx_http_core_create_main_conf(ngx_conf_t *cf)
  2628. {
  2629.     ngx_http_core_main_conf_t  *cmcf;

  2630.     cmcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_core_main_conf_t));
  2631.     if (cmcf == NULL) {
  2632.         return NULL;
  2633.     }

  2634.     if (ngx_array_init(&cmcf->servers, cf->pool, 4,
  2635.                        sizeof(ngx_http_core_srv_conf_t *))
  2636.         != NGX_OK)
  2637.     {
  2638.         return NULL;
  2639.     }

  2640.     cmcf->server_names_hash_max_size = NGX_CONF_UNSET_UINT;
  2641.     cmcf->server_names_hash_bucket_size = NGX_CONF_UNSET_UINT;

  2642.     cmcf->variables_hash_max_size = NGX_CONF_UNSET_UINT;
  2643.     cmcf->variables_hash_bucket_size = NGX_CONF_UNSET_UINT;

  2644.     return cmcf;
  2645. }


  2646. static char *
  2647. ngx_http_core_init_main_conf(ngx_conf_t *cf, void *conf)
  2648. {
  2649.     ngx_http_core_main_conf_t *cmcf = conf;

  2650.     ngx_conf_init_uint_value(cmcf->server_names_hash_max_size, 512);
  2651.     ngx_conf_init_uint_value(cmcf->server_names_hash_bucket_size,
  2652.                              ngx_cacheline_size);

  2653.     cmcf->server_names_hash_bucket_size =
  2654.             ngx_align(cmcf->server_names_hash_bucket_size, ngx_cacheline_size);


  2655.     ngx_conf_init_uint_value(cmcf->variables_hash_max_size, 1024);
  2656.     ngx_conf_init_uint_value(cmcf->variables_hash_bucket_size, 64);

  2657.     cmcf->variables_hash_bucket_size =
  2658.                ngx_align(cmcf->variables_hash_bucket_size, ngx_cacheline_size);

  2659.     if (cmcf->ncaptures) {
  2660.         cmcf->ncaptures = (cmcf->ncaptures + 1) * 3;
  2661.     }

  2662.     return NGX_CONF_OK;
  2663. }


  2664. static void *
  2665. ngx_http_core_create_srv_conf(ngx_conf_t *cf)
  2666. {
  2667.     ngx_http_core_srv_conf_t  *cscf;

  2668.     cscf = ngx_pcalloc(cf->pool, sizeof(ngx_http_core_srv_conf_t));
  2669.     if (cscf == NULL) {
  2670.         return NULL;
  2671.     }

  2672.     /*
  2673.      * set by ngx_pcalloc():
  2674.      *
  2675.      *     conf->client_large_buffers.num = 0;
  2676.      */

  2677.     if (ngx_array_init(&cscf->server_names, cf->temp_pool, 4,
  2678.                        sizeof(ngx_http_server_name_t))
  2679.         != NGX_OK)
  2680.     {
  2681.         return NULL;
  2682.     }

  2683.     cscf->connection_pool_size = NGX_CONF_UNSET_SIZE;
  2684.     cscf->request_pool_size = NGX_CONF_UNSET_SIZE;
  2685.     cscf->client_header_timeout = NGX_CONF_UNSET_MSEC;
  2686.     cscf->client_header_buffer_size = NGX_CONF_UNSET_SIZE;
  2687.     cscf->max_headers = NGX_CONF_UNSET_UINT;
  2688.     cscf->ignore_invalid_headers = NGX_CONF_UNSET;
  2689.     cscf->merge_slashes = NGX_CONF_UNSET;
  2690.     cscf->underscores_in_headers = NGX_CONF_UNSET;

  2691.     cscf->file_name = cf->conf_file->file.name.data;
  2692.     cscf->line = cf->conf_file->line;

  2693.     return cscf;
  2694. }


  2695. static char *
  2696. ngx_http_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
  2697. {
  2698.     ngx_http_core_srv_conf_t *prev = parent;
  2699.     ngx_http_core_srv_conf_t *conf = child;

  2700.     ngx_str_t                name;
  2701.     ngx_http_server_name_t  *sn;

  2702.     /* TODO: it does not merge, it inits only */

  2703.     ngx_conf_merge_size_value(conf->connection_pool_size,
  2704.                               prev->connection_pool_size, 64 * sizeof(void *));
  2705.     ngx_conf_merge_size_value(conf->request_pool_size,
  2706.                               prev->request_pool_size, 4096);
  2707.     ngx_conf_merge_msec_value(conf->client_header_timeout,
  2708.                               prev->client_header_timeout, 60000);
  2709.     ngx_conf_merge_size_value(conf->client_header_buffer_size,
  2710.                               prev->client_header_buffer_size, 1024);
  2711.     ngx_conf_merge_bufs_value(conf->large_client_header_buffers,
  2712.                               prev->large_client_header_buffers,
  2713.                               4, 8192);

  2714.     if (conf->large_client_header_buffers.size < conf->connection_pool_size) {
  2715.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  2716.                            "the \"large_client_header_buffers\" size must be "
  2717.                            "equal to or greater than \"connection_pool_size\"");
  2718.         return NGX_CONF_ERROR;
  2719.     }

  2720.     ngx_conf_merge_uint_value(conf->max_headers, prev->max_headers, 1000);

  2721.     ngx_conf_merge_value(conf->ignore_invalid_headers,
  2722.                               prev->ignore_invalid_headers, 1);

  2723.     ngx_conf_merge_value(conf->merge_slashes, prev->merge_slashes, 1);

  2724.     ngx_conf_merge_value(conf->underscores_in_headers,
  2725.                               prev->underscores_in_headers, 0);

  2726.     if (conf->server_names.nelts == 0) {
  2727.         /* the array has 4 empty preallocated elements, so push cannot fail */
  2728.         sn = ngx_array_push(&conf->server_names);
  2729. #if (NGX_PCRE)
  2730.         sn->regex = NULL;
  2731. #endif
  2732.         sn->server = conf;
  2733.         ngx_str_set(&sn->name, "");
  2734.     }

  2735.     sn = conf->server_names.elts;
  2736.     name = sn[0].name;

  2737. #if (NGX_PCRE)
  2738.     if (sn->regex) {
  2739.         name.len++;
  2740.         name.data--;
  2741.     } else
  2742. #endif

  2743.     if (name.data[0] == '.') {
  2744.         name.len--;
  2745.         name.data++;
  2746.     }

  2747.     conf->server_name.len = name.len;
  2748.     conf->server_name.data = ngx_pstrdup(cf->pool, &name);
  2749.     if (conf->server_name.data == NULL) {
  2750.         return NGX_CONF_ERROR;
  2751.     }

  2752.     return NGX_CONF_OK;
  2753. }


  2754. static void *
  2755. ngx_http_core_create_loc_conf(ngx_conf_t *cf)
  2756. {
  2757.     ngx_http_core_loc_conf_t  *clcf;

  2758.     clcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_core_loc_conf_t));
  2759.     if (clcf == NULL) {
  2760.         return NULL;
  2761.     }

  2762.     /*
  2763.      * set by ngx_pcalloc():
  2764.      *
  2765.      *     clcf->escaped_name = { 0, NULL };
  2766.      *     clcf->root = { 0, NULL };
  2767.      *     clcf->limit_except = 0;
  2768.      *     clcf->post_action = { 0, NULL };
  2769.      *     clcf->types = NULL;
  2770.      *     clcf->default_type = { 0, NULL };
  2771.      *     clcf->error_log = NULL;
  2772.      *     clcf->error_pages = NULL;
  2773.      *     clcf->client_body_path = NULL;
  2774.      *     clcf->regex = NULL;
  2775.      *     clcf->exact_match = 0;
  2776.      *     clcf->auto_redirect = 0;
  2777.      *     clcf->alias = 0;
  2778.      *     clcf->gzip_proxied = 0;
  2779.      *     clcf->keepalive_disable = 0;
  2780.      */

  2781.     clcf->client_max_body_size = NGX_CONF_UNSET;
  2782.     clcf->client_body_buffer_size = NGX_CONF_UNSET_SIZE;
  2783.     clcf->client_body_timeout = NGX_CONF_UNSET_MSEC;
  2784.     clcf->satisfy = NGX_CONF_UNSET_UINT;
  2785.     clcf->auth_delay = NGX_CONF_UNSET_MSEC;
  2786.     clcf->if_modified_since = NGX_CONF_UNSET_UINT;
  2787.     clcf->max_ranges = NGX_CONF_UNSET_UINT;
  2788.     clcf->client_body_in_file_only = NGX_CONF_UNSET_UINT;
  2789.     clcf->client_body_in_single_buffer = NGX_CONF_UNSET;
  2790.     clcf->internal = NGX_CONF_UNSET;
  2791.     clcf->sendfile = NGX_CONF_UNSET;
  2792.     clcf->sendfile_max_chunk = NGX_CONF_UNSET_SIZE;
  2793.     clcf->subrequest_output_buffer_size = NGX_CONF_UNSET_SIZE;
  2794.     clcf->aio = NGX_CONF_UNSET;
  2795.     clcf->aio_write = NGX_CONF_UNSET;
  2796. #if (NGX_THREADS)
  2797.     clcf->thread_pool = NGX_CONF_UNSET_PTR;
  2798.     clcf->thread_pool_value = NGX_CONF_UNSET_PTR;
  2799. #endif
  2800.     clcf->read_ahead = NGX_CONF_UNSET_SIZE;
  2801.     clcf->directio = NGX_CONF_UNSET;
  2802.     clcf->directio_alignment = NGX_CONF_UNSET;
  2803.     clcf->tcp_nopush = NGX_CONF_UNSET;
  2804.     clcf->tcp_nodelay = NGX_CONF_UNSET;
  2805.     clcf->send_timeout = NGX_CONF_UNSET_MSEC;
  2806.     clcf->send_lowat = NGX_CONF_UNSET_SIZE;
  2807.     clcf->postpone_output = NGX_CONF_UNSET_SIZE;
  2808.     clcf->limit_rate = NGX_CONF_UNSET_PTR;
  2809.     clcf->limit_rate_after = NGX_CONF_UNSET_PTR;
  2810.     clcf->keepalive_time = NGX_CONF_UNSET_MSEC;
  2811.     clcf->keepalive_timeout = NGX_CONF_UNSET_MSEC;
  2812.     clcf->keepalive_header = NGX_CONF_UNSET;
  2813.     clcf->keepalive_min_timeout = NGX_CONF_UNSET_MSEC;
  2814.     clcf->keepalive_requests = NGX_CONF_UNSET_UINT;
  2815.     clcf->lingering_close = NGX_CONF_UNSET_UINT;
  2816.     clcf->lingering_time = NGX_CONF_UNSET_MSEC;
  2817.     clcf->lingering_timeout = NGX_CONF_UNSET_MSEC;
  2818.     clcf->resolver_timeout = NGX_CONF_UNSET_MSEC;
  2819.     clcf->reset_timedout_connection = NGX_CONF_UNSET;
  2820.     clcf->absolute_redirect = NGX_CONF_UNSET;
  2821.     clcf->server_name_in_redirect = NGX_CONF_UNSET;
  2822.     clcf->port_in_redirect = NGX_CONF_UNSET;
  2823.     clcf->msie_padding = NGX_CONF_UNSET;
  2824.     clcf->msie_refresh = NGX_CONF_UNSET;
  2825.     clcf->log_not_found = NGX_CONF_UNSET;
  2826.     clcf->log_subrequest = NGX_CONF_UNSET;
  2827.     clcf->recursive_error_pages = NGX_CONF_UNSET;
  2828.     clcf->chunked_transfer_encoding = NGX_CONF_UNSET;
  2829.     clcf->etag = NGX_CONF_UNSET;
  2830.     clcf->server_tokens = NGX_CONF_UNSET_UINT;
  2831.     clcf->early_hints = NGX_CONF_UNSET_PTR;
  2832.     clcf->types_hash_max_size = NGX_CONF_UNSET_UINT;
  2833.     clcf->types_hash_bucket_size = NGX_CONF_UNSET_UINT;

  2834.     clcf->open_file_cache = NGX_CONF_UNSET_PTR;
  2835.     clcf->open_file_cache_valid = NGX_CONF_UNSET;
  2836.     clcf->open_file_cache_min_uses = NGX_CONF_UNSET_UINT;
  2837.     clcf->open_file_cache_errors = NGX_CONF_UNSET;
  2838.     clcf->open_file_cache_events = NGX_CONF_UNSET;

  2839. #if (NGX_HTTP_GZIP)
  2840.     clcf->gzip_vary = NGX_CONF_UNSET;
  2841.     clcf->gzip_http_version = NGX_CONF_UNSET_UINT;
  2842. #if (NGX_PCRE)
  2843.     clcf->gzip_disable = NGX_CONF_UNSET_PTR;
  2844. #endif
  2845.     clcf->gzip_disable_msie6 = 3;
  2846. #if (NGX_HTTP_DEGRADATION)
  2847.     clcf->gzip_disable_degradation = 3;
  2848. #endif
  2849. #endif

  2850. #if (NGX_HAVE_OPENAT)
  2851.     clcf->disable_symlinks = NGX_CONF_UNSET_UINT;
  2852.     clcf->disable_symlinks_from = NGX_CONF_UNSET_PTR;
  2853. #endif

  2854.     return clcf;
  2855. }


  2856. static ngx_str_t  ngx_http_core_text_html_type = ngx_string("text/html");
  2857. static ngx_str_t  ngx_http_core_image_gif_type = ngx_string("image/gif");
  2858. static ngx_str_t  ngx_http_core_image_jpeg_type = ngx_string("image/jpeg");

  2859. static ngx_hash_key_t  ngx_http_core_default_types[] = {
  2860.     { ngx_string("html"), 0, &ngx_http_core_text_html_type },
  2861.     { ngx_string("gif"), 0, &ngx_http_core_image_gif_type },
  2862.     { ngx_string("jpg"), 0, &ngx_http_core_image_jpeg_type },
  2863.     { ngx_null_string, 0, NULL }
  2864. };


  2865. static char *
  2866. ngx_http_core_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
  2867. {
  2868.     ngx_http_core_loc_conf_t *prev = parent;
  2869.     ngx_http_core_loc_conf_t *conf = child;

  2870.     ngx_uint_t        i;
  2871.     ngx_hash_key_t   *type;
  2872.     ngx_hash_init_t   types_hash;

  2873.     if (conf->root.data == NULL) {

  2874.         conf->alias = prev->alias;
  2875.         conf->root = prev->root;
  2876.         conf->root_lengths = prev->root_lengths;
  2877.         conf->root_values = prev->root_values;

  2878.         if (prev->root.data == NULL) {
  2879.             ngx_str_set(&conf->root, "html");

  2880.             if (ngx_conf_full_name(cf->cycle, &conf->root, 0) != NGX_OK) {
  2881.                 return NGX_CONF_ERROR;
  2882.             }
  2883.         }
  2884.     }

  2885.     if (conf->post_action.data == NULL) {
  2886.         conf->post_action = prev->post_action;
  2887.     }

  2888.     ngx_conf_merge_uint_value(conf->types_hash_max_size,
  2889.                               prev->types_hash_max_size, 1024);

  2890.     ngx_conf_merge_uint_value(conf->types_hash_bucket_size,
  2891.                               prev->types_hash_bucket_size, 64);

  2892.     conf->types_hash_bucket_size = ngx_align(conf->types_hash_bucket_size,
  2893.                                              ngx_cacheline_size);

  2894.     /*
  2895.      * the special handling of the "types" directive in the "http" section
  2896.      * to inherit the http's conf->types_hash to all servers
  2897.      */

  2898.     if (prev->types && prev->types_hash.buckets == NULL) {

  2899.         types_hash.hash = &prev->types_hash;
  2900.         types_hash.key = ngx_hash_key_lc;
  2901.         types_hash.max_size = conf->types_hash_max_size;
  2902.         types_hash.bucket_size = conf->types_hash_bucket_size;
  2903.         types_hash.name = "types_hash";
  2904.         types_hash.pool = cf->pool;
  2905.         types_hash.temp_pool = NULL;

  2906.         if (ngx_hash_init(&types_hash, prev->types->elts, prev->types->nelts)
  2907.             != NGX_OK)
  2908.         {
  2909.             return NGX_CONF_ERROR;
  2910.         }
  2911.     }

  2912.     if (conf->types == NULL) {
  2913.         conf->types = prev->types;
  2914.         conf->types_hash = prev->types_hash;
  2915.     }

  2916.     if (conf->types == NULL) {
  2917.         conf->types = ngx_array_create(cf->pool, 3, sizeof(ngx_hash_key_t));
  2918.         if (conf->types == NULL) {
  2919.             return NGX_CONF_ERROR;
  2920.         }

  2921.         for (i = 0; ngx_http_core_default_types[i].key.len; i++) {
  2922.             type = ngx_array_push(conf->types);
  2923.             if (type == NULL) {
  2924.                 return NGX_CONF_ERROR;
  2925.             }

  2926.             type->key = ngx_http_core_default_types[i].key;
  2927.             type->key_hash =
  2928.                        ngx_hash_key_lc(ngx_http_core_default_types[i].key.data,
  2929.                                        ngx_http_core_default_types[i].key.len);
  2930.             type->value = ngx_http_core_default_types[i].value;
  2931.         }
  2932.     }

  2933.     if (conf->types_hash.buckets == NULL) {

  2934.         types_hash.hash = &conf->types_hash;
  2935.         types_hash.key = ngx_hash_key_lc;
  2936.         types_hash.max_size = conf->types_hash_max_size;
  2937.         types_hash.bucket_size = conf->types_hash_bucket_size;
  2938.         types_hash.name = "types_hash";
  2939.         types_hash.pool = cf->pool;
  2940.         types_hash.temp_pool = NULL;

  2941.         if (ngx_hash_init(&types_hash, conf->types->elts, conf->types->nelts)
  2942.             != NGX_OK)
  2943.         {
  2944.             return NGX_CONF_ERROR;
  2945.         }
  2946.     }

  2947.     if (conf->error_log == NULL) {
  2948.         if (prev->error_log) {
  2949.             conf->error_log = prev->error_log;
  2950.         } else {
  2951.             conf->error_log = &cf->cycle->new_log;
  2952.         }
  2953.     }

  2954.     if (conf->error_pages == NULL && prev->error_pages) {
  2955.         conf->error_pages = prev->error_pages;
  2956.     }

  2957.     ngx_conf_merge_str_value(conf->default_type,
  2958.                               prev->default_type, "text/plain");

  2959.     ngx_conf_merge_off_value(conf->client_max_body_size,
  2960.                               prev->client_max_body_size, 1 * 1024 * 1024);
  2961.     ngx_conf_merge_size_value(conf->client_body_buffer_size,
  2962.                               prev->client_body_buffer_size,
  2963.                               (size_t) 2 * ngx_pagesize);
  2964.     ngx_conf_merge_msec_value(conf->client_body_timeout,
  2965.                               prev->client_body_timeout, 60000);

  2966.     ngx_conf_merge_bitmask_value(conf->keepalive_disable,
  2967.                               prev->keepalive_disable,
  2968.                               (NGX_CONF_BITMASK_SET
  2969.                                |NGX_HTTP_KEEPALIVE_DISABLE_MSIE6));
  2970.     ngx_conf_merge_uint_value(conf->satisfy, prev->satisfy,
  2971.                               NGX_HTTP_SATISFY_ALL);
  2972.     ngx_conf_merge_msec_value(conf->auth_delay, prev->auth_delay, 0);
  2973.     ngx_conf_merge_uint_value(conf->if_modified_since, prev->if_modified_since,
  2974.                               NGX_HTTP_IMS_EXACT);
  2975.     ngx_conf_merge_uint_value(conf->max_ranges, prev->max_ranges,
  2976.                               NGX_MAX_INT32_VALUE);
  2977.     ngx_conf_merge_uint_value(conf->client_body_in_file_only,
  2978.                               prev->client_body_in_file_only,
  2979.                               NGX_HTTP_REQUEST_BODY_FILE_OFF);
  2980.     ngx_conf_merge_value(conf->client_body_in_single_buffer,
  2981.                               prev->client_body_in_single_buffer, 0);
  2982.     ngx_conf_merge_value(conf->internal, prev->internal, 0);
  2983.     ngx_conf_merge_value(conf->sendfile, prev->sendfile, 0);
  2984.     ngx_conf_merge_size_value(conf->sendfile_max_chunk,
  2985.                               prev->sendfile_max_chunk, 2 * 1024 * 1024);
  2986.     ngx_conf_merge_size_value(conf->subrequest_output_buffer_size,
  2987.                               prev->subrequest_output_buffer_size,
  2988.                               (size_t) ngx_pagesize);
  2989.     ngx_conf_merge_value(conf->aio, prev->aio, NGX_HTTP_AIO_OFF);
  2990.     ngx_conf_merge_value(conf->aio_write, prev->aio_write, 0);
  2991. #if (NGX_THREADS)
  2992.     ngx_conf_merge_ptr_value(conf->thread_pool, prev->thread_pool, NULL);
  2993.     ngx_conf_merge_ptr_value(conf->thread_pool_value, prev->thread_pool_value,
  2994.                              NULL);
  2995. #endif
  2996.     ngx_conf_merge_size_value(conf->read_ahead, prev->read_ahead, 0);
  2997.     ngx_conf_merge_off_value(conf->directio, prev->directio,
  2998.                               NGX_OPEN_FILE_DIRECTIO_OFF);
  2999.     ngx_conf_merge_off_value(conf->directio_alignment, prev->directio_alignment,
  3000.                               512);
  3001.     ngx_conf_merge_value(conf->tcp_nopush, prev->tcp_nopush, 0);
  3002.     ngx_conf_merge_value(conf->tcp_nodelay, prev->tcp_nodelay, 1);

  3003.     ngx_conf_merge_msec_value(conf->send_timeout, prev->send_timeout, 60000);
  3004.     ngx_conf_merge_size_value(conf->send_lowat, prev->send_lowat, 0);
  3005.     ngx_conf_merge_size_value(conf->postpone_output, prev->postpone_output,
  3006.                               1460);

  3007.     ngx_conf_merge_ptr_value(conf->limit_rate, prev->limit_rate, NULL);
  3008.     ngx_conf_merge_ptr_value(conf->limit_rate_after,
  3009.                               prev->limit_rate_after, NULL);

  3010.     ngx_conf_merge_msec_value(conf->keepalive_time,
  3011.                               prev->keepalive_time, 3600000);
  3012.     ngx_conf_merge_msec_value(conf->keepalive_timeout,
  3013.                               prev->keepalive_timeout, 75000);
  3014.     ngx_conf_merge_sec_value(conf->keepalive_header,
  3015.                               prev->keepalive_header, 0);
  3016.     ngx_conf_merge_msec_value(conf->keepalive_min_timeout,
  3017.                               prev->keepalive_min_timeout, 0);
  3018.     ngx_conf_merge_uint_value(conf->keepalive_requests,
  3019.                               prev->keepalive_requests, 1000);
  3020.     ngx_conf_merge_uint_value(conf->lingering_close,
  3021.                               prev->lingering_close, NGX_HTTP_LINGERING_ON);
  3022.     ngx_conf_merge_msec_value(conf->lingering_time,
  3023.                               prev->lingering_time, 30000);
  3024.     ngx_conf_merge_msec_value(conf->lingering_timeout,
  3025.                               prev->lingering_timeout, 5000);
  3026.     ngx_conf_merge_msec_value(conf->resolver_timeout,
  3027.                               prev->resolver_timeout, 30000);

  3028.     if (conf->resolver == NULL) {

  3029.         if (prev->resolver == NULL) {

  3030.             /*
  3031.              * create dummy resolver in http {} context
  3032.              * to inherit it in all servers
  3033.              */

  3034.             prev->resolver = ngx_resolver_create(cf, NULL, 0);
  3035.             if (prev->resolver == NULL) {
  3036.                 return NGX_CONF_ERROR;
  3037.             }
  3038.         }

  3039.         conf->resolver = prev->resolver;
  3040.     }

  3041.     if (ngx_conf_merge_path_value(cf, &conf->client_body_temp_path,
  3042.                               prev->client_body_temp_path,
  3043.                               &ngx_http_client_temp_path)
  3044.         != NGX_CONF_OK)
  3045.     {
  3046.         return NGX_CONF_ERROR;
  3047.     }

  3048.     ngx_conf_merge_value(conf->reset_timedout_connection,
  3049.                               prev->reset_timedout_connection, 0);
  3050.     ngx_conf_merge_value(conf->absolute_redirect,
  3051.                               prev->absolute_redirect, 1);
  3052.     ngx_conf_merge_value(conf->server_name_in_redirect,
  3053.                               prev->server_name_in_redirect, 0);
  3054.     ngx_conf_merge_value(conf->port_in_redirect, prev->port_in_redirect, 1);
  3055.     ngx_conf_merge_value(conf->msie_padding, prev->msie_padding, 1);
  3056.     ngx_conf_merge_value(conf->msie_refresh, prev->msie_refresh, 0);
  3057.     ngx_conf_merge_value(conf->log_not_found, prev->log_not_found, 1);
  3058.     ngx_conf_merge_value(conf->log_subrequest, prev->log_subrequest, 0);
  3059.     ngx_conf_merge_value(conf->recursive_error_pages,
  3060.                               prev->recursive_error_pages, 0);
  3061.     ngx_conf_merge_value(conf->chunked_transfer_encoding,
  3062.                               prev->chunked_transfer_encoding, 1);
  3063.     ngx_conf_merge_value(conf->etag, prev->etag, 1);

  3064.     ngx_conf_merge_uint_value(conf->server_tokens, prev->server_tokens,
  3065.                               NGX_HTTP_SERVER_TOKENS_ON);

  3066.     ngx_conf_merge_ptr_value(conf->early_hints, prev->early_hints, NULL);

  3067.     ngx_conf_merge_ptr_value(conf->open_file_cache,
  3068.                               prev->open_file_cache, NULL);

  3069.     ngx_conf_merge_sec_value(conf->open_file_cache_valid,
  3070.                               prev->open_file_cache_valid, 60);

  3071.     ngx_conf_merge_uint_value(conf->open_file_cache_min_uses,
  3072.                               prev->open_file_cache_min_uses, 1);

  3073.     ngx_conf_merge_sec_value(conf->open_file_cache_errors,
  3074.                               prev->open_file_cache_errors, 0);

  3075.     ngx_conf_merge_sec_value(conf->open_file_cache_events,
  3076.                               prev->open_file_cache_events, 0);
  3077. #if (NGX_HTTP_GZIP)

  3078.     ngx_conf_merge_value(conf->gzip_vary, prev->gzip_vary, 0);
  3079.     ngx_conf_merge_uint_value(conf->gzip_http_version, prev->gzip_http_version,
  3080.                               NGX_HTTP_VERSION_11);
  3081.     ngx_conf_merge_bitmask_value(conf->gzip_proxied, prev->gzip_proxied,
  3082.                               (NGX_CONF_BITMASK_SET|NGX_HTTP_GZIP_PROXIED_OFF));

  3083. #if (NGX_PCRE)
  3084.     ngx_conf_merge_ptr_value(conf->gzip_disable, prev->gzip_disable, NULL);
  3085. #endif

  3086.     if (conf->gzip_disable_msie6 == 3) {
  3087.         conf->gzip_disable_msie6 =
  3088.             (prev->gzip_disable_msie6 == 3) ? 0 : prev->gzip_disable_msie6;
  3089.     }

  3090. #if (NGX_HTTP_DEGRADATION)

  3091.     if (conf->gzip_disable_degradation == 3) {
  3092.         conf->gzip_disable_degradation =
  3093.             (prev->gzip_disable_degradation == 3) ?
  3094.                  0 : prev->gzip_disable_degradation;
  3095.     }

  3096. #endif
  3097. #endif

  3098. #if (NGX_HAVE_OPENAT)
  3099.     ngx_conf_merge_uint_value(conf->disable_symlinks, prev->disable_symlinks,
  3100.                               NGX_DISABLE_SYMLINKS_OFF);
  3101.     ngx_conf_merge_ptr_value(conf->disable_symlinks_from,
  3102.                              prev->disable_symlinks_from, NULL);
  3103. #endif

  3104.     return NGX_CONF_OK;
  3105. }


  3106. static char *
  3107. ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  3108. {
  3109.     ngx_http_core_srv_conf_t *cscf = conf;

  3110.     ngx_str_t              *value, size;
  3111.     ngx_url_t               u;
  3112.     ngx_uint_t              n, i, backlog;
  3113.     ngx_http_listen_opt_t   lsopt;

  3114.     cscf->listen = 1;

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

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

  3117.     u.url = value[1];
  3118.     u.listen = 1;
  3119.     u.default_port = 80;

  3120.     if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
  3121.         if (u.err) {
  3122.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  3123.                                "%s in \"%V\" of the \"listen\" directive",
  3124.                                u.err, &u.url);
  3125.         }

  3126.         return NGX_CONF_ERROR;
  3127.     }

  3128.     ngx_memzero(&lsopt, sizeof(ngx_http_listen_opt_t));

  3129.     lsopt.backlog = NGX_LISTEN_BACKLOG;
  3130.     lsopt.type = SOCK_STREAM;
  3131.     lsopt.rcvbuf = -1;
  3132.     lsopt.sndbuf = -1;
  3133. #if (NGX_HAVE_SETFIB)
  3134.     lsopt.setfib = -1;
  3135. #endif
  3136. #if (NGX_HAVE_TCP_FASTOPEN)
  3137.     lsopt.fastopen = -1;
  3138. #endif
  3139. #if (NGX_HAVE_INET6)
  3140.     lsopt.ipv6only = 1;
  3141. #endif

  3142.     backlog = 0;

  3143.     for (n = 2; n < cf->args->nelts; n++) {

  3144.         if (ngx_strcmp(value[n].data, "default_server") == 0
  3145.             || ngx_strcmp(value[n].data, "default") == 0)
  3146.         {
  3147.             lsopt.default_server = 1;
  3148.             continue;
  3149.         }

  3150.         if (ngx_strcmp(value[n].data, "bind") == 0) {
  3151.             lsopt.set = 1;
  3152.             lsopt.bind = 1;
  3153.             continue;
  3154.         }

  3155. #if (NGX_HAVE_SETFIB)
  3156.         if (ngx_strncmp(value[n].data, "setfib=", 7) == 0) {
  3157.             lsopt.setfib = ngx_atoi(value[n].data + 7, value[n].len - 7);
  3158.             lsopt.set = 1;
  3159.             lsopt.bind = 1;

  3160.             if (lsopt.setfib == NGX_ERROR) {
  3161.                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  3162.                                    "invalid setfib \"%V\"", &value[n]);
  3163.                 return NGX_CONF_ERROR;
  3164.             }

  3165.             continue;
  3166.         }
  3167. #endif

  3168. #if (NGX_HAVE_TCP_FASTOPEN)
  3169.         if (ngx_strncmp(value[n].data, "fastopen=", 9) == 0) {
  3170.             lsopt.fastopen = ngx_atoi(value[n].data + 9, value[n].len - 9);
  3171.             lsopt.set = 1;
  3172.             lsopt.bind = 1;

  3173.             if (lsopt.fastopen == NGX_ERROR) {
  3174.                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  3175.                                    "invalid fastopen \"%V\"", &value[n]);
  3176.                 return NGX_CONF_ERROR;
  3177.             }

  3178.             continue;
  3179.         }
  3180. #endif

  3181.         if (ngx_strncmp(value[n].data, "backlog=", 8) == 0) {
  3182.             lsopt.backlog = ngx_atoi(value[n].data + 8, value[n].len - 8);
  3183.             lsopt.set = 1;
  3184.             lsopt.bind = 1;

  3185.             if (lsopt.backlog == NGX_ERROR || lsopt.backlog == 0) {
  3186.                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  3187.                                    "invalid backlog \"%V\"", &value[n]);
  3188.                 return NGX_CONF_ERROR;
  3189.             }

  3190.             backlog = 1;

  3191.             continue;
  3192.         }

  3193.         if (ngx_strncmp(value[n].data, "rcvbuf=", 7) == 0) {
  3194.             size.len = value[n].len - 7;
  3195.             size.data = value[n].data + 7;

  3196.             lsopt.rcvbuf = ngx_parse_size(&size);
  3197.             lsopt.set = 1;
  3198.             lsopt.bind = 1;

  3199.             if (lsopt.rcvbuf == NGX_ERROR) {
  3200.                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  3201.                                    "invalid rcvbuf \"%V\"", &value[n]);
  3202.                 return NGX_CONF_ERROR;
  3203.             }

  3204.             continue;
  3205.         }

  3206.         if (ngx_strncmp(value[n].data, "sndbuf=", 7) == 0) {
  3207.             size.len = value[n].len - 7;
  3208.             size.data = value[n].data + 7;

  3209.             lsopt.sndbuf = ngx_parse_size(&size);
  3210.             lsopt.set = 1;
  3211.             lsopt.bind = 1;

  3212.             if (lsopt.sndbuf == NGX_ERROR) {
  3213.                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  3214.                                    "invalid sndbuf \"%V\"", &value[n]);
  3215.                 return NGX_CONF_ERROR;
  3216.             }

  3217.             continue;
  3218.         }

  3219.         if (ngx_strncmp(value[n].data, "accept_filter=", 14) == 0) {
  3220. #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
  3221.             lsopt.accept_filter = (char *) &value[n].data[14];
  3222.             lsopt.set = 1;
  3223.             lsopt.bind = 1;
  3224. #else
  3225.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  3226.                                "accept filters \"%V\" are not supported "
  3227.                                "on this platform, ignored",
  3228.                                &value[n]);
  3229. #endif
  3230.             continue;
  3231.         }

  3232.         if (ngx_strcmp(value[n].data, "deferred") == 0) {
  3233. #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
  3234.             lsopt.deferred_accept = 1;
  3235.             lsopt.set = 1;
  3236.             lsopt.bind = 1;
  3237. #else
  3238.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  3239.                                "the deferred accept is not supported "
  3240.                                "on this platform, ignored");
  3241. #endif
  3242.             continue;
  3243.         }

  3244.         if (ngx_strncmp(value[n].data, "ipv6only=o", 10) == 0) {
  3245. #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
  3246.             if (ngx_strcmp(&value[n].data[10], "n") == 0) {
  3247.                 lsopt.ipv6only = 1;

  3248.             } else if (ngx_strcmp(&value[n].data[10], "ff") == 0) {
  3249.                 lsopt.ipv6only = 0;

  3250.             } else {
  3251.                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  3252.                                    "invalid ipv6only flags \"%s\"",
  3253.                                    &value[n].data[9]);
  3254.                 return NGX_CONF_ERROR;
  3255.             }

  3256.             lsopt.set = 1;
  3257.             lsopt.bind = 1;

  3258.             continue;
  3259. #else
  3260.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  3261.                                "ipv6only is not supported "
  3262.                                "on this platform");
  3263.             return NGX_CONF_ERROR;
  3264. #endif
  3265.         }

  3266.         if (ngx_strcmp(value[n].data, "reuseport") == 0) {
  3267. #if (NGX_HAVE_REUSEPORT)
  3268.             lsopt.reuseport = 1;
  3269.             lsopt.set = 1;
  3270.             lsopt.bind = 1;
  3271. #else
  3272.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  3273.                                "reuseport is not supported "
  3274.                                "on this platform, ignored");
  3275. #endif
  3276.             continue;
  3277.         }

  3278.         if (ngx_strcmp(value[n].data, "multipath") == 0) {
  3279. #ifdef IPPROTO_MPTCP
  3280.             lsopt.protocol = IPPROTO_MPTCP;
  3281.             lsopt.set = 1;
  3282.             lsopt.bind = 1;
  3283. #else
  3284.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  3285.                                "multipath is not supported "
  3286.                                "on this platform, ignored");
  3287. #endif
  3288.             continue;
  3289.         }

  3290.         if (ngx_strcmp(value[n].data, "ssl") == 0) {
  3291. #if (NGX_HTTP_SSL)
  3292.             lsopt.ssl = 1;
  3293.             continue;
  3294. #else
  3295.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  3296.                                "the \"ssl\" parameter requires "
  3297.                                "ngx_http_ssl_module");
  3298.             return NGX_CONF_ERROR;
  3299. #endif
  3300.         }

  3301.         if (ngx_strcmp(value[n].data, "http2") == 0) {
  3302. #if (NGX_HTTP_V2)
  3303.             ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
  3304.                                "the \"listen ... http2\" directive "
  3305.                                "is deprecated, use "
  3306.                                "the \"http2\" directive instead");

  3307.             lsopt.http2 = 1;
  3308.             continue;
  3309. #else
  3310.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  3311.                                "the \"http2\" parameter requires "
  3312.                                "ngx_http_v2_module");
  3313.             return NGX_CONF_ERROR;
  3314. #endif
  3315.         }

  3316.         if (ngx_strcmp(value[n].data, "quic") == 0) {
  3317. #if (NGX_HTTP_V3)
  3318.             lsopt.quic = 1;
  3319.             lsopt.type = SOCK_DGRAM;
  3320.             continue;
  3321. #else
  3322.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  3323.                                "the \"quic\" parameter requires "
  3324.                                "ngx_http_v3_module");
  3325.             return NGX_CONF_ERROR;
  3326. #endif
  3327.         }

  3328.         if (ngx_strncmp(value[n].data, "so_keepalive=", 13) == 0) {

  3329.             if (ngx_strcmp(&value[n].data[13], "on") == 0) {
  3330.                 lsopt.so_keepalive = 1;

  3331.             } else if (ngx_strcmp(&value[n].data[13], "off") == 0) {
  3332.                 lsopt.so_keepalive = 2;

  3333.             } else {

  3334. #if (NGX_HAVE_KEEPALIVE_TUNABLE)
  3335.                 u_char     *p, *end;
  3336.                 ngx_str_t   s;

  3337.                 end = value[n].data + value[n].len;
  3338.                 s.data = value[n].data + 13;

  3339.                 p = ngx_strlchr(s.data, end, ':');
  3340.                 if (p == NULL) {
  3341.                     p = end;
  3342.                 }

  3343.                 if (p > s.data) {
  3344.                     s.len = p - s.data;

  3345.                     lsopt.tcp_keepidle = ngx_parse_time(&s, 1);
  3346.                     if (lsopt.tcp_keepidle == (time_t) NGX_ERROR) {
  3347.                         goto invalid_so_keepalive;
  3348.                     }
  3349.                 }

  3350.                 s.data = (p < end) ? (p + 1) : end;

  3351.                 p = ngx_strlchr(s.data, end, ':');
  3352.                 if (p == NULL) {
  3353.                     p = end;
  3354.                 }

  3355.                 if (p > s.data) {
  3356.                     s.len = p - s.data;

  3357.                     lsopt.tcp_keepintvl = ngx_parse_time(&s, 1);
  3358.                     if (lsopt.tcp_keepintvl == (time_t) NGX_ERROR) {
  3359.                         goto invalid_so_keepalive;
  3360.                     }
  3361.                 }

  3362.                 s.data = (p < end) ? (p + 1) : end;

  3363.                 if (s.data < end) {
  3364.                     s.len = end - s.data;

  3365.                     lsopt.tcp_keepcnt = ngx_atoi(s.data, s.len);
  3366.                     if (lsopt.tcp_keepcnt == NGX_ERROR) {
  3367.                         goto invalid_so_keepalive;
  3368.                     }
  3369.                 }

  3370.                 if (lsopt.tcp_keepidle == 0 && lsopt.tcp_keepintvl == 0
  3371.                     && lsopt.tcp_keepcnt == 0)
  3372.                 {
  3373.                     goto invalid_so_keepalive;
  3374.                 }

  3375.                 lsopt.so_keepalive = 1;

  3376. #else

  3377.                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  3378.                                    "the \"so_keepalive\" parameter accepts "
  3379.                                    "only \"on\" or \"off\" on this platform");
  3380.                 return NGX_CONF_ERROR;

  3381. #endif
  3382.             }

  3383.             lsopt.set = 1;
  3384.             lsopt.bind = 1;

  3385.             continue;

  3386. #if (NGX_HAVE_KEEPALIVE_TUNABLE)
  3387.         invalid_so_keepalive:

  3388.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  3389.                                "invalid so_keepalive value: \"%s\"",
  3390.                                &value[n].data[13]);
  3391.             return NGX_CONF_ERROR;
  3392. #endif
  3393.         }

  3394.         if (ngx_strcmp(value[n].data, "proxy_protocol") == 0) {
  3395.             lsopt.proxy_protocol = 1;
  3396.             continue;
  3397.         }

  3398.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  3399.                            "invalid parameter \"%V\"", &value[n]);
  3400.         return NGX_CONF_ERROR;
  3401.     }

  3402.     if (lsopt.quic) {
  3403. #if (NGX_HAVE_TCP_FASTOPEN)
  3404.         if (lsopt.fastopen != -1) {
  3405.             return "\"fastopen\" parameter is incompatible with \"quic\"";
  3406.         }
  3407. #endif

  3408.         if (backlog) {
  3409.             return "\"backlog\" parameter is incompatible with \"quic\"";
  3410.         }

  3411. #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
  3412.         if (lsopt.accept_filter) {
  3413.             return "\"accept_filter\" parameter is incompatible with \"quic\"";
  3414.         }
  3415. #endif

  3416. #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
  3417.         if (lsopt.deferred_accept) {
  3418.             return "\"deferred\" parameter is incompatible with \"quic\"";
  3419.         }
  3420. #endif

  3421. #ifdef IPPROTO_MPTCP
  3422.         if (lsopt.protocol == IPPROTO_MPTCP) {
  3423.              return "\"multipath\" parameter is incompatible with \"quic\"";
  3424.         }
  3425. #endif

  3426. #if (NGX_HTTP_SSL)
  3427.         if (lsopt.ssl) {
  3428.             return "\"ssl\" parameter is incompatible with \"quic\"";
  3429.         }
  3430. #endif

  3431. #if (NGX_HTTP_V2)
  3432.         if (lsopt.http2) {
  3433.             return "\"http2\" parameter is incompatible with \"quic\"";
  3434.         }
  3435. #endif

  3436.         if (lsopt.so_keepalive) {
  3437.             return "\"so_keepalive\" parameter is incompatible with \"quic\"";
  3438.         }

  3439.         if (lsopt.proxy_protocol) {
  3440.             return "\"proxy_protocol\" parameter is incompatible with \"quic\"";
  3441.         }
  3442.     }

  3443.     for (n = 0; n < u.naddrs; n++) {

  3444.         for (i = 0; i < n; i++) {
  3445.             if (ngx_cmp_sockaddr(u.addrs[n].sockaddr, u.addrs[n].socklen,
  3446.                                  u.addrs[i].sockaddr, u.addrs[i].socklen, 1)
  3447.                 == NGX_OK)
  3448.             {
  3449.                 goto next;
  3450.             }
  3451.         }

  3452.         lsopt.sockaddr = u.addrs[n].sockaddr;
  3453.         lsopt.socklen = u.addrs[n].socklen;
  3454.         lsopt.addr_text = u.addrs[n].name;
  3455.         lsopt.wildcard = ngx_inet_wildcard(lsopt.sockaddr);

  3456.         if (ngx_http_add_listen(cf, cscf, &lsopt) != NGX_OK) {
  3457.             return NGX_CONF_ERROR;
  3458.         }

  3459.     next:
  3460.         continue;
  3461.     }

  3462.     return NGX_CONF_OK;
  3463. }


  3464. static char *
  3465. ngx_http_core_server_name(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  3466. {
  3467.     ngx_http_core_srv_conf_t *cscf = conf;

  3468.     u_char                   ch;
  3469.     ngx_str_t               *value;
  3470.     ngx_uint_t               i;
  3471.     ngx_http_server_name_t  *sn;

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

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

  3474.         ch = value[i].data[0];

  3475.         if ((ch == '*' && (value[i].len < 3 || value[i].data[1] != '.'))
  3476.             || (ch == '.' && value[i].len < 2))
  3477.         {
  3478.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  3479.                                "server name \"%V\" is invalid", &value[i]);
  3480.             return NGX_CONF_ERROR;
  3481.         }

  3482.         if (ngx_strchr(value[i].data, '/')) {
  3483.             ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
  3484.                                "server name \"%V\" has suspicious symbols",
  3485.                                &value[i]);
  3486.         }

  3487.         sn = ngx_array_push(&cscf->server_names);
  3488.         if (sn == NULL) {
  3489.             return NGX_CONF_ERROR;
  3490.         }

  3491. #if (NGX_PCRE)
  3492.         sn->regex = NULL;
  3493. #endif
  3494.         sn->server = cscf;

  3495.         if (ngx_strcasecmp(value[i].data, (u_char *) "$hostname") == 0) {
  3496.             sn->name = cf->cycle->hostname;

  3497.         } else {
  3498.             sn->name = value[i];
  3499.         }

  3500.         if (value[i].data[0] != '~') {
  3501.             ngx_strlow(sn->name.data, sn->name.data, sn->name.len);
  3502.             continue;
  3503.         }

  3504. #if (NGX_PCRE)
  3505.         {
  3506.         u_char               *p;
  3507.         ngx_regex_compile_t   rc;
  3508.         u_char                errstr[NGX_MAX_CONF_ERRSTR];

  3509.         if (value[i].len == 1) {
  3510.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  3511.                                "empty regex in server name \"%V\"", &value[i]);
  3512.             return NGX_CONF_ERROR;
  3513.         }

  3514.         value[i].len--;
  3515.         value[i].data++;

  3516.         ngx_memzero(&rc, sizeof(ngx_regex_compile_t));

  3517.         rc.pattern = value[i];
  3518.         rc.err.len = NGX_MAX_CONF_ERRSTR;
  3519.         rc.err.data = errstr;

  3520.         for (p = value[i].data; p < value[i].data + value[i].len; p++) {
  3521.             if (*p >= 'A' && *p <= 'Z') {
  3522.                 rc.options = NGX_REGEX_CASELESS;
  3523.                 break;
  3524.             }
  3525.         }

  3526.         sn->regex = ngx_http_regex_compile(cf, &rc);
  3527.         if (sn->regex == NULL) {
  3528.             return NGX_CONF_ERROR;
  3529.         }

  3530.         sn->name = value[i];
  3531.         cscf->captures = (rc.captures > 0);
  3532.         }
  3533. #else
  3534.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  3535.                            "using regex \"%V\" "
  3536.                            "requires PCRE library", &value[i]);

  3537.         return NGX_CONF_ERROR;
  3538. #endif
  3539.     }

  3540.     return NGX_CONF_OK;
  3541. }


  3542. static char *
  3543. ngx_http_core_root(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  3544. {
  3545.     ngx_http_core_loc_conf_t *clcf = conf;

  3546.     ngx_str_t                  *value;
  3547.     ngx_int_t                   alias;
  3548.     ngx_uint_t                  n;
  3549.     ngx_http_script_compile_t   sc;

  3550.     alias = (cmd->name.len == sizeof("alias") - 1) ? 1 : 0;

  3551.     if (clcf->root.data) {

  3552.         if ((clcf->alias != 0) == alias) {
  3553.             return "is duplicate";
  3554.         }

  3555.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  3556.                            "\"%V\" directive is duplicate, "
  3557.                            "\"%s\" directive was specified earlier",
  3558.                            &cmd->name, clcf->alias ? "alias" : "root");

  3559.         return NGX_CONF_ERROR;
  3560.     }

  3561.     if (clcf->named && alias) {
  3562.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  3563.                            "the \"alias\" directive cannot be used "
  3564.                            "inside the named location");

  3565.         return NGX_CONF_ERROR;
  3566.     }

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

  3568.     if (ngx_strstr(value[1].data, "$document_root")
  3569.         || ngx_strstr(value[1].data, "${document_root}"))
  3570.     {
  3571.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  3572.                            "the $document_root variable cannot be used "
  3573.                            "in the \"%V\" directive",
  3574.                            &cmd->name);

  3575.         return NGX_CONF_ERROR;
  3576.     }

  3577.     if (ngx_strstr(value[1].data, "$realpath_root")
  3578.         || ngx_strstr(value[1].data, "${realpath_root}"))
  3579.     {
  3580.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  3581.                            "the $realpath_root variable cannot be used "
  3582.                            "in the \"%V\" directive",
  3583.                            &cmd->name);

  3584.         return NGX_CONF_ERROR;
  3585.     }

  3586.     clcf->alias = alias ? clcf->name.len : 0;
  3587.     clcf->root = value[1];

  3588.     if (!alias && clcf->root.len > 0
  3589.         && clcf->root.data[clcf->root.len - 1] == '/')
  3590.     {
  3591.         clcf->root.len--;
  3592.     }

  3593.     if (clcf->root.data[0] != '$') {
  3594.         if (ngx_conf_full_name(cf->cycle, &clcf->root, 0) != NGX_OK) {
  3595.             return NGX_CONF_ERROR;
  3596.         }
  3597.     }

  3598.     n = ngx_http_script_variables_count(&clcf->root);

  3599.     ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
  3600.     sc.variables = n;

  3601. #if (NGX_PCRE)
  3602.     if (alias && clcf->regex) {
  3603.         clcf->alias = NGX_MAX_SIZE_T_VALUE;
  3604.         n = 1;
  3605.     }
  3606. #endif

  3607.     if (n) {
  3608.         sc.cf = cf;
  3609.         sc.source = &clcf->root;
  3610.         sc.lengths = &clcf->root_lengths;
  3611.         sc.values = &clcf->root_values;
  3612.         sc.complete_lengths = 1;
  3613.         sc.complete_values = 1;

  3614.         if (ngx_http_script_compile(&sc) != NGX_OK) {
  3615.             return NGX_CONF_ERROR;
  3616.         }
  3617.     }

  3618.     return NGX_CONF_OK;
  3619. }


  3620. static ngx_http_method_name_t  ngx_methods_names[] = {
  3621.     { (u_char *) "GET",       (uint32_t) ~NGX_HTTP_GET },
  3622.     { (u_char *) "HEAD",      (uint32_t) ~NGX_HTTP_HEAD },
  3623.     { (u_char *) "POST",      (uint32_t) ~NGX_HTTP_POST },
  3624.     { (u_char *) "PUT",       (uint32_t) ~NGX_HTTP_PUT },
  3625.     { (u_char *) "DELETE",    (uint32_t) ~NGX_HTTP_DELETE },
  3626.     { (u_char *) "MKCOL",     (uint32_t) ~NGX_HTTP_MKCOL },
  3627.     { (u_char *) "COPY",      (uint32_t) ~NGX_HTTP_COPY },
  3628.     { (u_char *) "MOVE",      (uint32_t) ~NGX_HTTP_MOVE },
  3629.     { (u_char *) "OPTIONS",   (uint32_t) ~NGX_HTTP_OPTIONS },
  3630.     { (u_char *) "PROPFIND",  (uint32_t) ~NGX_HTTP_PROPFIND },
  3631.     { (u_char *) "PROPPATCH", (uint32_t) ~NGX_HTTP_PROPPATCH },
  3632.     { (u_char *) "LOCK",      (uint32_t) ~NGX_HTTP_LOCK },
  3633.     { (u_char *) "UNLOCK",    (uint32_t) ~NGX_HTTP_UNLOCK },
  3634.     { (u_char *) "PATCH",     (uint32_t) ~NGX_HTTP_PATCH },
  3635.     { NULL, 0 }
  3636. };


  3637. static char *
  3638. ngx_http_core_limit_except(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  3639. {
  3640.     ngx_http_core_loc_conf_t *pclcf = conf;

  3641.     char                      *rv;
  3642.     void                      *mconf;
  3643.     ngx_str_t                 *value;
  3644.     ngx_uint_t                 i;
  3645.     ngx_conf_t                 save;
  3646.     ngx_http_module_t         *module;
  3647.     ngx_http_conf_ctx_t       *ctx, *pctx;
  3648.     ngx_http_method_name_t    *name;
  3649.     ngx_http_core_loc_conf_t  *clcf;

  3650.     if (pclcf->limit_except) {
  3651.         return "is duplicate";
  3652.     }

  3653.     pclcf->limit_except = 0xffffffff;

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

  3655.     for (i = 1; i < cf->args->nelts; i++) {
  3656.         for (name = ngx_methods_names; name->name; name++) {

  3657.             if (ngx_strcasecmp(value[i].data, name->name) == 0) {
  3658.                 pclcf->limit_except &= name->method;
  3659.                 goto next;
  3660.             }
  3661.         }

  3662.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  3663.                            "invalid method \"%V\"", &value[i]);
  3664.         return NGX_CONF_ERROR;

  3665.     next:
  3666.         continue;
  3667.     }

  3668.     if (!(pclcf->limit_except & NGX_HTTP_GET)) {
  3669.         pclcf->limit_except &= (uint32_t) ~NGX_HTTP_HEAD;
  3670.     }

  3671.     ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
  3672.     if (ctx == NULL) {
  3673.         return NGX_CONF_ERROR;
  3674.     }

  3675.     pctx = cf->ctx;
  3676.     ctx->main_conf = pctx->main_conf;
  3677.     ctx->srv_conf = pctx->srv_conf;

  3678.     ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
  3679.     if (ctx->loc_conf == NULL) {
  3680.         return NGX_CONF_ERROR;
  3681.     }

  3682.     for (i = 0; cf->cycle->modules[i]; i++) {
  3683.         if (cf->cycle->modules[i]->type != NGX_HTTP_MODULE) {
  3684.             continue;
  3685.         }

  3686.         module = cf->cycle->modules[i]->ctx;

  3687.         if (module->create_loc_conf) {

  3688.             mconf = module->create_loc_conf(cf);
  3689.             if (mconf == NULL) {
  3690.                 return NGX_CONF_ERROR;
  3691.             }

  3692.             ctx->loc_conf[cf->cycle->modules[i]->ctx_index] = mconf;
  3693.         }
  3694.     }


  3695.     clcf = ctx->loc_conf[ngx_http_core_module.ctx_index];
  3696.     pclcf->limit_except_loc_conf = ctx->loc_conf;
  3697.     clcf->loc_conf = ctx->loc_conf;
  3698.     clcf->name = pclcf->name;
  3699.     clcf->noname = 1;
  3700.     clcf->lmt_excpt = 1;

  3701.     if (ngx_http_add_location(cf, &pclcf->locations, clcf) != NGX_OK) {
  3702.         return NGX_CONF_ERROR;
  3703.     }

  3704.     save = *cf;
  3705.     cf->ctx = ctx;
  3706.     cf->cmd_type = NGX_HTTP_LMT_CONF;

  3707.     rv = ngx_conf_parse(cf, NULL);

  3708.     *cf = save;

  3709.     return rv;
  3710. }


  3711. static char *
  3712. ngx_http_core_set_aio(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  3713. {
  3714.     ngx_http_core_loc_conf_t *clcf = conf;

  3715.     ngx_str_t  *value;

  3716.     if (clcf->aio != NGX_CONF_UNSET) {
  3717.         return "is duplicate";
  3718.     }

  3719. #if (NGX_THREADS)
  3720.     clcf->thread_pool = NULL;
  3721.     clcf->thread_pool_value = NULL;
  3722. #endif

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

  3724.     if (ngx_strcmp(value[1].data, "off") == 0) {
  3725.         clcf->aio = NGX_HTTP_AIO_OFF;
  3726.         return NGX_CONF_OK;
  3727.     }

  3728.     if (ngx_strcmp(value[1].data, "on") == 0) {
  3729. #if (NGX_HAVE_FILE_AIO)
  3730.         clcf->aio = NGX_HTTP_AIO_ON;
  3731.         return NGX_CONF_OK;
  3732. #else
  3733.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  3734.                            "\"aio on\" "
  3735.                            "is unsupported on this platform");
  3736.         return NGX_CONF_ERROR;
  3737. #endif
  3738.     }

  3739.     if (ngx_strncmp(value[1].data, "threads", 7) == 0
  3740.         && (value[1].len == 7 || value[1].data[7] == '='))
  3741.     {
  3742. #if (NGX_THREADS)
  3743.         ngx_str_t                          name;
  3744.         ngx_thread_pool_t                 *tp;
  3745.         ngx_http_complex_value_t           cv;
  3746.         ngx_http_compile_complex_value_t   ccv;

  3747.         clcf->aio = NGX_HTTP_AIO_THREADS;

  3748.         if (value[1].len >= 8) {
  3749.             name.len = value[1].len - 8;
  3750.             name.data = value[1].data + 8;

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

  3752.             ccv.cf = cf;
  3753.             ccv.value = &name;
  3754.             ccv.complex_value = &cv;

  3755.             if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
  3756.                 return NGX_CONF_ERROR;
  3757.             }

  3758.             if (cv.lengths != NULL) {
  3759.                 clcf->thread_pool_value = ngx_palloc(cf->pool,
  3760.                                     sizeof(ngx_http_complex_value_t));
  3761.                 if (clcf->thread_pool_value == NULL) {
  3762.                     return NGX_CONF_ERROR;
  3763.                 }

  3764.                 *clcf->thread_pool_value = cv;

  3765.                 return NGX_CONF_OK;
  3766.             }

  3767.             tp = ngx_thread_pool_add(cf, &name);

  3768.         } else {
  3769.             tp = ngx_thread_pool_add(cf, NULL);
  3770.         }

  3771.         if (tp == NULL) {
  3772.             return NGX_CONF_ERROR;
  3773.         }

  3774.         clcf->thread_pool = tp;

  3775.         return NGX_CONF_OK;
  3776. #else
  3777.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  3778.                            "\"aio threads\" "
  3779.                            "is unsupported on this platform");
  3780.         return NGX_CONF_ERROR;
  3781. #endif
  3782.     }

  3783.     return "invalid value";
  3784. }


  3785. static char *
  3786. ngx_http_core_directio(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  3787. {
  3788.     ngx_http_core_loc_conf_t *clcf = conf;

  3789.     ngx_str_t  *value;

  3790.     if (clcf->directio != NGX_CONF_UNSET) {
  3791.         return "is duplicate";
  3792.     }

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

  3794.     if (ngx_strcmp(value[1].data, "off") == 0) {
  3795.         clcf->directio = NGX_OPEN_FILE_DIRECTIO_OFF;
  3796.         return NGX_CONF_OK;
  3797.     }

  3798.     clcf->directio = ngx_parse_offset(&value[1]);
  3799.     if (clcf->directio == (off_t) NGX_ERROR) {
  3800.         return "invalid value";
  3801.     }

  3802.     return NGX_CONF_OK;
  3803. }


  3804. static char *
  3805. ngx_http_core_error_page(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  3806. {
  3807.     ngx_http_core_loc_conf_t *clcf = conf;

  3808.     u_char                            *p;
  3809.     ngx_int_t                          overwrite;
  3810.     ngx_str_t                         *value, uri, args;
  3811.     ngx_uint_t                         i, n;
  3812.     ngx_http_err_page_t               *err;
  3813.     ngx_http_complex_value_t           cv;
  3814.     ngx_http_compile_complex_value_t   ccv;

  3815.     if (clcf->error_pages == NULL) {
  3816.         clcf->error_pages = ngx_array_create(cf->pool, 4,
  3817.                                              sizeof(ngx_http_err_page_t));
  3818.         if (clcf->error_pages == NULL) {
  3819.             return NGX_CONF_ERROR;
  3820.         }
  3821.     }

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

  3823.     i = cf->args->nelts - 2;

  3824.     if (value[i].data[0] == '=') {
  3825.         if (i == 1) {
  3826.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  3827.                                "invalid value \"%V\"", &value[i]);
  3828.             return NGX_CONF_ERROR;
  3829.         }

  3830.         if (value[i].len > 1) {
  3831.             overwrite = ngx_atoi(&value[i].data[1], value[i].len - 1);

  3832.             if (overwrite == NGX_ERROR) {
  3833.                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  3834.                                    "invalid value \"%V\"", &value[i]);
  3835.                 return NGX_CONF_ERROR;
  3836.             }

  3837.         } else {
  3838.             overwrite = 0;
  3839.         }

  3840.         n = 2;

  3841.     } else {
  3842.         overwrite = -1;
  3843.         n = 1;
  3844.     }

  3845.     uri = value[cf->args->nelts - 1];

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

  3847.     ccv.cf = cf;
  3848.     ccv.value = &uri;
  3849.     ccv.complex_value = &cv;

  3850.     if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
  3851.         return NGX_CONF_ERROR;
  3852.     }

  3853.     ngx_str_null(&args);

  3854.     if (cv.lengths == NULL && uri.len && uri.data[0] == '/') {
  3855.         p = (u_char *) ngx_strchr(uri.data, '?');

  3856.         if (p) {
  3857.             cv.value.len = p - uri.data;
  3858.             cv.value.data = uri.data;
  3859.             p++;
  3860.             args.len = (uri.data + uri.len) - p;
  3861.             args.data = p;
  3862.         }
  3863.     }

  3864.     for (i = 1; i < cf->args->nelts - n; i++) {
  3865.         err = ngx_array_push(clcf->error_pages);
  3866.         if (err == NULL) {
  3867.             return NGX_CONF_ERROR;
  3868.         }

  3869.         err->status = ngx_atoi(value[i].data, value[i].len);

  3870.         if (err->status == NGX_ERROR || err->status == 499) {
  3871.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  3872.                                "invalid value \"%V\"", &value[i]);
  3873.             return NGX_CONF_ERROR;
  3874.         }

  3875.         if (err->status < 300 || err->status > 599) {
  3876.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  3877.                                "value \"%V\" must be between 300 and 599",
  3878.                                &value[i]);
  3879.             return NGX_CONF_ERROR;
  3880.         }

  3881.         err->overwrite = overwrite;

  3882.         if (overwrite == -1) {
  3883.             switch (err->status) {
  3884.                 case NGX_HTTP_TO_HTTPS:
  3885.                 case NGX_HTTPS_CERT_ERROR:
  3886.                 case NGX_HTTPS_NO_CERT:
  3887.                 case NGX_HTTP_REQUEST_HEADER_TOO_LARGE:
  3888.                     err->overwrite = NGX_HTTP_BAD_REQUEST;
  3889.             }
  3890.         }

  3891.         err->value = cv;
  3892.         err->args = args;
  3893.     }

  3894.     return NGX_CONF_OK;
  3895. }


  3896. static char *
  3897. ngx_http_core_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  3898. {
  3899.     ngx_http_core_loc_conf_t *clcf = conf;

  3900.     time_t       inactive;
  3901.     ngx_str_t   *value, s;
  3902.     ngx_int_t    max;
  3903.     ngx_uint_t   i;

  3904.     if (clcf->open_file_cache != NGX_CONF_UNSET_PTR) {
  3905.         return "is duplicate";
  3906.     }

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

  3908.     max = 0;
  3909.     inactive = 60;

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

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

  3912.             max = ngx_atoi(value[i].data + 4, value[i].len - 4);
  3913.             if (max <= 0) {
  3914.                 goto failed;
  3915.             }

  3916.             continue;
  3917.         }

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

  3919.             s.len = value[i].len - 9;
  3920.             s.data = value[i].data + 9;

  3921.             inactive = ngx_parse_time(&s, 1);
  3922.             if (inactive == (time_t) NGX_ERROR) {
  3923.                 goto failed;
  3924.             }

  3925.             continue;
  3926.         }

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

  3928.             clcf->open_file_cache = NULL;

  3929.             continue;
  3930.         }

  3931.     failed:

  3932.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  3933.                            "invalid \"open_file_cache\" parameter \"%V\"",
  3934.                            &value[i]);
  3935.         return NGX_CONF_ERROR;
  3936.     }

  3937.     if (clcf->open_file_cache == NULL) {
  3938.         return NGX_CONF_OK;
  3939.     }

  3940.     if (max == 0) {
  3941.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  3942.                         "\"open_file_cache\" must have the \"max\" parameter");
  3943.         return NGX_CONF_ERROR;
  3944.     }

  3945.     clcf->open_file_cache = ngx_open_file_cache_init(cf->pool, max, inactive);
  3946.     if (clcf->open_file_cache) {
  3947.         return NGX_CONF_OK;
  3948.     }

  3949.     return NGX_CONF_ERROR;
  3950. }


  3951. static char *
  3952. ngx_http_core_error_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  3953. {
  3954.     ngx_http_core_loc_conf_t *clcf = conf;

  3955.     return ngx_log_set_log(cf, &clcf->error_log);
  3956. }


  3957. static char *
  3958. ngx_http_core_keepalive(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  3959. {
  3960.     ngx_http_core_loc_conf_t *clcf = conf;

  3961.     ngx_str_t  *value;

  3962.     if (clcf->keepalive_timeout != NGX_CONF_UNSET_MSEC) {
  3963.         return "is duplicate";
  3964.     }

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

  3966.     clcf->keepalive_timeout = ngx_parse_time(&value[1], 0);

  3967.     if (clcf->keepalive_timeout == (ngx_msec_t) NGX_ERROR) {
  3968.         return "invalid value";
  3969.     }

  3970.     if (cf->args->nelts == 2) {
  3971.         return NGX_CONF_OK;
  3972.     }

  3973.     clcf->keepalive_header = ngx_parse_time(&value[2], 1);

  3974.     if (clcf->keepalive_header == (time_t) NGX_ERROR) {
  3975.         return "invalid value";
  3976.     }

  3977.     return NGX_CONF_OK;
  3978. }


  3979. static char *
  3980. ngx_http_core_internal(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  3981. {
  3982.     ngx_http_core_loc_conf_t *clcf = conf;

  3983.     if (clcf->internal != NGX_CONF_UNSET) {
  3984.         return "is duplicate";
  3985.     }

  3986.     clcf->internal = 1;

  3987.     return NGX_CONF_OK;
  3988. }


  3989. static char *
  3990. ngx_http_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  3991. {
  3992.     ngx_http_core_loc_conf_t  *clcf = conf;

  3993.     ngx_str_t  *value;

  3994.     if (clcf->resolver) {
  3995.         return "is duplicate";
  3996.     }

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

  3998.     clcf->resolver = ngx_resolver_create(cf, &value[1], cf->args->nelts - 1);
  3999.     if (clcf->resolver == NULL) {
  4000.         return NGX_CONF_ERROR;
  4001.     }

  4002.     return NGX_CONF_OK;
  4003. }


  4004. #if (NGX_HTTP_GZIP)

  4005. static char *
  4006. ngx_http_gzip_disable(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  4007. {
  4008.     ngx_http_core_loc_conf_t  *clcf = conf;

  4009. #if (NGX_PCRE)

  4010.     ngx_str_t            *value;
  4011.     ngx_uint_t            i;
  4012.     ngx_regex_elt_t      *re;
  4013.     ngx_regex_compile_t   rc;
  4014.     u_char                errstr[NGX_MAX_CONF_ERRSTR];

  4015.     if (clcf->gzip_disable == NGX_CONF_UNSET_PTR) {
  4016.         clcf->gzip_disable = ngx_array_create(cf->pool, 2,
  4017.                                               sizeof(ngx_regex_elt_t));
  4018.         if (clcf->gzip_disable == NULL) {
  4019.             return NGX_CONF_ERROR;
  4020.         }
  4021.     }

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

  4023.     ngx_memzero(&rc, sizeof(ngx_regex_compile_t));

  4024.     rc.pool = cf->pool;
  4025.     rc.err.len = NGX_MAX_CONF_ERRSTR;
  4026.     rc.err.data = errstr;

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

  4028.         if (ngx_strcmp(value[i].data, "msie6") == 0) {
  4029.             clcf->gzip_disable_msie6 = 1;
  4030.             continue;
  4031.         }

  4032. #if (NGX_HTTP_DEGRADATION)

  4033.         if (ngx_strcmp(value[i].data, "degradation") == 0) {
  4034.             clcf->gzip_disable_degradation = 1;
  4035.             continue;
  4036.         }

  4037. #endif

  4038.         re = ngx_array_push(clcf->gzip_disable);
  4039.         if (re == NULL) {
  4040.             return NGX_CONF_ERROR;
  4041.         }

  4042.         rc.pattern = value[i];
  4043.         rc.options = NGX_REGEX_CASELESS;

  4044.         if (ngx_regex_compile(&rc) != NGX_OK) {
  4045.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V", &rc.err);
  4046.             return NGX_CONF_ERROR;
  4047.         }

  4048.         re->regex = rc.regex;
  4049.         re->name = value[i].data;
  4050.     }

  4051.     return NGX_CONF_OK;

  4052. #else
  4053.     ngx_str_t   *value;
  4054.     ngx_uint_t   i;

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

  4056.     for (i = 1; i < cf->args->nelts; i++) {
  4057.         if (ngx_strcmp(value[i].data, "msie6") == 0) {
  4058.             clcf->gzip_disable_msie6 = 1;
  4059.             continue;
  4060.         }

  4061. #if (NGX_HTTP_DEGRADATION)

  4062.         if (ngx_strcmp(value[i].data, "degradation") == 0) {
  4063.             clcf->gzip_disable_degradation = 1;
  4064.             continue;
  4065.         }

  4066. #endif

  4067.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  4068.                            "without PCRE library \"gzip_disable\" supports "
  4069.                            "builtin \"msie6\" and \"degradation\" mask only");

  4070.         return NGX_CONF_ERROR;
  4071.     }

  4072.     return NGX_CONF_OK;

  4073. #endif
  4074. }

  4075. #endif


  4076. #if (NGX_HAVE_OPENAT)

  4077. static char *
  4078. ngx_http_disable_symlinks(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  4079. {
  4080.     ngx_http_core_loc_conf_t *clcf = conf;

  4081.     ngx_str_t                         *value;
  4082.     ngx_uint_t                         i;
  4083.     ngx_http_compile_complex_value_t   ccv;

  4084.     if (clcf->disable_symlinks != NGX_CONF_UNSET_UINT) {
  4085.         return "is duplicate";
  4086.     }

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

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

  4089.         if (ngx_strcmp(value[i].data, "off") == 0) {
  4090.             clcf->disable_symlinks = NGX_DISABLE_SYMLINKS_OFF;
  4091.             continue;
  4092.         }

  4093.         if (ngx_strcmp(value[i].data, "if_not_owner") == 0) {
  4094.             clcf->disable_symlinks = NGX_DISABLE_SYMLINKS_NOTOWNER;
  4095.             continue;
  4096.         }

  4097.         if (ngx_strcmp(value[i].data, "on") == 0) {
  4098.             clcf->disable_symlinks = NGX_DISABLE_SYMLINKS_ON;
  4099.             continue;
  4100.         }

  4101.         if (ngx_strncmp(value[i].data, "from=", 5) == 0) {
  4102.             value[i].len -= 5;
  4103.             value[i].data += 5;

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

  4105.             ccv.cf = cf;
  4106.             ccv.value = &value[i];
  4107.             ccv.complex_value = ngx_palloc(cf->pool,
  4108.                                            sizeof(ngx_http_complex_value_t));
  4109.             if (ccv.complex_value == NULL) {
  4110.                 return NGX_CONF_ERROR;
  4111.             }

  4112.             if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
  4113.                 return NGX_CONF_ERROR;
  4114.             }

  4115.             clcf->disable_symlinks_from = ccv.complex_value;

  4116.             continue;
  4117.         }

  4118.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  4119.                            "invalid parameter \"%V\"", &value[i]);
  4120.         return NGX_CONF_ERROR;
  4121.     }

  4122.     if (clcf->disable_symlinks == NGX_CONF_UNSET_UINT) {
  4123.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  4124.                            "\"%V\" must have \"off\", \"on\" "
  4125.                            "or \"if_not_owner\" parameter",
  4126.                            &cmd->name);
  4127.         return NGX_CONF_ERROR;
  4128.     }

  4129.     if (cf->args->nelts == 2) {
  4130.         clcf->disable_symlinks_from = NULL;
  4131.         return NGX_CONF_OK;
  4132.     }

  4133.     if (clcf->disable_symlinks_from == NGX_CONF_UNSET_PTR) {
  4134.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  4135.                            "duplicate parameters \"%V %V\"",
  4136.                            &value[1], &value[2]);
  4137.         return NGX_CONF_ERROR;
  4138.     }

  4139.     if (clcf->disable_symlinks == NGX_DISABLE_SYMLINKS_OFF) {
  4140.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  4141.                            "\"from=\" cannot be used with \"off\" parameter");
  4142.         return NGX_CONF_ERROR;
  4143.     }

  4144.     return NGX_CONF_OK;
  4145. }

  4146. #endif


  4147. static char *
  4148. ngx_http_core_lowat_check(ngx_conf_t *cf, void *post, void *data)
  4149. {
  4150. #if (NGX_FREEBSD)
  4151.     ssize_t *np = data;

  4152.     if ((u_long) *np >= ngx_freebsd_net_inet_tcp_sendspace) {
  4153.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  4154.                            "\"send_lowat\" must be less than %d "
  4155.                            "(sysctl net.inet.tcp.sendspace)",
  4156.                            ngx_freebsd_net_inet_tcp_sendspace);

  4157.         return NGX_CONF_ERROR;
  4158.     }

  4159. #elif !(NGX_HAVE_SO_SNDLOWAT)
  4160.     ssize_t *np = data;

  4161.     ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
  4162.                        "\"send_lowat\" is not supported, ignored");

  4163.     *np = 0;

  4164. #endif

  4165.     return NGX_CONF_OK;
  4166. }


  4167. static char *
  4168. ngx_http_core_pool_size(ngx_conf_t *cf, void *post, void *data)
  4169. {
  4170.     size_t *sp = data;

  4171.     if (*sp < NGX_MIN_POOL_SIZE) {
  4172.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  4173.                            "the pool size must be no less than %uz",
  4174.                            NGX_MIN_POOL_SIZE);
  4175.         return NGX_CONF_ERROR;
  4176.     }

  4177.     if (*sp % NGX_POOL_ALIGNMENT) {
  4178.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  4179.                            "the pool size must be a multiple of %uz",
  4180.                            NGX_POOL_ALIGNMENT);
  4181.         return NGX_CONF_ERROR;
  4182.     }

  4183.     return NGX_CONF_OK;
  4184. }