प्रौद्योगिकी साझेदारी

HTTP मॉड्यूल् विकसितं कुर्वन्तु

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

HTTP मॉड्यूलस्य आँकडा संरचना

ngx_module_t मॉड्यूलस्य आँकडा संरचना

// core.ngx_core.h
typedef struct ngx_module_s          ngx_module_t;

// core.ngx_module.h
struct ngx_module_s {
    /* 表示当前模块在这个模块中的序号,
     * 既表示模块的优先级,也表明模块的位置,
     * 借以帮助Nginx框架快速获得某个模块的数据
     */
    ngx_uint_t            ctx_index;
    /*
     * 表示当前模块在ngx_modules数组中的序号,
     * ctx_index表示当前模块在一类模块中的序号,
     * index是在所有模块中的序号
     */
    ngx_uint_t            index;

    // 模块名称
    char                 *name;

    // spare系列的保留变量
    ngx_uint_t            spare0;
    ngx_uint_t            spare1;
    // 模块的版本号
    ngx_uint_t            version;
    const char           *signature; //
    /*
     * 用于指向一类模块的上下文结构体,
     * Nginx模块有很多种类的模块,不同模块之间功能差距很大
     * 事件类型的模块主要处理IO事件,HTTP类型模块主要处理HTTP应用层的功能
     * ctx指向特定类型模块的公共接口,例如HTTP模块中,指向ngx_http_module_t
     */
    void                 *ctx;
    ngx_command_t        *commands;// 将处理nginx.conf中的配置项
    /*
     * 模块的类型,有5种
     * NGX_HTTP_MODULE,NGX_CORE_MODULE,NGX_CONF_MODULE,NGX_EVENT_MODULE,NGX_MALL_MODULE
     * 实际上可以自己定义类型
     * */
    ngx_uint_t            type;

    /*
     * 如下7个函数指针表示有7个执行点会分别调用这7个方法,对于任何一个方法
     * 如果不需要Nginx在某个时刻执行它,那么可以简单的设置为NULL空指针即可
     * */

    // 当master进程启动时进行回调init_master,但是目前为止,框架代码从来不会调用,设置为NULL
    ngx_int_t           (*init_master)(ngx_log_t *log);
    // init_module初始化所有模块时被调用,在master/worker模式下,这个阶段将在启动worker子进程前完成
    ngx_int_t           (*init_module)(ngx_cycle_t *cycle);
    // 在正常服务前被调用,在master/worker模式下,多个worker子进程已经产生,在每个worker进程的初始化过程会调用所有模块的init_process
    ngx_int_t           (*init_process)(ngx_cycle_t *cycle);
    // Nginx不支持多线程模式,所以init_thread在框架代码中没有被调用过,设置为NULL
    ngx_int_t           (*init_thread)(ngx_cycle_t *cycle);
    // exit_thread也不支持,设置为NULL
    void                (*exit_thread)(ngx_cycle_t *cycle);
    // 在服务停止前调用,master/worker模式下,worker进程会在退出前调用它
    void                (*exit_process)(ngx_cycle_t *cycle);
    // 在master进程退出前被调用
    void                (*exit_master)(ngx_cycle_t *cycle);
    /*
     * 以下8个变量也是保留字段,目前没有使用,但可用Nginx提供的NGX_MODULE_V1_PADDING宏来填充
     * */
    uintptr_t             spare_hook0;
    uintptr_t             spare_hook1;
    uintptr_t             spare_hook2;
    uintptr_t             spare_hook3;
    uintptr_t             spare_hook4;
    uintptr_t             spare_hook5;
    uintptr_t             spare_hook6;
    uintptr_t             spare_hook7;
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72

HTTP मॉड्यूल परिभाषयन्ते सति प्रकारः NGX_HTTP_MODULE इति सेट् भवति: init_module, init_process, exit_process, exit_master, ते Nginx कोडेन आह्वयन्ति तथा च HTTP फ्रेमवर्क इत्यनेन सह किमपि सम्बन्धः नास्ति । nginx.conf मध्ये परिभाषितं नास्ति, एतादृशं उद्घाटनं HTTP कार्यविन्यासवस्तूनाम् कृते, एताः विनाशविधयः अद्यापि आह्विताः भविष्यन्ति । अतः HTTP मॉड्यूल् विकसिते सति ते प्रायः NULL इति सेट् भवन्ति यदा जालसर्वररूपेण न उपयुज्यन्ते तदा HTTP मॉड्यूल् मध्ये कोऽपि कोडः निष्पादितः न भविष्यति ।

HTTP मॉड्यूल् परिभाषयन्ते सति अन्तिमं कार्यं भवति यत् सदस्यद्वयं ctx तथा आदेशान् सेट् करणीयम् HTTP प्रकारस्य मॉड्यूलस्य कृते ctx ngx_http_module_t अन्तरफलकं प्रति सूचयति ।

ngx_http_module_t दत्तांशसंरचना

// http.ngx_http_config.h
typedef struct {
    // 解析配置文件前被调用
    ngx_int_t   (*preconfiguration)(ngx_conf_t *cf);
    // 完成配置文件的解析后调用
    ngx_int_t   (*postconfiguration)(ngx_conf_t *cf);
    //当需要创建数据结构用于存储main级别的全局配置项时,可以通过create_main_conf回调方法创建存储全局配置项的结构体
    void       *(*create_main_conf)(ngx_conf_t *cf);
    // 常用与初始化main级别配置项
    char       *(*init_main_conf)(ngx_conf_t *cf, void *conf);
    // 当需要创建数据结构用于存储srv级别的配置项时,可以通过create_srv_conf回调方法创建存储srv级别配置项的结构体
    void       *(*create_srv_conf)(ngx_conf_t *cf);
    // 合并main级别和srv级别的同名配置项
    char       *(*merge_srv_conf)(ngx_conf_t *cf, void *prev, void *conf);
    // 当需要创建结构体用于存储loc级别的配置项时,可以实现create_loc_conf回调方法
    void       *(*create_loc_conf)(ngx_conf_t *cf);
    // 合并srv级别和loc级别下的同名配置项
    char       *(*merge_loc_conf)(ngx_conf_t *cf, void *prev, void *conf);
} ngx_http_module_t;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

उपर्युक्ताष्टचरणस्य आह्वानक्रमः परिभाषितक्रमात् भिन्नः भवति Nginx प्रारम्भप्रक्रियायाः समये, वास्तविकक्रमः यस्मिन् HTTP ढांचा एतान् कॉलबैक् पद्धतीन् आह्वयति: (nginx.conf विन्यासवस्तुना सह सम्बद्धः)
1)मुख्य_सम्मेलनं_रचयतु
2)create_srv_conf
३)create_loc_conf इति
४)पूर्वविन्यासः
5)init_main_conf
6)विलय_स्र्व_कॉन्फ
7)विलय_स्थान_सम्मेलनम्
८)उत्तरविन्यासः

आदेशानां सरणी मॉड्यूलस्य विन्याससञ्चिकामापदण्डान् परिभाषितुं उपयुज्यते प्रत्येकं सरणीतत्त्वं ngx_null_command द्वारा प्रतिनिधियते यदा Nginx विन्याससञ्चिकायां विन्यासवस्तुं विश्लेषयति .

ngx_command_s दत्तांशसंरचना

// core.ngx_core.h
typedef struct ngx_command_s         ngx_command_t;

// core.ngx_conf_file.h
struct ngx_command_s {
    ngx_str_t             name;// 配置项名称,列入:gzip
    ngx_uint_t            type;// 配置项类型,指定可以出现的位置,例如server,location中以及它可以携带的参数个数
    // 出现了name中指定的配置项后,将会调用set方法处理配置项的参数
    char               *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
    // 在配置文件中的偏移量
    ngx_uint_t            conf;
    // 通常用于预设的解析方法解析配置项
    ngx_uint_t            offset;
    // 配置项读取后的处理方法,必须是ngx_conf_post_t结构体指针
    void                 *post;
};

#define ngx_null_command  { ngx_null_string, 0, NULL, 0, 0, NULL }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

HTTP मॉड्यूल् परिभाषयन्तु

// http.modules.ngx_http_mytest_module.c
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>

static char *ngx_http_mytest(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);

static ngx_command_t ngx_http_mytest_commands[] = {
        {
                ngx_string("mytest"),
                NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_HTTP_LMT_CONF | NGX_CONF_NOARGS,
                ngx_http_mytest,
                NGX_HTTP_LOC_CONF_OFFSET,
                0,
                NULL
        },
        ngx_null_command
};
static ngx_http_module_t  ngx_http_mytest_module_ctx = {
        NULL,                                  /* preconfiguration */
        NULL,                  /* postconfiguration */

        NULL,                                  /* create main configuration */
        NULL,                                  /* init main configuration */

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

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

ngx_module_t  ngx_http_mytest_module = {
        NGX_MODULE_V1,
        &ngx_http_mytest_module_ctx,           /* module context */
        ngx_http_mytest_commands,              /* module directives */
        NGX_HTTP_MODULE,                       /* module type */
        NULL,                                  /* init master */
        NULL,                                  /* init module */
        NULL,                                  /* init process */
        NULL,                                  /* init thread */
        NULL,                                  /* exit thread */
        NULL,                                  /* exit process */
        NULL,                                  /* exit master */
        NGX_MODULE_V1_PADDING
};

static char *ngx_http_mytest(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) {
    ngx_http_core_loc_conf_t *clcf;
    clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
    clcf->handler = ngx_http_mytest_handler;
    return NGX_CONF_OK;
}


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55

उपयोक्तृनिवेदनानि सम्पादयन्तु

// http.ngx_http_core_module.h
typedef struct ngx_http_core_loc_conf_s  ngx_http_core_loc_conf_t;
struct ngx_http_core_loc_conf_s {
    ngx_str_t     name;          /* location name */
    ngx_str_t     escaped_name;

#if (NGX_PCRE)
    ngx_http_regex_t  *regex;
#endif

    unsigned      noname:1;   /* "if () {}" block or limit_except */
    unsigned      lmt_excpt:1;
    unsigned      named:1;

    unsigned      exact_match:1;
    unsigned      noregex:1;

    unsigned      auto_redirect:1;
#if (NGX_HTTP_GZIP)
    unsigned      gzip_disable_msie6:2;
    unsigned      gzip_disable_degradation:2;
#endif

    ngx_http_location_tree_node_t   *static_locations;
#if (NGX_PCRE)
    ngx_http_core_loc_conf_t       **regex_locations;
#endif

    /* pointer to the modules' loc_conf */
    void        **loc_conf;

    uint32_t      limit_except;
    void        **limit_except_loc_conf;

    ngx_http_handler_pt  handler;

    /* location name length for inclusive location with inherited alias */
    size_t        alias;
    ngx_str_t     root;                    /* root, alias */
    ngx_str_t     post_action;

    ngx_array_t  *root_lengths;
    ngx_array_t  *root_values;

    ngx_array_t  *types;
    ngx_hash_t    types_hash;
    ngx_str_t     default_type;

    off_t         client_max_body_size;    /* client_max_body_size */
    off_t         directio;                /* directio */
    off_t         directio_alignment;      /* directio_alignment */

    size_t        client_body_buffer_size; /* client_body_buffer_size */
    size_t        send_lowat;              /* send_lowat */
    size_t        postpone_output;         /* postpone_output */
    size_t        sendfile_max_chunk;      /* sendfile_max_chunk */
    size_t        read_ahead;              /* read_ahead */
    size_t        subrequest_output_buffer_size;
                                           /* subrequest_output_buffer_size */

    ngx_http_complex_value_t  *limit_rate; /* limit_rate */
    ngx_http_complex_value_t  *limit_rate_after; /* limit_rate_after */

    ngx_msec_t    client_body_timeout;     /* client_body_timeout */
    ngx_msec_t    send_timeout;            /* send_timeout */
    ngx_msec_t    keepalive_time;          /* keepalive_time */
    ngx_msec_t    keepalive_timeout;       /* keepalive_timeout */
    ngx_msec_t    lingering_time;          /* lingering_time */
    ngx_msec_t    lingering_timeout;       /* lingering_timeout */
    ngx_msec_t    resolver_timeout;        /* resolver_timeout */
    ngx_msec_t    auth_delay;              /* auth_delay */

    ngx_resolver_t  *resolver;             /* resolver */

    time_t        keepalive_header;        /* keepalive_timeout */

    ngx_uint_t    keepalive_requests;      /* keepalive_requests */
    ngx_uint_t    keepalive_disable;       /* keepalive_disable */
    ngx_uint_t    satisfy;                 /* satisfy */
    ngx_uint_t    lingering_close;         /* lingering_close */
    ngx_uint_t    if_modified_since;       /* if_modified_since */
    ngx_uint_t    max_ranges;              /* max_ranges */
    ngx_uint_t    client_body_in_file_only; /* client_body_in_file_only */

    ngx_flag_t    client_body_in_single_buffer;
                                           /* client_body_in_singe_buffer */
    ngx_flag_t    internal;                /* internal */
    ngx_flag_t    sendfile;                /* sendfile */
    ngx_flag_t    aio;                     /* aio */
    ngx_flag_t    aio_write;               /* aio_write */
    ngx_flag_t    tcp_nopush;              /* tcp_nopush */
    ngx_flag_t    tcp_nodelay;             /* tcp_nodelay */
    ngx_flag_t    reset_timedout_connection; /* reset_timedout_connection */
    ngx_flag_t    absolute_redirect;       /* absolute_redirect */
    ngx_flag_t    server_name_in_redirect; /* server_name_in_redirect */
    ngx_flag_t    port_in_redirect;        /* port_in_redirect */
    ngx_flag_t    msie_padding;            /* msie_padding */
    ngx_flag_t    msie_refresh;            /* msie_refresh */
    ngx_flag_t    log_not_found;           /* log_not_found */
    ngx_flag_t    log_subrequest;          /* log_subrequest */
    ngx_flag_t    recursive_error_pages;   /* recursive_error_pages */
    ngx_uint_t    server_tokens;           /* server_tokens */
    ngx_flag_t    chunked_transfer_encoding; /* chunked_transfer_encoding */
    ngx_flag_t    etag;                    /* etag */

#if (NGX_HTTP_GZIP)
    ngx_flag_t    gzip_vary;               /* gzip_vary */

    ngx_uint_t    gzip_http_version;       /* gzip_http_version */
    ngx_uint_t    gzip_proxied;            /* gzip_proxied */

#if (NGX_PCRE)
    ngx_array_t  *gzip_disable;            /* gzip_disable */
#endif
#endif

#if (NGX_THREADS || NGX_COMPAT)
    ngx_thread_pool_t         *thread_pool;
    ngx_http_complex_value_t  *thread_pool_value;
#endif

#if (NGX_HAVE_OPENAT)
    ngx_uint_t    disable_symlinks;        /* disable_symlinks */
    ngx_http_complex_value_t  *disable_symlinks_from;
#endif

    ngx_array_t  *error_pages;             /* error_page */

    ngx_path_t   *client_body_temp_path;   /* client_body_temp_path */

    ngx_open_file_cache_t  *open_file_cache;
    time_t        open_file_cache_valid;
    ngx_uint_t    open_file_cache_min_uses;
    ngx_flag_t    open_file_cache_errors;
    ngx_flag_t    open_file_cache_events;

    ngx_log_t    *error_log;

    ngx_uint_t    types_hash_max_size;
    ngx_uint_t    types_hash_bucket_size;

    ngx_queue_t  *locations;

#if 0
    ngx_http_core_loc_conf_t  *prev_location;
#endif
};

typedef ngx_int_t (*ngx_http_handler_pt)(ngx_http_request_t *r);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149

return value

// http.ngx_http_request.h

#define NGX_HTTP_CONTINUE                  100
#define NGX_HTTP_SWITCHING_PROTOCOLS       101
#define NGX_HTTP_PROCESSING                102

#define NGX_HTTP_OK                        200
#define NGX_HTTP_CREATED                   201
#define NGX_HTTP_ACCEPTED                  202
#define NGX_HTTP_NO_CONTENT                204
#define NGX_HTTP_PARTIAL_CONTENT           206

#define NGX_HTTP_SPECIAL_RESPONSE          300
#define NGX_HTTP_MOVED_PERMANENTLY         301
#define NGX_HTTP_MOVED_TEMPORARILY         302
#define NGX_HTTP_SEE_OTHER                 303
#define NGX_HTTP_NOT_MODIFIED              304
#define NGX_HTTP_TEMPORARY_REDIRECT        307
#define NGX_HTTP_PERMANENT_REDIRECT        308

#define NGX_HTTP_BAD_REQUEST               400
#define NGX_HTTP_UNAUTHORIZED              401
#define NGX_HTTP_FORBIDDEN                 403
#define NGX_HTTP_NOT_FOUND                 404
#define NGX_HTTP_NOT_ALLOWED               405
#define NGX_HTTP_REQUEST_TIME_OUT          408
#define NGX_HTTP_CONFLICT                  409
#define NGX_HTTP_LENGTH_REQUIRED           411
#define NGX_HTTP_PRECONDITION_FAILED       412
#define NGX_HTTP_REQUEST_ENTITY_TOO_LARGE  413
#define NGX_HTTP_REQUEST_URI_TOO_LARGE     414
#define NGX_HTTP_UNSUPPORTED_MEDIA_TYPE    415
#define NGX_HTTP_RANGE_NOT_SATISFIABLE     416
#define NGX_HTTP_MISDIRECTED_REQUEST       421
#define NGX_HTTP_TOO_MANY_REQUESTS         429


/* Our own HTTP codes */

/* The special code to close connection without any response */
#define NGX_HTTP_CLOSE                     444

#define NGX_HTTP_NGINX_CODES               494

#define NGX_HTTP_REQUEST_HEADER_TOO_LARGE  494

#define NGX_HTTPS_CERT_ERROR               495
#define NGX_HTTPS_NO_CERT                  496

/*
 * We use the special code for the plain HTTP requests that are sent to
 * HTTPS port to distinguish it from 4XX in an error page redirection
 */
#define NGX_HTTP_TO_HTTPS                  497

/* 498 is the canceled code for the requests with invalid host name */

/*
 * HTTP does not define the code for the case when a client closed
 * the connection while we are processing its request so we introduce
 * own code to log such situation when a client has closed the connection
 * before we even try to send the HTTP header to it
 */
#define NGX_HTTP_CLIENT_CLOSED_REQUEST     499


#define NGX_HTTP_INTERNAL_SERVER_ERROR     500
#define NGX_HTTP_NOT_IMPLEMENTED           501
#define NGX_HTTP_BAD_GATEWAY               502
#define NGX_HTTP_SERVICE_UNAVAILABLE       503
#define NGX_HTTP_GATEWAY_TIME_OUT          504
#define NGX_HTTP_VERSION_NOT_SUPPORTED     505
#define NGX_HTTP_INSUFFICIENT_STORAGE      507

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74

RFC2616 विनिर्देशे परिभाषितानां रिटर्न् कोड् इत्यस्य अतिरिक्तं, उपर्युक्तेषु रिटर्न् वैल्यूषु Nginx द्वारा एव परिभाषिताः HTTP रिटर्न् कोड्स् अपि सन्ति उदाहरणार्थं: NGX_HTTP_CLOSE इत्यस्य उपयोगः HTTP फ्रेमवर्कं प्रत्यक्षतया उपयोक्तृसंयोजनं बन्दं कर्तुं अनुरोधयितुं भवति

Nginx全局定义的错误码
// core.ngx_core.h
#define  NGX_OK          0
#define  NGX_ERROR      -1
#define  NGX_AGAIN      -2
#define  NGX_BUSY       -3
#define  NGX_DONE       -4
#define  NGX_DECLINED   -5
#define  NGX_ABORT      -6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

यदा ngx_http_output_filter अन्ते उपयोक्त्रे प्रतिक्रियापैकेट् प्रेषयितुं आह्वयते तदा ngx_http_output_filter इत्यस्य रिटर्न् मूल्यं ngx_http_mytest_handler पद्धतेः रिटर्न् मूल्यरूपेण उपयोक्तुं शक्यते

URI तथा पैरामीटर्स् प्राप्तुम्

// http.ngx_http.h
typedef struct ngx_http_request_s     ngx_http_request_t;

// http.ngx_http_request.h

struct ngx_http_request_s {
	...
	ngx_uint_t                        method;
    ngx_uint_t                        http_version;

    ngx_str_t                         request_line;
    ngx_str_t                         uri;
    ngx_str_t                         args;
    ngx_str_t                         exten;
    ngx_str_t                         unparsed_uri;

    ngx_str_t                         method_name;
    ngx_str_t                         http_protocol;
    ngx_str_t                         schema;
	...
	u_char                           *uri_start;
    u_char                           *uri_end;
    u_char                           *uri_ext;
    u_char                           *args_start;
    u_char                           *request_start;
    u_char                           *request_end;
    u_char                           *method_end;
    u_char                           *schema_start;
    u_char                           *schema_end;
    ...
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

विधिनाम

// http.ngx_http_request.h
ngx_uint_t                        method;

// http.ngx_http_request.h
#define NGX_HTTP_UNKNOWN                   0x00000001
#define NGX_HTTP_GET                       0x00000002
#define NGX_HTTP_HEAD                      0x00000004
#define NGX_HTTP_POST                      0x00000008
#define NGX_HTTP_PUT                       0x00000010
#define NGX_HTTP_DELETE                    0x00000020
#define NGX_HTTP_MKCOL                     0x00000040
#define NGX_HTTP_COPY                      0x00000080
#define NGX_HTTP_MOVE                      0x00000100
#define NGX_HTTP_OPTIONS                   0x00000200
#define NGX_HTTP_PROPFIND                  0x00000400
#define NGX_HTTP_PROPPATCH                 0x00000800
#define NGX_HTTP_LOCK                      0x00001000
#define NGX_HTTP_UNLOCK                    0x00002000
#define NGX_HTTP_PATCH                     0x00004000
#define NGX_HTTP_TRACE                     0x00008000
#define NGX_HTTP_CONNECT                   0x00010000
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

विधिः कथं प्राप्नोति

  • method उपरि परिभाषितं मैक्रो अस्ति, प्रत्यक्षतुलना (यदि भवान् स्ट्रिंग् इत्यनेन सह तुलनां कर्तुं method_name सदस्यस्य उपयोगं करोति तर्हि कार्यक्षमता बहु दुर्गता भविष्यति)
  • यदि भवान् विधिनाम प्राप्तुम् इच्छति तर्हि method_name इत्यस्य उपयोगं कर्तुं शक्नोति, तथा च request_start तथा ​​method_end सूचकयोः संयोजनेन प्राप्तुं शक्नोति ।

उरी

	ngx_str_t                         uri;
	
	ngx_str_t                         unparsed_uri;
	
    u_char                           *uri_start;
    u_char                           *uri_end;
    u_char                           *uri_ext;

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

uri अनुरोधे URI इत्यस्य प्रतिनिधित्वं करोति, uri_start तथा ​​uri_end इत्यपि प्राप्तुं शक्यते ।
exten member चरः उपयोक्त्रा अनुरोधितं सञ्चिकाविस्तारं दर्शयति ।

unparsed_uri URL डिकोडिंग् विना मूलनिवेदनं प्रतिनिधियति । यथा, यदा uri /ab भवति तदा unparsed_uri /a%20b भवति

URL

args उपयोक्तुः अनुरोधे URL मापदण्डान् दर्शयति । तथैव: args_start तथा ​​uri_end अपि URL प्राप्तुं शक्नुवन्ति

प्रोटोकॉल संस्करणम्

http_protocol इत्यस्य दत्तांशसदस्यः उपयोक्तृ-अनुरोधस्य HTTP-प्रोटोकॉल-संस्करण-स्ट्रिंग्-इत्येतत् सूचयति, तथा च len-सदस्यः प्रोटोकॉल-संस्करण-स्ट्रिंग्-दीर्घता भवति ।

http_version इति Nginx द्वारा विश्लेषितं प्रोटोकॉलसंस्करणम् अस्ति

ngx_uint_t                        http_version;

#define NGX_HTTP_VERSION_9                 9
#define NGX_HTTP_VERSION_10                1000
#define NGX_HTTP_VERSION_11                1001
#define NGX_HTTP_VERSION_20                2000
#define NGX_HTTP_VERSION_30                3000

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

HTTP प्रोटोकॉल संस्करणस्य विश्लेषणार्थं http_version इत्यस्य उपयोगः अनुशंसितः अस्ति ।

मूलप्रयोक्तृअनुरोधपङ्क्तिं प्राप्तुं request_start तथा ​​request_end इत्येतयोः उपयोगं कुर्वन्तु

HTTP शीर्षकं प्राप्नुवन्तु


struct ngx_http_request_s {
	...
	ngx_buf_t                        *header_in;
	ngx_http_headers_in_t             headers_in;
	...
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

header_in Nginx द्वारा प्राप्तं अविश्लेषितं HTTP शीर्षकं प्रति सूचयति header_in एकः बफरः अस्ति यः ngx_http_headers_in_t प्रकारस्य headers_in विश्लेषितं HTTP शीर्षकं संग्रहयति ।

// http.ngx_http_request.h
typedef struct {
    //所有解析过的HTTP头部都在headers链表中
    ngx_list_t                        headers;
    // 每个ngx_table_elt_t成员都是RFC2616规范定义的HTTP头部,
    // 它们实际上指向headers链表中相应成员,当为NULL时表示没有解析到相应的HTTP头部
    ngx_table_elt_t                  *host;
    ngx_table_elt_t                  *connection;
    ngx_table_elt_t                  *if_modified_since;
    ngx_table_elt_t                  *if_unmodified_since;
    ngx_table_elt_t                  *if_match;
    ngx_table_elt_t                  *if_none_match;
    ngx_table_elt_t                  *user_agent;
    ngx_table_elt_t                  *referer;
    ngx_table_elt_t                  *content_length;
    ngx_table_elt_t                  *content_range;
    ngx_table_elt_t                  *content_type;

    ngx_table_elt_t                  *range;
    ngx_table_elt_t                  *if_range;

    ngx_table_elt_t                  *transfer_encoding;
    ngx_table_elt_t                  *te;
    ngx_table_elt_t                  *expect;
    ngx_table_elt_t                  *upgrade;

#if (NGX_HTTP_GZIP || NGX_HTTP_HEADERS)
    ngx_table_elt_t                  *accept_encoding;
    ngx_table_elt_t                  *via;
#endif

    ngx_table_elt_t                  *authorization;

    ngx_table_elt_t                  *keep_alive;

#if (NGX_HTTP_X_FORWARDED_FOR)
    ngx_table_elt_t                  *x_forwarded_for;
#endif

#if (NGX_HTTP_REALIP)
    ngx_table_elt_t                  *x_real_ip;
#endif

#if (NGX_HTTP_HEADERS)
    ngx_table_elt_t                  *accept;
    ngx_table_elt_t                  *accept_language;
#endif

#if (NGX_HTTP_DAV)
    ngx_table_elt_t                  *depth;
    ngx_table_elt_t                  *destination;
    ngx_table_elt_t                  *overwrite;
    ngx_table_elt_t                  *date;
#endif
    ngx_table_elt_t                  *cookie;
    // 只有ngx_http_auth_basic_module才会用到的成员
    ngx_str_t                         user;
    ngx_str_t                         passwd;
    // server名称
    ngx_str_t                         server;
    // 计算出的HTTP包体大小(ngx_table_elt_t * content_length)
    off_t                             content_length_n;
    time_t                            keep_alive_n;
    // HTTP连接类型,取值范围是0,
    // #define NGX_HTTP_CONNECTION_CLOSE          1
    //#define NGX_HTTP_CONNECTION_KEEP_ALIVE     2
    unsigned                          connection_type:2;
    unsigned                          chunked:1;
    unsigned                          multi:1;
    unsigned                          multi_linked:1;
    // 以下7个标志位是 HTTP框架根据浏览器传来的useragent头部,可以判断浏览器的类型,只为1表示相应的浏览器发来的请求
    unsigned                          msie:1;
    unsigned                          msie6:1;
    unsigned                          opera:1;
    unsigned                          gecko:1;
    unsigned                          chrome:1;
    unsigned                          safari:1;
    unsigned                          konqueror:1;
} ngx_http_headers_in_t;

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80

यथा: असामान्य HTTP अनुरोधशीर्षकाणि कथं अन्वेष्टव्यानि, भवान् केवलं headers_in.headers इत्येतत् भ्रमितुं शक्नोति

static ngx_int_t ngx_http_mytest_handler(ngx_http_request_t *r) {
	...
    ngx_list_part_t *part = &r->header_in.headers.part;
    ngx_table_elt_t *header = part->elts;
    for (i = 0;; ++i) {
        if (i >= part->nelts) {
            if (part->next == NULL) {
                break;
            }
            part = part->next;
            header = part->elts;
            i = 0;
        }
        if (header[i].hash == 0){
            continue;
        }
        if (0 == ngx_strncasecmp(header[i].key.data,(u_char*) "Rpc-Description",header[i].key.len)){
            if (0 == ngx_strncmp(header[i].value.data,"uploadFile",header[i].value.len)){
                // 找到了正确的头,继续向下执行
            }
        }
    }
    ...
}



  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

HTTP पैकेट शरीरं प्राप्नुवन्तु

HTTP पैकेट-शरीरस्य दीर्घता अतीव विशाला भवितुम् अर्हति यदि भवान् एकदा एव सर्वाणि पैकेट-बॉडी-आह्वानं पठितुं च प्रयतते तर्हि सम्भवतः nginx-प्रक्रियाम् अवरुद्धं करिष्यति HTTP-रूपरेखा पैकेट-बॉडी-प्राप्त्यर्थं अतुल्यकालिक-विधिं प्रदाति ।

ngx_int_t ngx_http_read_client_request_body(ngx_http_request_t *r,
    ngx_http_client_body_handler_pt post_handler);
  • 1
  • 2

इयं अतुल्यकालिकविधिः अस्ति यत् Nginx इत्यनेन अनुरोधितं संकुलशरीरं स्वीकुर्वितुं आरभ्यते इति न सूचयति यदा सर्वाणि संकुलशरीरसामग्रीणि प्राप्तानि भवन्ति तदा post_handler द्वारा सूचिता कॉलबैकविधिः भविष्यति पुनः आहूता भवतु।

प्रतिक्रिया प्रेषयन्तु

प्रतिक्रियायां त्रयः भागाः सन्ति : प्रतिक्रियापङ्क्तिः, प्रतिक्रियाशीर्षकं, संकुलशरीरं च ।

HTTP शीर्षकं प्रेषयन्तु

ngx_int_t ngx_http_send_header(ngx_http_request_t *r)
  • 1

struct ngx_http_request_s {
	ngx_http_headers_out_t            headers_out;
}

typedef struct {
    ngx_list_t                        headers;
    ngx_list_t                        trailers;

    ngx_uint_t                        status;
    ngx_str_t                         status_line;

    ngx_table_elt_t                  *server;
    ngx_table_elt_t                  *date;
    ngx_table_elt_t                  *content_length;
    ngx_table_elt_t                  *content_encoding;
    ngx_table_elt_t                  *location;
    ngx_table_elt_t                  *refresh;
    ngx_table_elt_t                  *last_modified;
    ngx_table_elt_t                  *content_range;
    ngx_table_elt_t                  *accept_ranges;
    ngx_table_elt_t                  *www_authenticate;
    ngx_table_elt_t                  *expires;
    ngx_table_elt_t                  *etag;

    ngx_table_elt_t                  *cache_control;
    ngx_table_elt_t                  *link;

    ngx_str_t                        *override_charset;

    size_t                            content_type_len;
    ngx_str_t                         content_type;
    ngx_str_t                         charset;
    u_char                           *content_type_lowcase;
    ngx_uint_t                        content_type_hash;

    off_t                             content_length_n;
    off_t                             content_offset;
    time_t                            date_time;
    time_t                            last_modified_time;
} ngx_http_headers_out_t;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

अनुरोधशीर्षकं योजयन्तु

   ngx_table_elt_t  h = ngx_list_push(&r->headers_out.headers);
   if (h == NULL){
       return NGX_ERROR
   }
   h.hash = 1;
   h.key.len = sizeof("TestHeader") - 1;
   h.key.data = (u_char *) "TestHeader";
   h.value.len = sizeof("TestValue") - 1;
   h.value.data = (u_char *) "TestValue" ;


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

संकुलशरीररूपेण स्मृतौ एकं स्ट्रिंग् प्रेषयन्तु

ngx_int_t ngx_http_output_filter(ngx_http_request_t *r, ngx_chain_t *in)
  • 1

HTTP प्रतिक्रियाशरीरं क्लायन्ट् प्रति प्रेषयन्तु

    ngx_buf_t *b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
    b->start = (u_char*)ngx_pcalloc(r->pool,128);
    b->pos = b->start;
    b->last = b->start;
    b->end = b->last + 128;
    b->temporary = 1;
    
    // 等同于如下
    ngx_buf_t *b = ngx_create_temp_buf(r->pool,128) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

एकं नमस्कारं जगत् प्रत्यागच्छतु

static ngx_int_t ngx_http_mytest_handler(ngx_http_request_t *r) {
    // 必须为GET或者HEAD,否则返回405
    if (!(r->method & (NGX_HTTP_GET | NGX_HTTP_HEAD))){
        return NGX_HTTP_NOT_ALLOWED;
    }
    // 丢弃请求中的包体
    ngx_int_t rc = ngx_http_discard_request_body(r);
    if (rc != NGX_OK){
        return rc;
    }
    // 设置返回类型
    ngx_str_t  type = ngx_string("text/plain");
    // 设置返回体
    ngx_str_t response = ngx_string("Hello World!");
    // 设置响应码
    r->headers_out.status = NGX_HTTP_OK;
    // 设置响应体大小
    r->headers_out.content_length_n = response.len;
    // 设置类型
    r->headers_out.content_type = type;
    // 发送HTTP头部
    rc = ngx_http_send_header(r);
    if (rc == NGX_ERROR || rc > NGX_OK || r->header_only){
        return rc;
    }
    // 构造ngx_buf_t结构体发送包体
    ngx_buf_t *b;
    b = ngx_create_temp_buf(r->pool,response.len);
    if (b == NULL){
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }
    // 将hello world复制到ngx_buf_t指向的内存中
    ngx_memcpy(b->pos,response.data,response.len);
    // 注意设置好last指针
    b->last = b->pos + response.len;
    // 声明这是最后一块缓冲区
    b->last_buf = 1;
    // 构造发送时的ngx_chain_t结构体
    ngx_chain_t  out;
    out.buf = b;
    out.next = NULL;
    // 发送包体
    return ngx_http_output_filter(r,&out);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44

संकुलशरीररूपेण प्रेषिता डिस्कसञ्चिका

ngx_buf_t इत्यस्य in_file इत्येतत् 1 इति सेट् कुर्वन्तु, यत् बफरः सञ्चिका अस्ति, न तु स्मृतिः इति सूचयति । सञ्चिका ngx_file_t अस्ति, संरचना निम्नलिखितरूपेण अस्ति ।


struct ngx_file_s {
    ngx_fd_t                   fd;// 文件句柄描述符
    ngx_str_t                  name;// 文件名称
    ngx_file_info_t            info;// 文件大小等基本信息,就是Linux系统定义的stat结构

    off_t                      offset;// 表示处理到文件何处了
    off_t                      sys_offset;// 当前文件系统偏移量

    ngx_log_t                 *log;// 日志对象,相关的日志会输出到log指定的日志文件中

#if (NGX_THREADS || NGX_COMPAT)
    ngx_int_t                (*thread_handler)(ngx_thread_task_t *task,
                                               ngx_file_t *file);
    void                      *thread_ctx;
    ngx_thread_task_t         *thread_task;
#endif

#if (NGX_HAVE_FILE_AIO || NGX_COMPAT)
    ngx_event_aio_t           *aio;
#endif

    unsigned                   valid_info:1;
    unsigned                   directio:1;// 在发送大文件时可以设置为1
};

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26