Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ios,android): add request duration in fetch response header #3952

Merged
merged 1 commit into from
Jul 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
public class NetworkModule extends HippyNativeModuleBase {

private static final String TAG = "NetworkModule";
private static final String HTTP_RESPONSE_REQUEST_DURATION = "Hippy-Request-Duration";

public NetworkModule(HippyEngineContext context) {
super(context);
Expand Down Expand Up @@ -103,8 +104,9 @@ protected void normalizeRequest(@NonNull HippyMap request,
}

@NonNull
protected JSObject handleFetchResponse(@NonNull ResourceDataHolder dataHolder)
throws IllegalStateException {
protected JSObject handleFetchResponse(@NonNull ResourceDataHolder dataHolder,
double requestDuration)
throws IllegalStateException {
JSObject responseObject = new JSObject();
int statusCode = -1;
String responseMessage = null;
Expand All @@ -129,6 +131,7 @@ protected JSObject handleFetchResponse(@NonNull ResourceDataHolder dataHolder)
if (responseMessage == null) {
responseMessage = (dataHolder.errorMessage == null) ? "" : dataHolder.errorMessage;
}
headerObject.set(HTTP_RESPONSE_REQUEST_DURATION, Double.toString(requestDuration));
responseObject.set(HTTP_RESPONSE_STATUS_CODE, statusCode);
responseObject.set("statusLine", responseMessage);
responseObject.set("respHeaders", headerObject);
Expand All @@ -145,10 +148,12 @@ protected JSObject handleFetchResponse(@NonNull ResourceDataHolder dataHolder)
return responseObject;
}

protected void handleFetchResult(@NonNull ResourceDataHolder dataHolder, final Promise promise) {
protected void handleFetchResult(@NonNull ResourceDataHolder dataHolder,
double requestDuration,
final Promise promise) {
try {
if (dataHolder.resultCode == ResourceDataHolder.RESOURCE_LOAD_SUCCESS_CODE) {
JSObject responseObject = handleFetchResponse(dataHolder);
JSObject responseObject = handleFetchResponse(dataHolder, requestDuration);
promise.resolve(responseObject);
} else {
String errorMessage =
Expand Down Expand Up @@ -177,19 +182,25 @@ public void fetch(final HippyMap request, final Promise promise) {
promise.reject("Get url parameter failed!");
return;
}

// Record request start time
final long startTime = System.nanoTime();

vfsManager.fetchResourceAsync(uri, requestHeaders, requestParams,
new FetchResourceCallback() {
@Override
public void onFetchCompleted(@NonNull ResourceDataHolder dataHolder) {
handleFetchResult(dataHolder, promise);
dataHolder.recycle();
}
new FetchResourceCallback() {
@Override
public void onFetchCompleted(@NonNull ResourceDataHolder dataHolder) {
// Time taken for the request, in milliseconds
double requestDuration = (System.nanoTime() - startTime) / 1_000_000.0;
handleFetchResult(dataHolder, requestDuration, promise);
dataHolder.recycle();
}

@Override
public void onFetchProgress(long total, long loaded) {
// Nothing need to do here.
}
});
@Override
public void onFetchProgress(long total, long loaded) {
// Nothing need to do here.
}
});
}

@HippyMethod(name = "getCookie")
Expand Down
2 changes: 1 addition & 1 deletion framework/ios/module/network/HippyNetWork.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@
*/

#import <Foundation/Foundation.h>

#import "HippyBridgeModule.h"

/// Hippy Network module
@interface HippyNetWork : NSObject <HippyBridgeModule, NSURLSessionDataDelegate>

@end
90 changes: 68 additions & 22 deletions framework/ios/module/network/HippyNetWork.mm
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,31 @@
* limitations under the License.
*/

#import <WebKit/WKHTTPCookieStore.h>
#import <WebKit/WKWebsiteDataStore.h>

#import "HippyNetWork.h"
#import <WebKit/WebKit.h>
#import <QuartzCore/QuartzCore.h>
#import "HippyBridge+VFSLoader.h"
#import "HippyDefines.h"
#import "HippyNetWork.h"
#import "HippyAssert.h"
#import "HippyUtils.h"


// Request parameter of fetch API
static NSString *const kHippyNetworkRequestParaURL = @"url";
static NSString *const kHippyNetworkRequestParaMethod = @"method";
static NSString *const kHippyNetworkRequestParaHeaders = @"headers";
static NSString *const kHippyNetworkRequestParaBody = @"body";

// Response parameter of fetch API
static NSString *const kHippyNetworkResponseStatusCode = @"statusCode";
static NSString *const kHippyNetworkResponseStatusLine = @"statusLine";
static NSString *const kHippyNetworkResponseHeaders = @"respHeaders";
static NSString *const kHippyNetworkResponseBody = @"respBody";

// Duration parameter in resp.header of fetch API
static NSString *const kHippyNetworkRequestDuration = @"Hippy-Request-Duration";


static NSStringEncoding GetStringEncodingFromURLResponse(NSURLResponse *response) {
NSString *textEncoding = [response textEncodingName];
if (!textEncoding) {
Expand All @@ -45,35 +61,51 @@ @implementation HippyNetWork

HIPPY_EXPORT_MODULE(network)

HIPPY_EXPORT_METHOD(fetch:(NSDictionary *)params resolver:(__unused HippyPromiseResolveBlock)resolve rejecter:(__unused HippyPromiseRejectBlock)reject) {
HIPPY_EXPORT_METHOD(fetch:(NSDictionary *)params
resolver:(HippyPromiseResolveBlock)resolve
rejecter:(HippyPromiseRejectBlock)reject) {
if (!resolve) {
return;
}
NSString *method = params[@"method"];
NSString *url = params[@"url"];
NSDictionary *header = params[@"headers"];
NSString *body = params[@"body"];

HippyAssertParam(url);
HippyAssertParam(method);

NSString *url = params[kHippyNetworkRequestParaURL];
NSString *method = params[kHippyNetworkRequestParaMethod];
NSDictionary *header = params[kHippyNetworkRequestParaHeaders];
NSString *body = params[kHippyNetworkRequestParaBody];

if (!url) {
HippyAssertParam(url);
if (reject) {
reject(@"invalid_params", @"URL is missing", nil);
}
return;
}

NSMutableDictionary *vfsParams = [NSMutableDictionary new];
[header enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, __unused BOOL *stop) {
[header enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL *stop) {
NSString *value = nil;
if ([obj isKindOfClass: [NSArray class]]) {
if ([obj isKindOfClass:[NSArray class]]) {
value = [[(NSArray *)obj valueForKey:@"description"] componentsJoinedByString:@","];
} else if ([obj isKindOfClass: [NSString class]]) {
} else if ([obj isKindOfClass:[NSString class]]) {
value = obj;
}

[vfsParams setValue: value forKey: key];
if (value) {
[vfsParams setValue:value forKey:key];
}
}];

NSData *data = nil;
if (body) {
data = [body dataUsingEncoding:NSUTF8StringEncoding];
}

// Record request start time
CFTimeInterval startTime = CACurrentMediaTime();

// Send Request
[self.bridge loadContentsAsynchronouslyFromUrl:url
method:method?:@"Get"
method:method ?: @"GET"
params:vfsParams
body:data
queue:nil
Expand All @@ -83,19 +115,33 @@ @implementation HippyNetWork
NSStringEncoding encoding = GetStringEncodingFromURLResponse(response);
NSString *dataStr = [[NSString alloc] initWithData:data encoding:encoding];
NSUInteger statusCode = 0;
NSDictionary *headers = nil;
NSMutableDictionary *headers = [NSMutableDictionary dictionary];

if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
NSHTTPURLResponse *httpRes = (NSHTTPURLResponse *)response;
statusCode = [httpRes statusCode];
headers = [httpRes allHeaderFields];
[headers addEntriesFromDictionary:[httpRes allHeaderFields]];
}
NSDictionary *result =
@{ @"statusCode": @(statusCode), @"statusLine": @"", @"respHeaders": headers ?: @ {}, @"respBody": dataStr ?: @"" };

// Get request duration,in ms.
// and add to resp headers.
CFTimeInterval requestDuration = (CACurrentMediaTime() - startTime) * 1000;
[headers addEntriesFromDictionary:@{ kHippyNetworkRequestDuration : @(requestDuration).stringValue }];

NSDictionary *result = @{
kHippyNetworkResponseStatusCode : @(statusCode),
kHippyNetworkResponseStatusLine : @"",
kHippyNetworkResponseHeaders : headers ?: @{},
kHippyNetworkResponseBody : dataStr ?: @""
};

resolve(result);
}];
}

HIPPY_EXPORT_METHOD(getCookie:(NSString *)urlString resolver:(HippyPromiseResolveBlock)resolve rejecter:(__unused HippyPromiseRejectBlock)reject) {
HIPPY_EXPORT_METHOD(getCookie:(NSString *)urlString
resolver:(HippyPromiseResolveBlock)resolve
rejecter:(__unused HippyPromiseRejectBlock)reject) {
NSData *uriData = [urlString dataUsingEncoding:NSUTF8StringEncoding];
if (nil == uriData) {
resolve(@"");
Expand Down
Loading