Due to third party API limitations (very strict security), we are required to send a very strict list of headers in our http requests. Due to this we tried implementing our requests in as low a level as possible following the documentation here: https://developer.apple.com/library/ios/documentation/Networking/Conceptual/CFNetwork/CFHTTPTasks/CFHTTPTasks.html
Even though we don't set the User-Agent header it is still present in our requests (besides the Connection header it seems to be the only one we can't remove). Searching around the web lead us to this as well https://opensource.apple.com/source/CFNetwork/CFNetwork-128/Headers/CFHTTPMessage.h Not sure how up to date this is but the comments state that passing null as the value for the CFHTTPMessageSetHeaderFieldValue call should remove the header, but it doesn't...
Is there any way to get rid of the User-Agent header?
Simple snippet of what we have:
#import "GTlRpcHelper.h"
#import "GTlRpcRequest.h"
@implementation GTlRpcHelper
RCT_EXPORT_MODULE()
RCT_EXPORT_METHOD(TlRpcHttpRequest:(NSString *)url method:(NSString *)method data:(NSString *)postData resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject){
CFHTTPMessageRef request = [self buildMessage: url method:method data:postData];
CFHTTPMessageRef response = [self performHTTPRequest: request];
UInt32 statusCode;
statusCode = CFHTTPMessageGetResponseStatusCode(response);
int authCount = 0;
while((statusCode == 401 || statusCode == 407) && authCount < 3) {
request = [self buildMessage: url method:method data:postData];
[self addAuthenticationToRequest:request withResponse:response];
response = [self performHTTPRequest: request];
statusCode = CFHTTPMessageGetResponseStatusCode;
authCount++;
}
NSData *responseBodyData = (__bridge NSData*)CFHTTPMessageCopyBody(response);
NSString *responseBody = [[NSString alloc] initWithData:responseBodyData encoding:NSUTF8StringEncoding];
NSLog(responseBody);
}
-(CFHTTPMessageRef) buildMessage: (NSString *)url method:(NSString *)method data:(NSString *)postData{
CFStringRef reqUrlString = (__bridge CFStringRef)url;
CFURLRef reqUrl = CFURLCreateWithString(kCFAllocatorDefault, reqUrlString, NULL);
CFStringRef requestMethod = (__bridge CFStringRef)method;
CFHTTPMessageRef request = CFHTTPMessageCreateRequest(kCFAllocatorDefault, requestMethod, reqUrl, kCFHTTPVersion1_1);
if([method isEqualToString:@"POST"] || [method isEqualToString:@"PUT"]){
/
CFStringRef bodyString = (__bridge CFStringRef)postData;
CFDataRef bodyData = CFStringCreateExternalRepresentation(kCFAllocatorDefault, bodyString, kCFStringEncodingUTF8, 0);
CFHTTPMessageSetBody(request, bodyData);
CFStringRef headerFieldName = CFSTR("Content-Length");
CFStringRef headerFieldValue = (__bridge CFStringRef)[NSString stringWithFormat:@"%ld", CFDataGetLength(bodyData)];
CFHTTPMessageSetHeaderFieldValue(request, headerFieldName, headerFieldValue);
}
CFHTTPMessageSetHeaderFieldValue(request, CFSTR("Connection"), CFSTR("Keep-Alive"));
CFHTTPMessageSetHeaderFieldValue(request, CFSTR("User-Agent"), NULL);
return request;
}
-(void)addAuthenticationToRequest:(CFHTTPMessageRef)request withResponse:(CFHTTPMessageRef)response
{
CFHTTPAuthenticationRef authentication = CFHTTPAuthenticationCreateFromResponse(NULL, response);
CFStreamError err;
Boolean success = CFHTTPMessageApplyCredentials(request, authentication, CFSTR("username"), CFSTR("password"), &err);
}
-(CFHTTPMessageRef)performHTTPRequest:(CFHTTPMessageRef)request
{
CFReadStreamRef requestStream = CFReadStreamCreateForHTTPRequest(NULL, request);
CFReadStreamOpen(requestStream);
NSMutableData *responseBytes = [NSMutableData data];
CFIndex numBytesRead = 0 ;
do
{
UInt8 buf[1024];
numBytesRead = CFReadStreamRead(requestStream, buf, sizeof(buf));
if(numBytesRead > 0)
[responseBytes appendBytes:buf length:numBytesRead];
} while(numBytesRead > 0);
CFHTTPMessageRef response = (CFHTTPMessageRef)CFReadStreamCopyProperty(requestStream, kCFStreamPropertyHTTPResponseHeader);
CFHTTPMessageSetBody(response, (__bridge CFDataRef)responseBytes);
CFReadStreamClose(requestStream);
CFRelease(requestStream);
return response;
}