-
Notifications
You must be signed in to change notification settings - Fork 72
/
GYMockURLProtocol.m
135 lines (111 loc) · 6.67 KB
/
GYMockURLProtocol.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
//
// GYNSURLProtocol.m
// GYNetwork
//
// Created by hypo on 16/1/13.
// Copyright © 2016年 hypoyao. All rights reserved.
//
#import "GYMockURLProtocol.h"
#import "GYHttpMock.h"
#import "GYMockResponse.h"
#import "GYHttpMock.h"
@interface NSHTTPURLResponse(UndocumentedInitializer)
- (id)initWithURL:(NSURL*)URL statusCode:(NSInteger)statusCode headerFields:(NSDictionary*)headerFields requestTime:(double)requestTime;
@end
@implementation GYMockURLProtocol
+ (BOOL)canInitWithRequest:(NSURLRequest *)request {
[[GYHttpMock sharedInstance] log:@"mock request: %@", request];
GYMockResponse* stubbedResponse = [[GYHttpMock sharedInstance] responseForRequest:(id<GYHTTPRequest>)request];
if (stubbedResponse && !stubbedResponse.shouldNotMockAgain) {
return YES;
}
return NO;
}
+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request {
return request;
}
+ (BOOL)requestIsCacheEquivalent:(NSURLRequest *)a toRequest:(NSURLRequest *)b {
return NO;
}
- (void)startLoading {
NSURLRequest* request = [self request];
id<NSURLProtocolClient> client = [self client];
GYMockResponse* stubbedResponse = [[GYHttpMock sharedInstance] responseForRequest:(id<GYHTTPRequest>)request];
if (stubbedResponse.shouldFail) {
[client URLProtocol:self didFailWithError:stubbedResponse.error];
}
else if (stubbedResponse.isUpdatePartResponseBody) {
stubbedResponse.shouldNotMockAgain = YES;
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
[NSURLConnection sendAsynchronousRequest:request
queue:queue
completionHandler:^(NSURLResponse *response, NSData *data, NSError *error){
if (error) {
NSLog(@"Httperror:%@%@", error.localizedDescription,@(error.code));
[client URLProtocol:self didFailWithError:[NSError errorWithDomain:NSCocoaErrorDomain code:NSUserCancelledError userInfo:nil]];
}else{
id json = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];
NSMutableDictionary *result = [NSMutableDictionary dictionaryWithDictionary:json];
if (!error && json) {
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:stubbedResponse.body options:NSJSONReadingMutableContainers error:nil];
[self addEntriesFromDictionary:dict to:result];
}
NSData *combinedData = [NSJSONSerialization dataWithJSONObject:result options:NSJSONWritingPrettyPrinted error:nil];
[client URLProtocol:self didReceiveResponse:response
cacheStoragePolicy:NSURLCacheStorageNotAllowed];
[client URLProtocol:self didLoadData:combinedData];
[client URLProtocolDidFinishLoading:self];
}
stubbedResponse.shouldNotMockAgain = NO;
}];
}
else {
NSHTTPURLResponse* urlResponse = [[NSHTTPURLResponse alloc] initWithURL:request.URL statusCode:stubbedResponse.statusCode HTTPVersion:@"1.1" headerFields:stubbedResponse.headers];
if (stubbedResponse.statusCode < 300 || stubbedResponse.statusCode > 399
|| stubbedResponse.statusCode == 304 || stubbedResponse.statusCode == 305 ) {
NSData *body = stubbedResponse.body;
[client URLProtocol:self didReceiveResponse:urlResponse
cacheStoragePolicy:NSURLCacheStorageNotAllowed];
[client URLProtocol:self didLoadData:body];
[client URLProtocolDidFinishLoading:self];
} else {
NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
[cookieStorage setCookies:[NSHTTPCookie cookiesWithResponseHeaderFields:stubbedResponse.headers forURL:request.URL]
forURL:request.URL mainDocumentURL:request.URL];
NSURL *newURL = [NSURL URLWithString:[stubbedResponse.headers objectForKey:@"Location"] relativeToURL:request.URL];
NSMutableURLRequest *redirectRequest = [NSMutableURLRequest requestWithURL:newURL];
[redirectRequest setAllHTTPHeaderFields:[NSHTTPCookie requestHeaderFieldsWithCookies:[cookieStorage cookiesForURL:newURL]]];
[client URLProtocol:self
wasRedirectedToRequest:redirectRequest
redirectResponse:urlResponse];
// According to: https://developer.apple.com/library/ios/samplecode/CustomHTTPProtocol/Listings/CustomHTTPProtocol_Core_Code_CustomHTTPProtocol_m.html
// needs to abort the original request
[client URLProtocol:self didFailWithError:[NSError errorWithDomain:NSCocoaErrorDomain code:NSUserCancelledError userInfo:nil]];
}
}
}
- (void)stopLoading {
}
- (void)addEntriesFromDictionary:(NSDictionary *)dict to:(NSMutableDictionary *)targetDict
{
for (NSString *key in dict) {
if (!targetDict[key] || [dict[key] isKindOfClass:[NSString class]] || [dict[key] isKindOfClass:[NSNumber class]]) {
[targetDict addEntriesFromDictionary:dict];
} else if ([dict[key] isKindOfClass:[NSArray class]]) {
NSMutableArray *mutableArray = [NSMutableArray array];
for (NSDictionary *targetArrayDict in targetDict[key]) {
NSMutableDictionary *mutableDict = [NSMutableDictionary dictionaryWithDictionary:targetArrayDict];
for (NSDictionary *arrayDict in dict[key]) {
[self addEntriesFromDictionary:arrayDict to:mutableDict];
}
[mutableArray addObject:mutableDict];
}
[targetDict setObject:mutableArray forKey:key];
} else if ([dict[key] isKindOfClass:[NSDictionary class]]) {
NSMutableDictionary *mutableDict = [NSMutableDictionary dictionaryWithDictionary:targetDict[key]];
[self addEntriesFromDictionary:dict[key] to:mutableDict];
[targetDict setObject:mutableDict forKey:key];
}
}
}
@end