-
Notifications
You must be signed in to change notification settings - Fork 265
Expand file tree
/
Copy pathOneSignalRequest.m
More file actions
167 lines (133 loc) · 6.7 KB
/
Copy pathOneSignalRequest.m
File metadata and controls
167 lines (133 loc) · 6.7 KB
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
/**
* Modified MIT License
*
* Copyright 2017 OneSignal
*
* 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:
*
* 1. The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* 2. All copies of substantial portions of the Software may only be used in connection
* with services provided by OneSignal.
*
* 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 "OneSignalRequest.h"
#import "OneSignalCommonDefines.h"
#import "OneSignalLog.h"
#import "OneSignalWrapper.h"
#import "OneSignalVersion.h"
#define HTTP_HEADER_KEY_OS_VERSION @"SDK-Version"
#define HTTP_HEADER_KEY_OS_WRAPPER @"SDK-Wrapper"
#define HTTP_HEADER_PREFIX_OS_VERSION @"onesignal/ios/"
@implementation OneSignalRequest
- (id)init {
if (self = [super init]) {
self.reattemptCount = 0;
// sets default values that are true for most requests
// the following parameters can be overridden by subclasses
self.disableLocalCaching = false;
// Most requests in our SDK are API requests that return JSON
// However some requests want to load non-JSON data like HTML
// In those cases, `dataRequest` should be true
self.dataRequest = false;
self.timestamp = [NSDate date];
}
return self;
}
-(NSMutableURLRequest *)urlRequest {
//build URL
NSString *urlString = [OS_API_SERVER_URL stringByAppendingString:self.path];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlString]];
for (NSString *key in self.additionalHeaders) {
[request setValue:self.additionalHeaders[key] forHTTPHeaderField:key];
}
if (!self.dataRequest)
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setValue:OS_API_ACCEPT_HEADER forHTTPHeaderField:@"Accept"];
NSString *versionString = [NSString stringWithFormat:@"%@%@", HTTP_HEADER_PREFIX_OS_VERSION, OneSignalVersion.numeric];
[request setValue:versionString forHTTPHeaderField:HTTP_HEADER_KEY_OS_VERSION];
// Set header field if this is used in a wrapper SDK
if (OneSignalWrapper.sdkType && OneSignalWrapper.sdkVersion) {
NSString *wrapperString = [NSString stringWithFormat:@"onesignal/%@/%@", OneSignalWrapper.sdkType, OneSignalWrapper.sdkVersion];
[request setValue:wrapperString forHTTPHeaderField:HTTP_HEADER_KEY_OS_WRAPPER];
}
[request setHTTPMethod:httpMethodString(self.method)];
switch (self.method) {
case GET:
case DELETE:
[self attachQueryParametersToRequest:request withParameters:self.parameters];
break;
case POST:
case PATCH:
case PUT:
[self attachBodyToRequest:request withParameters:self.parameters];
break;
default:
break;
}
return request;
}
-(BOOL)missingAppId {
if ([self.path containsString:@"apps/"]) {
NSArray *pathComponents = [self.path componentsSeparatedByString:@"/"];
NSUInteger x = [pathComponents indexOfObject:@"apps"] + 1; // Find the index that follows "apps" in the path
return ([pathComponents count] <= x || [[pathComponents objectAtIndex:x] length] == 0 || [[pathComponents objectAtIndex:x] isEqual: @"(null)"]);
}
return (self.parameters[@"app_id"] == nil || [self.parameters[@"app_id"] length] == 0);
}
-(void)attachBodyToRequest:(NSMutableURLRequest *)request withParameters:(NSDictionary *)parameters {
if (!self.parameters)
return;
//to prevent a crash, print error and return before attempting to serialize to JSON data
if (![NSJSONSerialization isValidJSONObject:self.parameters]) {
[OneSignalLog onesignalLog:ONE_S_LL_WARN message:[NSString stringWithFormat:@"OneSignal Attempted to make a request with an invalid JSON body: %@", self.parameters]];
return;
}
NSError *error;
NSData *requestData = [NSJSONSerialization dataWithJSONObject:parameters options:0 error:&error];
NSString *requestString = [[NSString alloc] initWithData:requestData encoding:NSUTF8StringEncoding];
NSRegularExpression *eidRegex = [NSRegularExpression regularExpressionWithPattern:@"(?<=\"external_user_id\":\").*\\/.*?(?=\",|\"\\})" options:0 error:&error];
NSArray *matches = [eidRegex matchesInString:requestString options:0 range:NSMakeRange(0, [requestString length])];
if ([matches count] > 0) {
NSTextCheckingResult *match = matches[0];
NSString *matched = [requestString substringWithRange:[match range]];
NSString *unescapedEID = [matched stringByReplacingOccurrencesOfString:@"\\/" withString:@"/"];
requestString = [requestString stringByReplacingOccurrencesOfString:matched withString:unescapedEID];
}
request.HTTPBody = [requestString dataUsingEncoding:NSUTF8StringEncoding];
}
-(void)attachQueryParametersToRequest:(NSMutableURLRequest *)request withParameters:(NSDictionary *)parameters {
if (!parameters)
return;
NSString *urlString = [request.URL absoluteString];
NSString *queryString = [self queryStringForParameters:parameters];
if (queryString && queryString.length > 0) {
urlString = [urlString stringByAppendingString:@"?"];
urlString = [urlString stringByAppendingString:queryString];
}
request.URL = [NSURL URLWithString:urlString];
}
-(NSString *)queryStringForParameters:(NSDictionary *)parameters {
NSEnumerator *enumerator = [parameters keyEnumerator];
id key;
NSString *result = @"";
while (key = [enumerator nextObject]) {
result = [result stringByAppendingFormat:@"%@=%@&", key, [parameters objectForKey:key]];
}
result = [result substringToIndex:result.length - 1];
return [result stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
}
@end