在做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值,进行发送。