1、提出问题
Domain=com.alamofire.error.serialization.response Code=-1016,unacceptable content-type: content-type: application/json。
这是一次调试中遇到的问题,首先我想到的是不是我在设置AFN 的这个属性的时候有问题_manager.responseSerializer.acceptableContentTypes
检查一下代码
_manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript", @"text/html", nil];
的确设置了application/json的属性啊,啥还是有问题的。但是我在抓包工具上的确看到的json数据,很费解,我试着去掉抓包工具,换个手机试试,用模拟器试试,慌乱的时候,总觉得是设备或者其他的问题。事实证明是愚蠢的。
2、代码调试
我想,解决问题的根本办法还是去代码里面看看吧,与是断点就跟到了这里
- (BOOL)validateResponse:(NSHTTPURLResponse *)response
data:(NSData *)data
error:(NSError * __autoreleasing *)error
{
BOOL responseIsValid = YES;
NSError *validationError = nil;
if (response && [response isKindOfClass:[NSHTTPURLResponse class]]) {
if (self.acceptableContentTypes && ![self.acceptableContentTypes containsObject:[response MIMEType]] &&
!([response MIMEType] == nil && [data length] == 0)) {
if ([data length] > 0 && [response URL]) {
NSMutableDictionary *mutableUserInfo = [@{
NSLocalizedDescriptionKey: [NSString stringWithFormat:NSLocalizedStringFromTable(@"Request failed: unacceptable content-type: %@", @"AFNetworking", nil), [response MIMEType]],
NSURLErrorFailingURLErrorKey:[response URL],
AFNetworkingOperationFailingURLResponseErrorKey: response,
} mutableCopy];
if (data) {
mutableUserInfo[AFNetworkingOperationFailingURLResponseDataErrorKey] = data;
}
validationError = AFErrorWithUnderlyingError([NSError errorWithDomain:AFURLResponseSerializationErrorDomain code:NSURLErrorCannotDecodeContentData userInfo:mutableUserInfo], validationError);
}
responseIsValid = NO;
}
if (self.acceptableStatusCodes && ![self.acceptableStatusCodes containsIndex:(NSUInteger)response.statusCode] && [response URL]) {
NSMutableDictionary *mutableUserInfo = [@{
NSLocalizedDescriptionKey: [NSString stringWithFormat:NSLocalizedStringFromTable(@"Request failed: %@ (%ld)", @"AFNetworking", nil), [NSHTTPURLResponse localizedStringForStatusCode:response.statusCode], (long)response.statusCode],
NSURLErrorFailingURLErrorKey:[response URL],
AFNetworkingOperationFailingURLResponseErrorKey: response,
} mutableCopy];
if (data) {
mutableUserInfo[AFNetworkingOperationFailingURLResponseDataErrorKey] = data;
}
validationError = AFErrorWithUnderlyingError([NSError errorWithDomain:AFURLResponseSerializationErrorDomain code:NSURLErrorBadServerResponse userInfo:mutableUserInfo], validationError);
responseIsValid = NO;
}
}
if (error && !responseIsValid) {
*error = validationError;
}
return responseIsValid;
}
在AFURLResponseSerialization文件中,116行,有这样一个判断
![self.acceptableContentTypes containsObject:[response MIMEType]]
,于是有了这样的[response MIMEType] = "content-type: application/json"
,好吧,服务器的哥们content type 设置成了"content-type: application/json",多了一个“content-type:”。问题找到了。自然解决也就是告诉他一下的事情。
3、 反思
为啥这个问题解决花了比较长的时间
- 遇到问题不仔细看日志,其实日志上写的很清晰
unacceptable content-type: content-type: application/json。
读的时候囫囵吞枣,只看后面没看前面 - 过分信任工具,觉得charles和安卓都能解析到、那么就是自己代码的问题。
- 基础知识不扎实,遇到问题不能一下定位清楚。想各种与之无关的方法去解决问题。
4、反思后
MIME, Mutipurpose Internet Mail Extensions,多用途 Internet 邮箱扩展。MIME 是描述消息内容类型的 internet 标准。在创建之初,是为了在发送电子邮件时附加多媒体数据,让邮件客户程序根据其类型进行处理。现在 MIME TYPE 被 HTTP 协议支持后,使得HTTP能够传输各种各样的文件。
浏览器与 MIME-TYPE
浏览器通过 MIME TYE,也就是该资源的媒体类型,来决定以什么形式显示数据。
媒体类型通常是通过 HTTP 协议,由 Web 服务器请求头中的 Content-Type 来告知浏览器数据类型的,比如:
Content-Type: text/HTML
表示内容是 text/HTML 类型,也就是超文本文件。注意,必须是 "text/HTML" 而不是 "HTML/text".因为 MIME 是经过 ietf 组织协商,以 RFC 的形式发布在网上的。
自定义的类型
需要注意的是:只有一些在互联网上获得广泛应用的格式才会获得一个 MIME Type,如果是某个客户端自己定义的格式,一般只能以 application/x- 开头。
Internet 中有一个专门组织来对 MIME 标准进行修订,但是由于 Internet 发展过快,很多应用程序便使用在类别中以 x- 开头的方法标识这个类别还没有成为标准,例如 x-gzip,x-tar等。
5 、后续计划
这几天遇到了很多网络知识不足造成的问题,所以计划恶补一下这块知识。