您的位置:首页 > 运维架构 > Apache

针对Apache2handler的几个问题

2015-11-03 16:50 549 查看
    php作为一项普通的脚本语言,有如今的部署规模,很大程度上归结于apache2handler的功劳。众所周知,通常情况在UNIX下,php在编译时通过--with-apxs2=apxs2_path的方式向apache modules中生成libphp5.so,然后在httpd.conf文件中添加LoadMoudle语句,并设置MIME以提供对php请求文件的支持。

    然而,httpd在接收到HTTP请求后是怎样调出php工作的?当然是通过钩子php_ap2_register_hook拉起php启动,但apache何时开始拉起钩子?交给钩子的是请求内容还是读取后的文件流?

   根据php经验来看,php环境变量中有文件信息如__FILE__和$_SERVER[script_filename]等信息,此外,php中经常使用require等语句,猜测php获得的必定是请求信息。这个还有待验证。

   经过测试,在Win32下编译apache2-2handler发现,AP在phpmod注册了php5_module 结构体后,通过hook:php_ap2_register_hook进入周期:

  

void php_ap2_register_hook(apr_pool_t *p)
{
ap_hook_pre_config(php_pre_config, NULL, NULL, APR_HOOK_MIDDLE);
ap_hook_post_config(php_apache_server_startup, NULL, NULL, APR_HOOK_MIDDLE);
ap_hook_handler(php_handler, NULL, NULL, APR_HOOK_MIDDLE);
ap_hook_child_init(php_apache_child_init, NULL, NULL, APR_HOOK_MIDDLE);
}


其中,php_handler作为核心handler接收了request_rec结构体。其实质与CLI差不多,想想CLI下,php需要的最重要的ARGS就是-f  filename。在这里,先列出该结构体:

struct request_rec {
/** The pool associated with the request */
apr_pool_t *pool;
/** The connection to the client */
conn_rec *connection;
/** The virtual host for this request */
server_rec *server;

/** Pointer to the redirected request if this is an external redirect */
request_rec *next;
/** Pointer to the previous request if this is an internal redirect */
request_rec *prev;

/** Pointer to the main request if this is a sub-request
* (see http_request.h) */
request_rec *main;

/* Info about the request itself... we begin with stuff that only
* protocol.c should ever touch...
*/
/** First line of request */
char *the_request;
/** HTTP/0.9, "simple" request (e.g. GET /foo\n w/no headers) */
int assbackwards;
/** A proxy request (calculated during post_read_request/translate_name)
*  possible values PROXYREQ_NONE, PROXYREQ_PROXY, PROXYREQ_REVERSE,
*                  PROXYREQ_RESPONSE
*/
int proxyreq;
/** HEAD request, as opposed to GET */
int header_only;
/** Protocol string, as given to us, or HTTP/0.9 */
char *protocol;
/** Protocol version number of protocol; 1.1 = 1001 */
int proto_num;
/** Host, as set by full URI or Host: */
const char *hostname;

/** Time when the request started */
apr_time_t request_time;

/** Status line, if set by script */
const char *status_line;
/** Status line */
int status;

/* Request method, two ways; also, protocol, etc..  Outside of protocol.c,
* look, but don't touch.
*/

/** Request method (eg. GET, HEAD, POST, etc.) */
const char *method;
/** M_GET, M_POST, etc. */
int method_number;

/**
*  'allowed' is a bitvector of the allowed methods.
*
*  A handler must ensure that the request method is one that
*  it is capable of handling.  Generally modules should DECLINE
*  any request methods they do not handle.  Prior to aborting the
*  handler like this the handler should set r->allowed to the list
*  of methods that it is willing to handle.  This bitvector is used
*  to construct the "Allow:" header required for OPTIONS requests,
*  and HTTP_METHOD_NOT_ALLOWED and HTTP_NOT_IMPLEMENTED status codes.
*
*  Since the default_handler deals with OPTIONS, all modules can
*  usually decline to deal with OPTIONS.  TRACE is always allowed,
*  modules don't need to set it explicitly.
*
*  Since the default_handler will always handle a GET, a
*  module which does *not* implement GET should probably return
*  HTTP_METHOD_NOT_ALLOWED.  Unfortunately this means that a Script GET
*  handler can't be installed by mod_actions.
*/
apr_int64_t allowed;
/** Array of extension methods */
apr_array_header_t *allowed_xmethods;
/** List of allowed methods */
ap_method_list_t *allowed_methods;

/** byte count in stream is for body */
apr_off_t sent_bodyct;
/** body byte count, for easy access */
apr_off_t bytes_sent;
/** Last modified time of the requested resource */
apr_time_t mtime;

/* HTTP/1.1 connection-level features */

/** sending chunked transfer-coding */
int chunked;
/** The Range: header */
const char *range;
/** The "real" content length */
apr_off_t clength;

/** Remaining bytes left to read from the request body */
apr_off_t remaining;
/** Number of bytes that have been read  from the request body */
apr_off_t read_length;
/** Method for reading the request body
* (eg. REQUEST_CHUNKED_ERROR, REQUEST_NO_BODY,
*  REQUEST_CHUNKED_DECHUNK, etc...) */
int read_body;
/** reading chunked transfer-coding */
int read_chunked;
/** is client waiting for a 100 response? */
unsigned expecting_100;

/* MIME header environments, in and out.  Also, an array containing
* environment variables to be passed to subprocesses, so people can
* write modules to add to that environment.
*
* The difference between headers_out and err_headers_out is that the
* latter are printed even on error, and persist across internal redirects
* (so the headers printed for ErrorDocument handlers will have them).
*
* The 'notes' apr_table_t is for notes from one module to another, with no
* other set purpose in mind...
*/

/** MIME header environment from the request */
apr_table_t *headers_in;
/** MIME header environment for the response */
apr_table_t *headers_out;
/** MIME header environment for the response, printed even on errors and
* persist across internal redirects */
apr_table_t *err_headers_out;
/** Array of environment variables to be used for sub processes */
apr_table_t *subprocess_env;
/** Notes from one module to another */
apr_table_t *notes;

/* content_type, handler, content_encoding, and all content_languages
* MUST be lowercased strings.  They may be pointers to static strings;
* they should not be modified in place.
*/
/** The content-type for the current request */
const char *content_type;	/* Break these out --- we dispatch on 'em */
/** The handler string that we use to call a handler function */
const char *handler;	/* What we *really* dispatch on */

/** How to encode the data */
const char *content_encoding;
/** Array of strings representing the content languages */
apr_array_header_t *content_languages;

/** variant list validator (if negotiated) */
char *vlist_validator;

/** If an authentication check was made, this gets set to the user name. */
char *user;
/** If an authentication check was made, this gets set to the auth type. */
char *ap_auth_type;

/** This response can not be cached */
int no_cache;
/** There is no local copy of this response */
int no_local_copy;

/* What object is being requested (either directly, or via include
* or content-negotiation mapping).
*/

/** The URI without any parsing performed */
char *unparsed_uri;
/** The path portion of the URI, or "/" if no path provided */
char *uri;
/** The filename on disk corresponding to this response */
char *filename;
/* XXX: What does this mean? Please define "canonicalize" -aaron */
/** The true filename, we canonicalize r->filename if these don't match */
char *canonical_filename;
/** The PATH_INFO extracted from this request */
char *path_info;
/** The QUERY_ARGS extracted from this request */
char *args;
/**  finfo.protection (st_mode) set to zero if no such file */
apr_finfo_t finfo;
/** A struct containing the components of URI */
apr_uri_t parsed_uri;

/**
* Flag for the handler to accept or reject path_info on
* the current request.  All modules should respect the
* AP_REQ_ACCEPT_PATH_INFO and AP_REQ_REJECT_PATH_INFO
* values, while AP_REQ_DEFAULT_PATH_INFO indicates they
* may follow existing conventions.  This is set to the
* user's preference upon HOOK_VERY_FIRST of the fixups.
*/
int used_path_info;

/* Various other config info which may change with .htaccess files
* These are config vectors, with one void* pointer for each module
* (the thing pointed to being the module's business).
*/

/** Options set in config files, etc. */
struct ap_conf_vector_t *per_dir_config;
/** Notes on *this* request */
struct ap_conf_vector_t *request_config;

/**
* A linked list of the .htaccess configuration directives
* accessed by this request.
* N.B. always add to the head of the list, _never_ to the end.
* that way, a sub request's list can (temporarily) point to a parent's list
*/
const struct htaccess_result *htaccess;

/** A list of output filters to be used for this request */
struct ap_filter_t *output_filters;
/** A list of input filters to be used for this request */
struct ap_filter_t *input_filters;

/** A list of protocol level output filters to be used for this
*  request */
struct ap_filter_t *proto_output_filters;
/** A list of protocol level input filters to be used for this
*  request */
struct ap_filter_t *proto_input_filters;

/** A flag to determine if the eos bucket has been sent yet */
int eos_sent;

/* Things placed at the end of the record to avoid breaking binary
* compatibility.  It would be nice to remember to reorder the entire
* re
9182
cord to improve 64bit alignment the next time we need to break
* binary compatibility for some other reason.
*/

/** MIME trailer environment from the request */
apr_table_t *trailers_in;
/** MIME trailer environment from the response */
apr_table_t *trailers_out;
};


该结构体提供了各类请求的内容信息,并包含最重要的信息r->filename。在PHP环境启动后,与sapi.cli一样,通过php_execute_script/zend_execute_script进入了完全相同的过程。不同的只是对上层定义的函数指针进行了针对自己环境的实现而已。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: