Content-Type初探

Content-Type初探

事情背景

有运营反馈用户打开微信群内的投放链接不能正常显示,显示的是乱码(其实是HTML的代码),错误如图所示:

这种异常的原因是服务返回的Content-Type是text/plain类型,不是text/html类型,导致页面无法正常渲染。

复现问题

投放的链接用的是CDN域名,而且用户再次打开就又可以,联系CDN同事先进行问题确认。查看用户反馈时间点前后的CDN日志,可以看到sent_http_content_type(返回给用户)有两种类型的返回。

Chrome有个ModHeader插件,可以修改请求和返回的header值,修改Response headers中Content-Type为text/plain;charset=UTF-8,可以复现用户的问题,如下图:

排查问题

CDN节点日志中获取的sent_http_content_type来自于源站返回的Content-Type,需要测试一下源站的返回,使用Python脚本进行测试,脚本内容如下:

# -*- coding:utf-8 -*-

import json
import requests
import socket


headers = {
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
    'Accept-Encoding': 'gzip, deflate, br',
    'Accept-Language': 'zh-CN,zh;q=0.9',
    'Cache-Control': 'no-cache',
    'Pragma': 'cache',
    'sec-ch-ua': '"Chromium";v="92", " Not A;Brand";v="99", "Google Chrome";v="92"',
    'sec-ch-ua-mobile': '?0',
    'Sec-Ch-Ua-Platform': '"macOS"',
    'Sec-Fetch-Dest': 'document',
    'Sec-Fetch-Mode': 'navigate',
    'Sec-Fetch-Site': 'none',
    'Sec-Fetch-User': '?1',
    'Upgrade-Insecure-Requests': '1',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36'
}


# 替换为你想要获取IP的域名
domain = "投放链接域名"

ip = socket.gethostbyname(domain)
print(f"The IP address of {domain} is: {ip}")


# 构建URL
url = 'https://投放链接地址'
 
# 发送GET请求
response = requests.get(url, headers=headers)
 
# 输出响应内容
content_type = response.headers.get('Content-Type')
print('Content-Type:', content_type)

1、去掉Host,进行测试,请求的是CDN的节点,Content-Type结果都是text/html类型

2、绑定Host,请求的是源站节点,Content-Type结果也都是text/html类型

按正常的请求方式无法复现Content-Type结果text/plain类型,使用curl方式不带任何Request header可以复现Content-Type结果text/plain类型的现象,如下图:

可以怀疑是用户侧发起的请求Request headers中某个header为空导致的,查阅资料和排查,发现如果请求中如果header头Accept为空则Content-Type返回的是text/plain。

Accept属于http请求头,描述客户端希望接收的响应body 数据类型。就是希望服务器返回什么类型的数据。

text/html : HTML格式
text/plain :纯文本格式
text/xml : XML格式
image/gif :gif图片格式
image/jpeg :jpg图片格式
image/png:png图片格式
video/mpeg:视频
vedio/quicktime:视频
application/xhtml+xml :XHTML格式
application/xml : XML数据格式
application/atom+xml :Atom XML聚合格式
application/json : JSON数据格式
application/pdf :pdf格式
application/msword : Word文档格式
application/octet-stream : 二进制流数据(如常见的文件下载)
application/x-www-form-urlencoded : < form encType=””>中默认的encType,form表单数据被编码为key/value格式发送到服务器(表单默认的提交数据的格式)

下一步就是进行验证怀疑,curl请求中header头Accept设置为text/html,可以看到服务端返回的Content-Type则是text/html,下图所示:

找CDN同事继续查看日志,果然可以看到有请求的Accept是-(也就是空值),引起错误的原因找到了。

解决问题

解决起来比较简单了,可以在CDN或者源站服务这边加一下返回的Content-Type设置为text/html,和开发同学沟通后这个服务不需要JSON的返回,服务侧修改起来也比较方便可控。更新服务后curl请求可以看到Content-Type结果是text/html;charset=utf-8,问题得到解决。

写在最后

周一工作不怎么顺利,突然想起一个词”动辄得咎“,后面需要思考下。但是在这个问题的排查、验证过程中收获颇丰,有点”塞翁失马,焉知非福“的感觉,也感谢一直配合的研发和CDN同学。

留下回复

error: Content is protected !!