Nginx 对字符串编码函数解析

本文介绍了Nginx中ngx_escape_uri函数的工作原理,详细解释了如何使用位图判断特定字符是否需要进行URI编码转换,并提供了核心源码片段。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Nginx 对字符串编码函数解析

Nginx函数ngx_escape_uri对非普通字符进行编码转换,源码如下:

ngx_escape_uri(u_char *dst, u_char *src, size_t size, ngx_uint_t type)
{
    ngx_uint_t      n;
    uint32_t       *escape;
    static u_char   hex[] = "0123456789ABCDEF";

                    /* " ", "#", "%", "?", %00-%1F, %7F-%FF */
    static uint32_t   uri[] = {
        0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
                    /* ?>=< ;:98 7654 3210  /.-, +*)( '&%$ #"!  */
        0x80000029, /* 1000 0000 0000 0000  0000 0000 0010 1001 */
                    /* _^]\ [ZYX WVUT SRQP  ONML KJIH GFED CBA@ */
        0x00000000, /* 0000 0000 0000 0000  0000 0000 0000 0000 */
                    /*  ~}| {zyx wvut srqp  onml kjih gfed cba` */
        0x80000000, /* 1000 0000 0000 0000  0000 0000 0000 0000 */
        0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
        0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
        0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
        0xffffffff  /* 1111 1111 1111 1111  1111 1111 1111 1111 */
    };
    ...
    ...
    static uint32_t  *map[] =
        { uri, args, uri_component, html, refresh, memcached, memcached };

    escape = map[type];

    if (dst == NULL) {
        /* find the number of the characters to be escaped */
        n = 0;
        while (size) {
            if (escape[*src >> 5] & (1U << (*src & 0x1f))) {
                n++;
            }
            src++;
            size--;
        }
        return (uintptr_t) n;
    }
    while (size) {
        if (escape[*src >> 5] & (1U << (*src & 0x1f))) {
            *dst++ = '%';
            *dst++ = hex[*src >> 4];
            *dst++ = hex[*src & 0xf];
            src++;
        } else {
            *dst++ = *src++;
        }
        size--;
    }
    return (uintptr_t) dst;
}

在上述函数中利用位图来判断是否需要编码,其中static uint32_t uri[]用0和1来表示ASCII码表中的字符是否需要编码,每一位表示一个符号,其中值为1表示此符号需要转换,值为0表示不需要转换。
然后利用(escape[*src >> 5] & (1U << (*src & 0x1f)))来判断字符是否需要编码,这个判断分为两步:一是利用escape[*src >> 5] 获取字符所在的分组,注意到uri[]把256个字符分为8组,每组32个字符,所以利用表示字符的ASCII码右移5位(相当于除以32)即可得到所在分组;二是利用1U << (*src & 0x1f)获取字符在分组中的位置,*src & 0x1f相当于利用表示字符的ASCII码对32取余,然后1左移该余数即可得到字符在分组中的位置,最后根据该位置是0还是1来判断是否需要编码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值