From 2b4e15f3672bd32b7f2456e4fc08a3997a75a9c3 Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Wed, 18 Feb 2026 05:33:04 -0800 Subject: [PATCH 1/3] Add RCTDevSupportHttpHeaders singleton (#55586) Summary: Add a thread-safe singleton that holds custom HTTP headers to be applied to all iOS devsupport network requests. This mirrors the Android `DevSupportHttpClient` from D93481539. Uses a GCD concurrent queue with barrier writes for reader-writer synchronization. Reviewed By: cipolleschi Differential Revision: D93490954 --- .../React/Base/RCTDevSupportHttpHeaders.h | 24 +++++++ .../React/Base/RCTDevSupportHttpHeaders.m | 65 +++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 packages/react-native/React/Base/RCTDevSupportHttpHeaders.h create mode 100644 packages/react-native/React/Base/RCTDevSupportHttpHeaders.m diff --git a/packages/react-native/React/Base/RCTDevSupportHttpHeaders.h b/packages/react-native/React/Base/RCTDevSupportHttpHeaders.h new file mode 100644 index 000000000000..e73cdd3c4b88 --- /dev/null +++ b/packages/react-native/React/Base/RCTDevSupportHttpHeaders.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +/** + * Thread-safe singleton that holds custom HTTP headers to be applied + * to all devsupport network requests (bundle fetches, packager status + * checks, inspector and HMR WebSocket connections). + */ +@interface RCTDevSupportHttpHeaders : NSObject + ++ (instancetype)sharedInstance; + +- (void)addRequestHeader:(NSString *)name value:(NSString *)value; +- (void)removeRequestHeader:(NSString *)name; +- (NSDictionary *)allHeaders; +- (void)applyHeadersToRequest:(NSMutableURLRequest *)request; + +@end diff --git a/packages/react-native/React/Base/RCTDevSupportHttpHeaders.m b/packages/react-native/React/Base/RCTDevSupportHttpHeaders.m new file mode 100644 index 000000000000..0717537f8424 --- /dev/null +++ b/packages/react-native/React/Base/RCTDevSupportHttpHeaders.m @@ -0,0 +1,65 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "RCTDevSupportHttpHeaders.h" + +@implementation RCTDevSupportHttpHeaders { + NSMutableDictionary *_headers; + dispatch_queue_t _queue; +} + ++ (instancetype)sharedInstance +{ + static RCTDevSupportHttpHeaders *sharedInstance; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[RCTDevSupportHttpHeaders alloc] init]; + }); + return sharedInstance; +} + +- (instancetype)init +{ + if (self = [super init]) { + _headers = [NSMutableDictionary new]; + _queue = dispatch_queue_create("com.facebook.react.RCTDevSupportHttpHeaders", DISPATCH_QUEUE_SERIAL); + } + return self; +} + +- (void)addRequestHeader:(NSString *)name value:(NSString *)value +{ + dispatch_sync(_queue, ^{ + self->_headers[name] = value; + }); +} + +- (void)removeRequestHeader:(NSString *)name +{ + dispatch_sync(_queue, ^{ + [self->_headers removeObjectForKey:name]; + }); +} + +- (NSDictionary *)allHeaders +{ + __block NSDictionary *snapshot; + dispatch_sync(_queue, ^{ + snapshot = [self->_headers copy]; + }); + return snapshot; +} + +- (void)applyHeadersToRequest:(NSMutableURLRequest *)request +{ + NSDictionary *headers = [self allHeaders]; + [headers enumerateKeysAndObjectsUsingBlock:^(NSString *headerName, NSString *headerValue, BOOL *stop) { + [request setValue:headerValue forHTTPHeaderField:headerName]; + }]; +} + +@end From 36b6e8b7261277963628683ee2a17e4fde7de4ae Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Wed, 18 Feb 2026 05:33:04 -0800 Subject: [PATCH 2/3] Apply custom headers in RCTMultipartDataTask (#55607) Summary: Inject custom devsupport headers into bundle download requests. This ensures that multipart bundle fetches include any headers registered via `RCTDevSupportHttpHeaders`. Reviewed By: cipolleschi Differential Revision: D93596721 --- packages/react-native/React/Base/RCTMultipartDataTask.m | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/react-native/React/Base/RCTMultipartDataTask.m b/packages/react-native/React/Base/RCTMultipartDataTask.m index 3ac07683eb93..9f5ff5995535 100644 --- a/packages/react-native/React/Base/RCTMultipartDataTask.m +++ b/packages/react-native/React/Base/RCTMultipartDataTask.m @@ -7,6 +7,8 @@ #import "RCTMultipartDataTask.h" +#import "RCTDevSupportHttpHeaders.h" + @interface RCTMultipartDataTask () @end @@ -40,6 +42,7 @@ - (void)startTask delegateQueue:nil]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:_url]; [request addValue:@"multipart/mixed" forHTTPHeaderField:@"Accept"]; + [[RCTDevSupportHttpHeaders sharedInstance] applyHeadersToRequest:request]; NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request]; [dataTask resume]; [session finishTasksAndInvalidate]; From 8fca2baa7f27caacf65cce66948cd0fa5e5431f0 Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Wed, 18 Feb 2026 05:33:04 -0800 Subject: [PATCH 3/3] Apply custom headers in RCTBundleURLProvider (#55608) Summary: Inject custom devsupport headers into the packager status check request. Changes NSURLRequest to NSMutableURLRequest to allow header mutation before the request is sent. Reviewed By: cipolleschi Differential Revision: D93596717 --- packages/react-native/React/Base/RCTBundleURLProvider.mm | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/react-native/React/Base/RCTBundleURLProvider.mm b/packages/react-native/React/Base/RCTBundleURLProvider.mm index e99b2dcc1515..b599cb95eca7 100644 --- a/packages/react-native/React/Base/RCTBundleURLProvider.mm +++ b/packages/react-native/React/Base/RCTBundleURLProvider.mm @@ -10,6 +10,7 @@ #import "RCTConstants.h" #import "RCTConvert.h" #import "RCTDefines.h" +#import "RCTDevSupportHttpHeaders.h" #import "RCTLog.h" #import @@ -93,9 +94,10 @@ + (BOOL)isPackagerRunning:(NSString *)hostPort scheme:(NSString *)scheme NSURL *url = [serverRootWithHostPort(hostPort, scheme) URLByAppendingPathComponent:@"status"]; NSURLSession *session = [NSURLSession sharedSession]; - NSURLRequest *request = [NSURLRequest requestWithURL:url - cachePolicy:NSURLRequestUseProtocolCachePolicy - timeoutInterval:10]; + NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url + cachePolicy:NSURLRequestUseProtocolCachePolicy + timeoutInterval:10]; + [[RCTDevSupportHttpHeaders sharedInstance] applyHeadersToRequest:request]; __block NSURLResponse *response; __block NSData *data;