How to remove the User-Agent header?

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;
  }

>Not sure how up to date this is


It pre-dates iOS and mobile browsers, so...


user-agent is included for a reason....what is your reason for not wanting servers to have that information?

There’s no way to remove the

User-Agent
header. Internally the code looks like this:
get the user agent header from the message
if that’s nil then
    use the default
end if

If you can’t fix the server then your only option would be to write or acquire some other HTTP library.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"
How to remove the User-Agent header?
 
 
Q