apache 学习笔记 之 周边工具(1)apr_uri_t

一直想好好分析apache的源代码,今天闲来无聊就作为一个开端,分析一个简单的:apr_uri_t。
正好这个是之前做一个项目的时候接触比较深的,apr_url是作为apr(apache portable runtime)的的一部分,
主要功能是解析url,如http://www.kimnote.com这样的字符串。
先介绍一下java里的对应功能的类。java.net.URI

apr_uri相关的文件具体位置如下:
include:apache目录下的srclib/apr-util/include/apr_uri.h
实现文件:apache目录下的srclib/apr-util/uri/apr_uri.c

先看看宏定义

#define APR_URI_FTP_DEFAULT_PORT         <strong>21</strong> /**&lt; default FTP port */
#define APR_URI_SSH_DEFAULT_PORT         <strong>22</strong> /**&lt; default SSH port */
#define APR_URI_TELNET_DEFAULT_PORT      <strong>23</strong> /**&lt; default telnet port */
#define APR_URI_GOPHER_DEFAULT_PORT      70 /**&lt; default Gopher port */
#define APR_URI_HTTP_DEFAULT_PORT        <strong>80</strong> /**&lt; default HTTP port */
#define APR_URI_POP_DEFAULT_PORT        110 /**&lt; default POP port */
#define APR_URI_NNTP_DEFAULT_PORT       119 /**&lt; default NNTP port */
#define APR_URI_IMAP_DEFAULT_PORT       143 /**&lt; default IMAP port */
#define APR_URI_PROSPERO_DEFAULT_PORT   191 /**&lt; default Prospero port */
#define APR_URI_WAIS_DEFAULT_PORT       210 /**&lt; default WAIS port */
#define APR_URI_LDAP_DEFAULT_PORT       389 /**&lt; default LDAP port */
#define APR_URI_HTTPS_DEFAULT_PORT      443 /**&lt; default HTTPS port */
#define APR_URI_RTSP_DEFAULT_PORT       554 /**&lt; default RTSP port */
#define APR_URI_SNEWS_DEFAULT_PORT      563 /**&lt; default SNEWS port */
#define APR_URI_ACAP_DEFAULT_PORT       674 /**&lt; default ACAP port */
#define APR_URI_NFS_DEFAULT_PORT       2049 /**&lt; default NFS port */
#define APR_URI_TIP_DEFAULT_PORT       3372 /**&lt; default TIP port */
#define APR_URI_SIP_DEFAULT_PORT       5060 /**&lt; default SIP port */

 结构体

拿 “ftp://admin:admpass@kimnote.com:2323/path/file.txt?from=test#anchor”这个url为例说明。

struct apr_uri_t {
    /** scheme ("http"/"ftp"/...) 协议部分*/
    char *scheme;//ftp
    /** combined [user[:password]\@]host[:port] 如果是ftp*/
    char *hostinfo;//admin:admpass@kimnote.com:2323
    /** user name, as in http://user:passwd\@host:port/ */
    char *user;//admin
    /** password, as in http://user:passwd\@host:port/ */
    char *password;//pass
    /** hostname from URI (or from Host: header) */
    char *hostname;//kimnote.com
    /** port string (integer representation is in "port") */
    char *port_str;//2323
    /** the request path (or NULL if only scheme://host was given) */
    char *path;//path/file.txt
    /** Everything after a '?' in the path, if present */
    char *query;//from=test
    /** Trailing "#fragment" string, if present */
    char *fragment;//anchor

    /** structure returned from gethostbyname() */
    struct hostent *hostent;

    /** The port number, numeric, valid only if port_str != NULL */
    apr_port_t port;//2323

    /** has the structure been initialized */
    unsigned is_initialized:1;

    /** has the DNS been looked up yet */
    unsigned dns_looked_up:1;
    /** has the dns been resolved yet */
    unsigned dns_resolved:1;
};

 方法定义

APU_DECLARE(apr_port_t) apr_uri_port_of_scheme(const char *scheme_str);
APU_DECLARE(char *) apr_uri_unparse(apr_pool_t *p, const apr_uri_t *uptr,unsigned flags);
APU_DECLARE(apr_status_t) apr_uri_parse(apr_pool_t *p, const char *uri, apr_uri_t *uptr);
APU_DECLARE(apr_status_t) apr_uri_parse_hostinfo(apr_pool_t *p, const char *hostinfo, apr_uri_t *uptr);

一个一个看。

apr_uri_port_of_scheme

APU_DECLARE(apr_port_t) apr_uri_port_of_scheme(const char *scheme_str)
{
    schemes_t *scheme;

    if (scheme_str) {
        for (scheme = schemes; scheme-&gt;name != NULL; ++scheme) {
            if (<strong>strcasecmp</strong>(scheme_str, scheme-&gt;name) == 0) {
                return scheme-&gt;default_port;
            }
        }
    }
    return 0;
}
struct schemes_t {
    /** The name of the scheme */
    const char *name; 
    /** The default port for the scheme */
    apr_port_t default_port;
}; 
static schemes_t schemes[] =
{
    {"http",     APR_URI_HTTP_DEFAULT_PORT},
    {"ftp",      APR_URI_FTP_DEFAULT_PORT},
    {"https",    APR_URI_HTTPS_DEFAULT_PORT},
    {"gopher",   APR_URI_GOPHER_DEFAULT_PORT},
    {"ldap",     APR_URI_LDAP_DEFAULT_PORT},
    {"nntp",     APR_URI_NNTP_DEFAULT_PORT},
    {"snews",    APR_URI_SNEWS_DEFAULT_PORT},
    {"imap",     APR_URI_IMAP_DEFAULT_PORT},
    {"pop",      APR_URI_POP_DEFAULT_PORT},
    {"sip",      APR_URI_SIP_DEFAULT_PORT},
    {"rtsp",     APR_URI_RTSP_DEFAULT_PORT},
    {"wais",     APR_URI_WAIS_DEFAULT_PORT},
    {"z39.50r",  APR_URI_WAIS_DEFAULT_PORT},
    {"z39.50s",  APR_URI_WAIS_DEFAULT_PORT},
    {"prospero", APR_URI_PROSPERO_DEFAULT_PORT},
    {"nfs",      APR_URI_NFS_DEFAULT_PORT},
    {"tip",      APR_URI_TIP_DEFAULT_PORT},
    {"acap",     APR_URI_ACAP_DEFAULT_PORT},
    {"telnet",   APR_URI_TELNET_DEFAULT_PORT},
    {"ssh",      APR_URI_SSH_DEFAULT_PORT},
    { NULL, 0xFFFF }     /* unknown port */
};

 apr_uri_unparse方法

从apr_uri_t结构体恢复到url格式。注意flag参数,根据flag参数的不一样得到的结果也是不一样的。

/** Flags passed to unparse_uri_components(): */
/** suppress "scheme://user\@site:port" */
#define APR_URI_UNP_OMITSITEPART    (1U&lt;&lt;0)
/** Just omit user */
#define APR_URI_UNP_OMITUSER        (1U&lt;&lt;1)
/** Just omit password */
#define APR_URI_UNP_OMITPASSWORD    (1U&lt;&lt;2)
/** omit "user:password\@" part */
#define APR_URI_UNP_OMITUSERINFO    (APR_URI_UNP_OMITUSER | \
                                     APR_URI_UNP_OMITPASSWORD)
/** Show plain text password (default: show XXXXXXXX) */
#define APR_URI_UNP_REVEALPASSWORD  (1U&lt;&lt;3)
/** Show "scheme://user\@site:port" only */
#define APR_URI_UNP_OMITPATHINFO    (1U&lt;&lt;4)
/** Omit the "?queryarg" from the path */
#define APR_URI_UNP_OMITQUERY       (1U&lt;&lt;5)

 apr_uri_parse方法

把url解析到apr_uri_t结构体。

apr_uri_parse_hostinfo方法

/* Special case for CONNECT parsing: it comes with the hostinfo part only */
/* See the INTERNET-DRAFT document "Tunneling SSL Through a WWW Proxy"
 * currently at http://www.mcom.com/newsref/std/tunneling_ssl.html
 * for the format of the "CONNECT host:port HTTP/1.0" request
 */

可以看到专为connect请求解析hostinfo部分。

发表评论

电子邮件地址不会被公开。 必填项已用 * 标注

您可以使用这些 HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>