diff --git a/YuMi/Library/GZIP/NSData+GZIP.h b/YuMi/Library/GZIP/NSData+GZIP.h new file mode 100644 index 00000000..ac6a7886 --- /dev/null +++ b/YuMi/Library/GZIP/NSData+GZIP.h @@ -0,0 +1,43 @@ +// +// GZIP.h +// +// Version 1.3.2 +// +// Created by Nick Lockwood on 03/06/2012. +// Copyright (C) 2012 Charcoal Design +// +// Distributed under the permissive MIT license +// Get the latest version from here: +// +// https://github.com/nicklockwood/GZIP +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// + +#import + + +@interface NSData (GZIP) + +- (nullable NSData *)gzippedDataWithCompressionLevel:(float)level; +- (nullable NSData *)gzippedData; +- (nullable NSData *)gunzippedData; +- (BOOL)isGzippedData; + +@end diff --git a/YuMi/Library/GZIP/NSData+GZIP.m b/YuMi/Library/GZIP/NSData+GZIP.m new file mode 100644 index 00000000..e20a95c6 --- /dev/null +++ b/YuMi/Library/GZIP/NSData+GZIP.m @@ -0,0 +1,135 @@ +// +// GZIP.m +// +// Version 1.3.2 +// +// Created by Nick Lockwood on 03/06/2012. +// Copyright (C) 2012 Charcoal Design +// +// Distributed under the permissive MIT license +// Get the latest version from here: +// +// https://github.com/nicklockwood/GZIP +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// + +#import "NSData+GZIP.h" +#import + + +#pragma clang diagnostic ignored "-Wcast-qual" + + +@implementation NSData (GZIP) + +- (NSData *)gzippedDataWithCompressionLevel:(float)level +{ + if (self.length == 0 || [self isGzippedData]) + { + return self; + } + + z_stream stream; + stream.zalloc = Z_NULL; + stream.zfree = Z_NULL; + stream.opaque = Z_NULL; + stream.avail_in = (uint)self.length; + stream.next_in = (Bytef *)(void *)self.bytes; + stream.total_out = 0; + stream.avail_out = 0; + + static const NSUInteger ChunkSize = 16384; + + NSMutableData *output = nil; + int compression = (level < 0.0f)? Z_DEFAULT_COMPRESSION: (int)(roundf(level * 9)); + if (deflateInit2(&stream, compression, Z_DEFLATED, 31, 8, Z_DEFAULT_STRATEGY) == Z_OK) + { + output = [NSMutableData dataWithLength:ChunkSize]; + while (stream.avail_out == 0) + { + if (stream.total_out >= output.length) + { + output.length += ChunkSize; + } + stream.next_out = (uint8_t *)output.mutableBytes + stream.total_out; + stream.avail_out = (uInt)(output.length - stream.total_out); + deflate(&stream, Z_FINISH); + } + deflateEnd(&stream); + output.length = stream.total_out; + } + + return output; +} + +- (NSData *)gzippedData +{ + return [self gzippedDataWithCompressionLevel:-1.0f]; +} + +- (NSData *)gunzippedData +{ + if (self.length == 0 || ![self isGzippedData]) + { + return self; + } + + z_stream stream; + stream.zalloc = Z_NULL; + stream.zfree = Z_NULL; + stream.avail_in = (uint)self.length; + stream.next_in = (Bytef *)self.bytes; + stream.total_out = 0; + stream.avail_out = 0; + + NSMutableData *output = nil; + if (inflateInit2(&stream, 47) == Z_OK) + { + int status = Z_OK; + output = [NSMutableData dataWithCapacity:self.length * 2]; + while (status == Z_OK) + { + if (stream.total_out >= output.length) + { + output.length += self.length / 2; + } + stream.next_out = (uint8_t *)output.mutableBytes + stream.total_out; + stream.avail_out = (uInt)(output.length - stream.total_out); + status = inflate (&stream, Z_SYNC_FLUSH); + } + if (inflateEnd(&stream) == Z_OK) + { + if (status == Z_STREAM_END) + { + output.length = stream.total_out; + } + } + } + + return output; +} + +- (BOOL)isGzippedData +{ + const UInt8 *bytes = (const UInt8 *)self.bytes; + return (self.length >= 2 && bytes[0] == 0x1f && bytes[1] == 0x8b); +} + +@end diff --git a/YuMi/Modules/YMNewHome/View/XPNewHomeViewController.m b/YuMi/Modules/YMNewHome/View/XPNewHomeViewController.m index 69b9f0ae..8391fde9 100644 --- a/YuMi/Modules/YMNewHome/View/XPNewHomeViewController.m +++ b/YuMi/Modules/YMNewHome/View/XPNewHomeViewController.m @@ -200,7 +200,7 @@ UIKIT_EXTERN NSString * const kOpenRoomNotification; if (tabArray == nil) { tabArray = @[]; } - self.tabArray = tabArray; + _tabArray = tabArray; // 如果 tab items 总长度到达或超过边缘,要显示箭头按钮 if (46 * self.tabArray.count + 12 * (self.tabArray.count-1) > KScreenWidth-30) { self.gradientMask.hidden = NO; @@ -217,8 +217,8 @@ UIKIT_EXTERN NSString * const kOpenRoomNotification; return; } - if (self.tabArray.count > 0) { - if (self.lastSelectedIndex > -1 && self.lastSelectedIndex < self.tabArray.count - 1) { + if (tabArray.count > 0) { + if (self.lastSelectedIndex > -1 && self.lastSelectedIndex < tabArray.count - 1) { [self.tabCollectionView selectItemAtIndexPath:[NSIndexPath indexPathForRow:self.lastSelectedIndex inSection:0] animated:NO scrollPosition:UICollectionViewScrollPositionNone]; diff --git a/YuMi/Modules/YMRoom/View/StageView/StageView.m b/YuMi/Modules/YMRoom/View/StageView/StageView.m index cdb4fea3..12e21430 100644 --- a/YuMi/Modules/YMRoom/View/StageView/StageView.m +++ b/YuMi/Modules/YMRoom/View/StageView/StageView.m @@ -703,7 +703,7 @@ [self giftValueUpdate:attachment.data]; } else if(attachment.first == CustomMessageType_Gift && (attachment.second == Custom_Message_Sub_Gift_Send || attachment.second == Custom_Message_Sub_Gift_LuckySend || attachment.second == Custom_Message_Sub_Gift_ChannelNotify)) { [self giftValueUpdate:attachment.data]; - }else if(attachment.first == CustomMessageType_AllMicroSend && (attachment.second == Custom_Message_Sub_AllMicroSend || attachment.second == Custom_Message_Sub_AllBatchSend || attachment.second == Custom_Message_Sub_AllMicroLuckySend || attachment.second == Custom_Message_Sub_AllBatchMicroLuckySend)) { + } else if(attachment.first == CustomMessageType_AllMicroSend && (attachment.second == Custom_Message_Sub_AllMicroSend || attachment.second == Custom_Message_Sub_AllBatchSend || attachment.second == Custom_Message_Sub_AllMicroLuckySend || attachment.second == Custom_Message_Sub_AllBatchMicroLuckySend)) { [self giftValueUpdate:attachment.data]; } else if (attachment.first == CustomMessageType_Face && attachment.second == Custom_Message_Sub_Face_Send) { [self showUserFace:attachment.data]; diff --git a/YuMi/Modules/YMTabbar/Api/Api+Main.m b/YuMi/Modules/YMTabbar/Api/Api+Main.m index 928733f4..73770a88 100644 --- a/YuMi/Modules/YMTabbar/Api/Api+Main.m +++ b/YuMi/Modules/YMTabbar/Api/Api+Main.m @@ -55,7 +55,7 @@ } + (void)clientConfig:(HttpRequestHelperCompletion)completion { - [HttpRequestHelper request:@"client/config" method:HttpRequestHelperMethodGET params:@{@"timeoutInterval":@(10)} completion:completion]; + [HttpRequestHelper request:@"client/config" method:HttpRequestHelperMethodGET params:@{@"NeedChangeTimeOut":@(10)} completion:completion]; } diff --git a/YuMi/Modules/YMTabbar/View/TabbarViewController.m b/YuMi/Modules/YMTabbar/View/TabbarViewController.m index 03981005..a719ef39 100644 --- a/YuMi/Modules/YMTabbar/View/TabbarViewController.m +++ b/YuMi/Modules/YMTabbar/View/TabbarViewController.m @@ -444,7 +444,7 @@ UIKIT_EXTERN NSString *kTabShowAnchorCardKey; #pragma mark - app 启动调用此接口 主要功能: 给主播分流 - (void)clientStartApp { - // [self.presenter clientStartApp]; +// [self.presenter clientStartApp]; } #pragma mark - BaseMvpProtocol diff --git a/YuMi/Network/HttpRequestHelper.h b/YuMi/Network/HttpRequestHelper.h index 44d156ea..9b63caca 100644 --- a/YuMi/Network/HttpRequestHelper.h +++ b/YuMi/Network/HttpRequestHelper.h @@ -22,7 +22,7 @@ NS_ASSUME_NONNULL_BEGIN @interface HttpRequestHelper : NSObject +(NSString *)getHostUrl; -+ (NSDictionary*)configBaseParmars:(NSDictionary *)parmars; ++ (NSDictionary*)configBaseParmars:(NSDictionary * _Nullable)parmars; + (void)GET:(NSString *)method params:(NSDictionary *)params diff --git a/YuMi/Network/HttpRequestHelper.m b/YuMi/Network/HttpRequestHelper.m index dada9761..c5774d66 100644 --- a/YuMi/Network/HttpRequestHelper.m +++ b/YuMi/Network/HttpRequestHelper.m @@ -12,7 +12,7 @@ #import #import "YUMIMacroUitls.h" #import "MSParamsDecode.h" - +#import "NSData+GZIP.h" @implementation HttpRequestHelper @@ -21,17 +21,32 @@ static AFHTTPSessionManager *manager = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ - manager = [[AFHTTPSessionManager manager]initWithBaseURL:[NSURL URLWithString:[HttpRequestHelper getHostUrl]]]; + NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; + configuration.HTTPShouldUsePipelining = YES; // 启用 HTTP/2 pipelining + configuration.HTTPMaximumConnectionsPerHost = 5; // 提升并发 + + manager = [[AFHTTPSessionManager alloc] initWithBaseURL:[NSURL URLWithString:[HttpRequestHelper getHostUrl]] + sessionConfiguration:configuration]; + manager.responseSerializer = [AFJSONResponseSerializer serializer]; + manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects: + @"application/json", + @"text/json", + @"text/javascript", + @"text/html", + @"text/plain", + @"image/jpeg", + @"image/png", nil]; + manager.requestSerializer.HTTPShouldHandleCookies = YES; - // 客户端是否信任非法证书 - manager.securityPolicy.allowInvalidCertificates = YES; - AFSecurityPolicy *securityPolicy= [AFSecurityPolicy defaultPolicy]; - manager.securityPolicy = securityPolicy; - // 是否在证书域字段中验证域名 - [manager.securityPolicy setValidatesDomainName:NO]; - manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript",@"text/html",@"text/plain",@"image/jpeg",@"image/png", nil]; manager.requestSerializer.timeoutInterval = 60; + // 声明开启 gzip 和 br + [manager.requestSerializer setValue:@"gzip, br" forHTTPHeaderField:@"Accept-Encoding"]; + + // 确保所有请求走 HTTPS,避免降级到 HTTP/1.1 + manager.securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone]; + manager.securityPolicy.allowInvalidCertificates = NO; + manager.securityPolicy.validatesDomainName = YES; }); return manager; } @@ -51,10 +66,9 @@ success:(void (^)(BaseModel *data))success failure:(void (^)(NSInteger resCode, NSString *message))failure { - if ([AFNetworkReachabilityManager sharedManager].networkReachabilityStatus == 0) { - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ - failure(-1, YMLocalizedString(@"HttpRequestHelper0")); - }); + if ([self checkNetworkStatusWithFailure:^{ + failure(-1, YMLocalizedString(@"HttpRequestHelper0")); + }]) { return; } @@ -62,12 +76,11 @@ AFHTTPSessionManager *manager = [HttpRequestHelper requestManager]; - NSString *key = @"timeoutInterval"; - if ([params.allKeys containsObject:key]) { - NSInteger timeout = [[params objectForKey:key] integerValue]; - NSMutableDictionary *filteredDictionary = [params mutableCopy]; - [filteredDictionary removeObjectForKey:key]; - params = filteredDictionary.copy; + NSString *key = @"NeedChangeTimeOut"; + NSMutableDictionary *editParam = [params mutableCopy]; + if ([editParam.allKeys containsObject:key]) { + NSInteger timeout = [[editParam objectForKey:key] integerValue]; + [editParam removeObjectForKey:key]; if (timeout > 0) { manager.requestSerializer.timeoutInterval = timeout; } @@ -76,24 +89,22 @@ manager.requestSerializer.timeoutInterval = 60; } - params = [MSParamsDecode msDecodeParams:[params mutableCopy] ]; - params = [self configBaseParmars:params]; - + editParam = [MSParamsDecode msDecodeParams:editParam]; + params = [self configBaseParmars:editParam]; #ifdef DEBUG NSLog(@"\nmethod:\n%@\nparameter:\n%@", method, params); #endif - + @kWeakify(self); [manager GET:method parameters:params headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { BaseModel *baseModel = [BaseModel modelWithDictionary:responseObject]; - #ifdef DEBUG - NSLog(@"\n%@", [baseModel toJSONString]); + NSLog(@"%@ - \n%@", method, [baseModel toJSONString]); #else #endif - success(baseModel); } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { + @kStrongify(self); [self handleNetError:error method:method failure:failure]; }]; } @@ -103,18 +114,15 @@ success:(void (^)(BaseModel *data))success failure:(void (^)(NSInteger resCode, NSString *message))failure { - if ([AFNetworkReachabilityManager sharedManager].networkReachabilityStatus == 0) { - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ - failure(-1, YMLocalizedString(@"HttpRequestHelper0")); - }); + if ([self checkNetworkStatusWithFailure:^{ + failure(-1, YMLocalizedString(@"HttpRequestHelper0")); + }]) { return; } [self configHeaders]; AFHTTPSessionManager *manager = [HttpRequestHelper requestManager]; params = [MSParamsDecode msDecodeParams:[params mutableCopy] ]; - - params = [self configBaseParmars:params]; #ifdef DEBUG @@ -122,15 +130,28 @@ #else #endif - [manager POST:method parameters:params headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { + // 将 NSDictionary 转换为 JSON + NSData *jsonData = [NSJSONSerialization dataWithJSONObject:params options:0 error:nil]; + + // Gzip 压缩数据 + NSData *gzipData = [jsonData gzippedData]; + @kWeakify(self); + [manager POST:method + parameters:params + headers:nil +constructingBodyWithBlock:^(id _Nonnull formData) { + [formData appendPartWithFormData:gzipData name:@"data"]; + } + progress:nil + success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { BaseModel *baseModel = [BaseModel modelWithDictionary:responseObject]; #ifdef DEBUG NSLog(@"\n%@", [baseModel toJSONString]); #else #endif - success(baseModel); } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { + @kStrongify(self); [self handleNetError:error method:method failure:failure]; }]; } @@ -140,14 +161,11 @@ success:(void (^)(BaseModel *data))success failure:(void (^)(NSInteger resCode, NSString *message))failure { - if ([AFNetworkReachabilityManager sharedManager].networkReachabilityStatus == 0) { - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ - failure(-1, YMLocalizedString(@"HttpRequestHelper0")); - - }); + if ([self checkNetworkStatusWithFailure:^{ + failure(-1, YMLocalizedString(@"HttpRequestHelper0")); + }]) { return; } - [self configHeaders]; params = [MSParamsDecode msDecodeParams:[params mutableCopy] ]; params = [self configBaseParmars:params]; @@ -156,16 +174,16 @@ NSLog(@"\nmethod:\n%@\nparameter:\n%@", method, params); #else #endif - + @kWeakify(self); [manager DELETE:method parameters:params headers:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { BaseModel *baseModel = [BaseModel modelWithDictionary:responseObject]; - #ifdef DEBUG NSLog(@"\n%@", [baseModel toJSONString]); #else #endif success(baseModel); } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { + @kStrongify(self); [self handleNetError:error method:method failure:failure]; }]; } @@ -225,7 +243,7 @@ [client.requestSerializer setValue:PI_App_Version forHTTPHeaderField:@"App-Version"]; } -+ (NSDictionary*)configBaseParmars:(NSDictionary *)parmars ++ (NSDictionary*)configBaseParmars:(NSDictionary * _Nullable)parmars { NSDictionary *defaultBasciParame = @{ @"Accept-Language":[NSBundle uploadLanguageText], @@ -239,7 +257,6 @@ @"appVersion" : [YYUtility appVersion], @"app" : [YYUtility appName], @"lang" : [YYUtility getLanguage], - }; if (!parmars||![parmars isKindOfClass:[NSDictionary class]]){ @@ -254,9 +271,7 @@ if(![[YYUtility getMobileCountryCode] isEqualToString:@"65535"]){ [dic setValue:[YYUtility getMobileCountryCode] forKey:@"mcc"]; } - for (NSString *parameKey in defaultBasciParame.allKeys) { - [dic setObject:defaultBasciParame[parameKey] forKey:parameKey]; - } + [dic addEntriesFromDictionary:defaultBasciParame]; return dic; } @@ -268,20 +283,12 @@ NSString *NETWORK_ERROR = error.description.length > 0 ? error.description : YMLocalizedString(@"HttpRequestHelper5");; if (response && response.statusCode == 401) { failure(response.statusCode, YMLocalizedString(@"HttpRequestHelper7")); - } else { - if (error.code == -1009 || error.code == -1001 || error.code == -1004 || error.code == -1003 || error.code == -1002 || error.code == 3840) { failure(error.code, @""); } else { failure(error.code, error.localizedDescription.length > 0 ? error.localizedDescription : YMLocalizedString(@"HttpRequestHelper4")); } - NSString * code = error.code ? [NSString stringWithFormat:@"%ld", error.code] : @"9999"; - NSString * des = error.description.length > 0 ? error.description : YMLocalizedString(@"HttpRequestHelper5"); - NSException *exception = [NSException exceptionWithName:@"229181" - reason:method - userInfo:@{@"code":code, @"desc":des}]; - } #ifdef DEBUG NSLog(@"\n%@", error); @@ -305,10 +312,9 @@ params:(NSString *)params completion:(HttpRequestHelperCompletion)completion{ - if ([AFNetworkReachabilityManager sharedManager].networkReachabilityStatus == 0) { - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ - completion(nil, -1, YMLocalizedString(@"HttpRequestHelper0")); - }); + if ([self checkNetworkStatusWithFailure:^{ + completion(nil, -1, YMLocalizedString(@"HttpRequestHelper0")); + }]) { return; } @@ -357,7 +363,6 @@ [request setValue:PI_App_Version forHTTPHeaderField:@"App-Version"]; [manager.requestSerializer setValue:[NSBundle uploadLanguageText] forHTTPHeaderField:@"Accept-Language"]; [manager.requestSerializer setValue:PI_App_Version forHTTPHeaderField:@"App-Version"]; - NSError *error; [request setHTTPBody:[params dataUsingEncoding:NSUTF8StringEncoding]]; @@ -371,9 +376,8 @@ #endif if (baseModel.code == 200) { #ifdef DEBUG - - NSHTTPURLResponse *response = response; - NSDictionary *allHeaders = response.allHeaderFields; + NSHTTPURLResponse *urlresponse = (NSHTTPURLResponse *)response; + NSDictionary *allHeaders = urlresponse.allHeaderFields; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ [BSNetListenModel addHttpRsp:urlPath header:allHeaders result:baseModel.data isSuccess:YES time:[NSDate getCurrentTimeWithFormat:@"yyyy-MM-dd HH:mm:ss"]]; }); @@ -396,4 +400,16 @@ }] resume]; } ++ (BOOL)checkNetworkStatusWithFailure:(void (^)(void))failure { + if ([AFNetworkReachabilityManager sharedManager].networkReachabilityStatus == AFNetworkReachabilityStatusNotReachable) { + if (failure) { + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + failure(); + }); + } + return YES; + } + return NO; +} + @end