Skip to content

Commit c5a676c

Browse files
committed
feat(ios,android): add request duration in fetch response header
1 parent 1d9ed5a commit c5a676c

File tree

3 files changed

+95
-38
lines changed

3 files changed

+95
-38
lines changed

framework/android/src/main/java/com/tencent/mtt/hippy/modules/nativemodules/network/NetworkModule.java

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
public class NetworkModule extends HippyNativeModuleBase {
4848

4949
private static final String TAG = "NetworkModule";
50+
private static final String HTTP_RESPONSE_REQUEST_DURATION = "Hippy-Request-Duration";
5051

5152
public NetworkModule(HippyEngineContext context) {
5253
super(context);
@@ -103,8 +104,9 @@ protected void normalizeRequest(@NonNull HippyMap request,
103104
}
104105

105106
@NonNull
106-
protected JSObject handleFetchResponse(@NonNull ResourceDataHolder dataHolder)
107-
throws IllegalStateException {
107+
protected JSObject handleFetchResponse(@NonNull ResourceDataHolder dataHolder,
108+
double requestDuration)
109+
throws IllegalStateException {
108110
JSObject responseObject = new JSObject();
109111
int statusCode = -1;
110112
String responseMessage = null;
@@ -129,6 +131,7 @@ protected JSObject handleFetchResponse(@NonNull ResourceDataHolder dataHolder)
129131
if (responseMessage == null) {
130132
responseMessage = (dataHolder.errorMessage == null) ? "" : dataHolder.errorMessage;
131133
}
134+
headerObject.set(HTTP_RESPONSE_REQUEST_DURATION, Double.toString(requestDuration));
132135
responseObject.set(HTTP_RESPONSE_STATUS_CODE, statusCode);
133136
responseObject.set("statusLine", responseMessage);
134137
responseObject.set("respHeaders", headerObject);
@@ -145,10 +148,12 @@ protected JSObject handleFetchResponse(@NonNull ResourceDataHolder dataHolder)
145148
return responseObject;
146149
}
147150

148-
protected void handleFetchResult(@NonNull ResourceDataHolder dataHolder, final Promise promise) {
151+
protected void handleFetchResult(@NonNull ResourceDataHolder dataHolder,
152+
double requestDuration,
153+
final Promise promise) {
149154
try {
150155
if (dataHolder.resultCode == ResourceDataHolder.RESOURCE_LOAD_SUCCESS_CODE) {
151-
JSObject responseObject = handleFetchResponse(dataHolder);
156+
JSObject responseObject = handleFetchResponse(dataHolder, requestDuration);
152157
promise.resolve(responseObject);
153158
} else {
154159
String errorMessage =
@@ -177,19 +182,25 @@ public void fetch(final HippyMap request, final Promise promise) {
177182
promise.reject("Get url parameter failed!");
178183
return;
179184
}
185+
186+
// Record request start time
187+
final long startTime = System.nanoTime();
188+
180189
vfsManager.fetchResourceAsync(uri, requestHeaders, requestParams,
181-
new FetchResourceCallback() {
182-
@Override
183-
public void onFetchCompleted(@NonNull ResourceDataHolder dataHolder) {
184-
handleFetchResult(dataHolder, promise);
185-
dataHolder.recycle();
186-
}
190+
new FetchResourceCallback() {
191+
@Override
192+
public void onFetchCompleted(@NonNull ResourceDataHolder dataHolder) {
193+
// Time taken for the request, in milliseconds
194+
double requestDuration = (System.nanoTime() - startTime) / 1_000_000.0;
195+
handleFetchResult(dataHolder, requestDuration, promise);
196+
dataHolder.recycle();
197+
}
187198

188-
@Override
189-
public void onFetchProgress(long total, long loaded) {
190-
// Nothing need to do here.
191-
}
192-
});
199+
@Override
200+
public void onFetchProgress(long total, long loaded) {
201+
// Nothing need to do here.
202+
}
203+
});
193204
}
194205

195206
@HippyMethod(name = "getCookie")

framework/ios/module/network/HippyNetWork.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@
2121
*/
2222

2323
#import <Foundation/Foundation.h>
24-
2524
#import "HippyBridgeModule.h"
2625

26+
/// Hippy Network module
2727
@interface HippyNetWork : NSObject <HippyBridgeModule, NSURLSessionDataDelegate>
2828

2929
@end

framework/ios/module/network/HippyNetWork.mm

Lines changed: 68 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,31 @@
2020
* limitations under the License.
2121
*/
2222

23-
#import <WebKit/WKHTTPCookieStore.h>
24-
#import <WebKit/WKWebsiteDataStore.h>
25-
23+
#import "HippyNetWork.h"
24+
#import <WebKit/WebKit.h>
25+
#import <QuartzCore/QuartzCore.h>
2626
#import "HippyBridge+VFSLoader.h"
2727
#import "HippyDefines.h"
28-
#import "HippyNetWork.h"
2928
#import "HippyAssert.h"
3029
#import "HippyUtils.h"
3130

31+
32+
// Request parameter of fetch API
33+
static NSString *const kHippyNetworkRequestParaURL = @"url";
34+
static NSString *const kHippyNetworkRequestParaMethod = @"method";
35+
static NSString *const kHippyNetworkRequestParaHeaders = @"headers";
36+
static NSString *const kHippyNetworkRequestParaBody = @"body";
37+
38+
// Response parameter of fetch API
39+
static NSString *const kHippyNetworkResponseStatusCode = @"statusCode";
40+
static NSString *const kHippyNetworkResponseStatusLine = @"statusLine";
41+
static NSString *const kHippyNetworkResponseHeaders = @"respHeaders";
42+
static NSString *const kHippyNetworkResponseBody = @"respBody";
43+
44+
// Duration parameter in resp.header of fetch API
45+
static NSString *const kHippyNetworkRequestDuration = @"Hippy-Request-Duration";
46+
47+
3248
static NSStringEncoding GetStringEncodingFromURLResponse(NSURLResponse *response) {
3349
NSString *textEncoding = [response textEncodingName];
3450
if (!textEncoding) {
@@ -45,35 +61,51 @@ @implementation HippyNetWork
4561

4662
HIPPY_EXPORT_MODULE(network)
4763

48-
HIPPY_EXPORT_METHOD(fetch:(NSDictionary *)params resolver:(__unused HippyPromiseResolveBlock)resolve rejecter:(__unused HippyPromiseRejectBlock)reject) {
64+
HIPPY_EXPORT_METHOD(fetch:(NSDictionary *)params
65+
resolver:(HippyPromiseResolveBlock)resolve
66+
rejecter:(HippyPromiseRejectBlock)reject) {
4967
if (!resolve) {
5068
return;
5169
}
52-
NSString *method = params[@"method"];
53-
NSString *url = params[@"url"];
54-
NSDictionary *header = params[@"headers"];
55-
NSString *body = params[@"body"];
56-
57-
HippyAssertParam(url);
58-
HippyAssertParam(method);
70+
71+
NSString *url = params[kHippyNetworkRequestParaURL];
72+
NSString *method = params[kHippyNetworkRequestParaMethod];
73+
NSDictionary *header = params[kHippyNetworkRequestParaHeaders];
74+
NSString *body = params[kHippyNetworkRequestParaBody];
75+
76+
if (!url) {
77+
HippyAssertParam(url);
78+
if (reject) {
79+
reject(@"invalid_params", @"URL is missing", nil);
80+
}
81+
return;
82+
}
5983

6084
NSMutableDictionary *vfsParams = [NSMutableDictionary new];
61-
[header enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, __unused BOOL *stop) {
85+
[header enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL *stop) {
6286
NSString *value = nil;
63-
if ([obj isKindOfClass: [NSArray class]]) {
87+
if ([obj isKindOfClass:[NSArray class]]) {
6488
value = [[(NSArray *)obj valueForKey:@"description"] componentsJoinedByString:@","];
65-
} else if ([obj isKindOfClass: [NSString class]]) {
89+
} else if ([obj isKindOfClass:[NSString class]]) {
6690
value = obj;
6791
}
6892

69-
[vfsParams setValue: value forKey: key];
93+
if (value) {
94+
[vfsParams setValue:value forKey:key];
95+
}
7096
}];
97+
7198
NSData *data = nil;
7299
if (body) {
73100
data = [body dataUsingEncoding:NSUTF8StringEncoding];
74101
}
102+
103+
// Record request start time
104+
CFTimeInterval startTime = CACurrentMediaTime();
105+
106+
// Send Request
75107
[self.bridge loadContentsAsynchronouslyFromUrl:url
76-
method:method?:@"Get"
108+
method:method ?: @"GET"
77109
params:vfsParams
78110
body:data
79111
queue:nil
@@ -83,19 +115,33 @@ @implementation HippyNetWork
83115
NSStringEncoding encoding = GetStringEncodingFromURLResponse(response);
84116
NSString *dataStr = [[NSString alloc] initWithData:data encoding:encoding];
85117
NSUInteger statusCode = 0;
86-
NSDictionary *headers = nil;
118+
NSMutableDictionary *headers = [NSMutableDictionary dictionary];
119+
87120
if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
88121
NSHTTPURLResponse *httpRes = (NSHTTPURLResponse *)response;
89122
statusCode = [httpRes statusCode];
90-
headers = [httpRes allHeaderFields];
123+
[headers addEntriesFromDictionary:[httpRes allHeaderFields]];
91124
}
92-
NSDictionary *result =
93-
@{ @"statusCode": @(statusCode), @"statusLine": @"", @"respHeaders": headers ?: @ {}, @"respBody": dataStr ?: @"" };
125+
126+
// Get request duration,in ms.
127+
// and add to resp headers.
128+
CFTimeInterval requestDuration = (CACurrentMediaTime() - startTime) * 1000;
129+
[headers addEntriesFromDictionary:@{ kHippyNetworkRequestDuration : @(requestDuration).stringValue }];
130+
131+
NSDictionary *result = @{
132+
kHippyNetworkResponseStatusCode : @(statusCode),
133+
kHippyNetworkResponseStatusLine : @"",
134+
kHippyNetworkResponseHeaders : headers ?: @{},
135+
kHippyNetworkResponseBody : dataStr ?: @""
136+
};
137+
94138
resolve(result);
95139
}];
96140
}
97141

98-
HIPPY_EXPORT_METHOD(getCookie:(NSString *)urlString resolver:(HippyPromiseResolveBlock)resolve rejecter:(__unused HippyPromiseRejectBlock)reject) {
142+
HIPPY_EXPORT_METHOD(getCookie:(NSString *)urlString
143+
resolver:(HippyPromiseResolveBlock)resolve
144+
rejecter:(__unused HippyPromiseRejectBlock)reject) {
99145
NSData *uriData = [urlString dataUsingEncoding:NSUTF8StringEncoding];
100146
if (nil == uriData) {
101147
resolve(@"");

0 commit comments

Comments
 (0)