NGINX源码中按需要修改发送的流的Content-Type值

在做CDN的项目中, 由于媒体文件没有后缀, NGINX不会自动根据mime.types来自动获取Content-Type的值,之前使用默认的Content-Type: application/octet-stream;  有部分客户端不会自己去识别流的格式, 不指定正确的Content-Type值无法播放文件,所以我只有修改NGINX源码来指定要发送的Content-Type值了。

记录下我修改的东西,方便以后查阅。


ngx_int_t  ngx_http_send_response(ngx_http_request_t *r, ngx_uint_t status, ngx_str_t *ct, ngx_http_complex_value_t *cv)
ngx_int_t  ngx_http_set_content_type(ngx_http_request_t *r)
r->uri 得到文件名, 查找   文件名.type


//GDB调试时得到的调用堆栈
Breakpoint 1, ngx_http_set_content_type (r=0x7e6760) at src/http/ngx_http_core_module.c:1750
1750        if (r->headers_out.content_type.len) {
(gdb) bt
#0  ngx_http_set_content_type (r=0x7e6760) at src/http/ngx_http_core_module.c:1750
#1  0x0000000000482704 in ngx_http_static_handler (r=0x7e6760) at src/http/modules/ngx_http_static_module.c:223
#2  0x00000000004546f1 in ngx_http_core_content_phase (r=0x7e6760, ph=0x80a3e8) at src/http/ngx_http_core_module.c:1414
#3  0x00000000004531d7 in ngx_http_core_run_phases (r=0x7e6760) at src/http/ngx_http_core_module.c:888
#4  0x000000000045314e in ngx_http_handler (r=0x7e6760) at src/http/ngx_http_core_module.c:871
#5  0x0000000000461604 in ngx_http_process_request (r=0x7e6760) at src/http/ngx_http_request.c:1694
#6  0x000000000046000f in ngx_http_process_request_headers (rev=0x80cef8) at src/http/ngx_http_request.c:1144
#7  0x000000000045f7c4 in ngx_http_process_request_line (rev=0x80cef8) at src/http/ngx_http_request.c:940
#8  0x000000000045e9ac in ngx_http_init_request (rev=0x80cef8) at src/http/ngx_http_request.c:524
#9  0x0000000000448d2a in ngx_epoll_process_events (cycle=0x7a1760, timer=60000, flags=1)
    at src/event/modules/ngx_epoll_module.c:683
#10 0x0000000000439738 in ngx_process_events_and_timers (cycle=0x7a1760) at src/event/ngx_event.c:247
#11 0x0000000000445916 in ngx_single_process_cycle (cycle=0x7a1760) at src/os/unix/ngx_process_cycle.c:316
#12 0x00000000004153e8 in main (argc=1, argv=0x7fffffffe548) at src/core/nginx.c:407



//修改下面这个函数即可
ngx_int_t
ngx_http_set_content_type(ngx_http_request_t *r)
{
    u_char                     c, *exten;
    ngx_str_t                 *type;
    ngx_uint_t                 i, hash;
    ngx_http_core_loc_conf_t  *clcf;

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

    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

    if (r->exten.len) {

        hash = 0;

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

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

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

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

                r->exten.data = exten;

                break;
            }

            hash = ngx_hash(hash, c);
        }

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

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

            return NGX_OK;
        }
    }

//性能影响就影响吧,只是为了做个功能测试,把Content-Type的值记录到一个文本文件里面,暂时没想到啥好的办法
/////////////////////处理Content-Type添加的代码////////////////////////////////////

        char url[1024]={0};
        strncpy (url, r->uri.data, r->uri.len);
        strcat (url, ".type");
        char filename[256]={0};
        snprintf (filename, sizeof(filename)-1, "../html%s", url);
        char stype[64]={0};
        FILE* fp = fopen (filename, "rb");
        if (fp != NULL)
        {
                fread (stype, sizeof(char), sizeof(stype), fp);
                fclose(fp);
                int slen = strlen(stype);
                char* sp = stype+slen;
                while (sp != stype)
                {
                        sp--;
                        if (*sp == '\r' || *sp == '\n' || *sp == ' ')
                                *sp = '\0';
                }
                ngx_str_t cnttype;
                cnttype.len = strlen(stype);
                cnttype.data = strdup(stype);
                r->headers_out.content_type_len = cnttype.len;
                r->headers_out.content_type = cnttype;
                return NGX_OK;
        }


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

    return NGX_OK;
}

这样当发送一个流的时候, NGINX会检查是否有对应的 "文件名.type" 文件, 没有还是按照默认的处理, 有的话,读取文件里的Content-Type值,进行发送。



你可能感兴趣的:(NGINX源码中按需要修改发送的流的Content-Type值)