I need to modify response headers in an NSURLResponse. Is this possible?
-
Are you trying to modify the headers you get from the server?! Do you mean NSURLRequest? – notnoop Jan 19 '10 at 20:09
-
wait... no.. i mean NSURLResponse – Arlen Anderson Jan 19 '10 at 20:26
4 Answers
I was just talking about this with a friend. My suggestion would be to write a subclass of NSURLResponse. Something along these lines:
@interface MyHTTPURLResponse : NSURLResponse { NSDictionary *myDict; }
- (void)setAllHeaderFields:(NSDictionary *)dictionary;
@end
@implementation MyHTTPURLResponse
- (NSDictionary *)allHeaderFields { return myDict ?: [super allHeaderFields]; }
- (void)setAllHeaderFields:(NSDictionary *)dict { if (myDict != dict) { [myDict release]; myDict = [dict retain]; } }
@end
If you're dealing with an object you didn't make, you can try using object_setClass
to swizzle the class out. However I don't know if that will add the necessary instance variable. You could also use objc_setAssociatedObject
and stuff this all in a category instead, if you can support a new enough SDK.

- 4,305
- 22
- 23

- 4,451
- 1
- 26
- 33
You can read them into a NSDictionary using the allHeaderFields
method.
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
NSDictionary *httpResponseHeaderFields = [httpResponse
allHeaderFields];
To be 100% safe you'd want to wrap it with
if ([response respondsToSelector:@selector(allHeaderFields)]) {... }

- 4,549
- 1
- 27
- 38
-
Doesn't that return an NSDictionary instead of an NSMutableDictionary? – Arlen Anderson Jan 19 '10 at 20:15
-
Yeah, that's what is there in the code sample. Here's the class reference http://developer.apple.com/iphone/library/documentation/Cocoa/Reference/Foundation/Classes/NSHTTPURLResponse_Class/Reference/Reference.html#//apple_ref/occ/instm/NSHTTPURLResponse/allHeaderFields – shawnwall Jan 19 '10 at 20:30
-
I don't see how an immutable dictionary will help me modify the keys/values – Arlen Anderson Jan 19 '10 at 20:34
-
Ah... sorry, my mistake - what exactly are you trying to do by modifying the response? You could create a new NSMutableDictionary and use setDictionary to put the values from the original response headers, but I still don't understand the final goal here. – shawnwall Jan 19 '10 at 21:07
-
Use NSMutableDictionary *httpResponseHeaderFields = [[httpResponse allHeaderFields] mutableCopy]; But really we could all help you much more if you would tell us WHY you want to modify fields in a response... are you looking to "fool" some kind of library getting back an NSHTTPURLResponse? – Kendall Helmstetter Gelner Jan 19 '10 at 22:16
I had a similar problem. I wanted to modify the header fileds of http url response. I needed it because wanted to provide cached url response to UIWebView and want to fool the web view that the response is not expired (i.e. I wanted to change "Cache-Control" property of the header but to keep the rest of the headers). My solution was to use NSKeyedArchiver to encode the original http response and to intercept the serialization with delegate. In
-(id) archiver:(NSKeyedArchiver*) archiver willEncodeObject:(id) object
I check if the object is NSDictionary and if so, I returned modified dictionary (i.e with updated "Cache-Control" header). Afterwards I just deserialized the serialized response using NSKeyedUnarchiver. Of course you may hook to the unarchiver and modify the headers in its delegate.
Note that in iOS 5 Apple has added
-(id)initWithURL:(NSURL*) url statusCode:(NSInteger) statusCode HTTPVersion:(NSString*) HTTPVersion headerFields:(NSDictionary*) headerFields
which is not in the documentation (documentation bug), but it is in the public API of NSHTTPURLResponse

- 11
- 1
You can do that, and you'd need NSHTTPURLResponse
not NSURLResponse
, because, in Swift, NSURLResponse
can be used with many protocols rather than just http
, such as ftp
, data:
, or https
. As a result, you can call it to get the meta data info, such as expected content type, mime type and text encoding, while NSHTTURLResponse
is the one responsible of handling HTTP protocol responses. Thus, it is the one to manipulate the headers.
This is a small code that manipulates the header key Server
from the response, and prints the value before and after the change.
let url = "https://www.google.com"
let request = NSMutableURLRequest(URL: NSURL(string: url)!)
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(request, completionHandler: {(data, response, error) in
if let response = response {
let nsHTTPURLResponse = response as! NSHTTPURLResponse
var headers = nsHTTPURLResponse.allHeaderFields
print ("The value of the Server header before is: \(headers["Server"]!)")
headers["Server"] = "whatever goes here"
print ("The value of the Server header after is: \(headers["Server"]!)")
}
})
task.resume()

- 28,059
- 20
- 85
- 118
-
1Your code manipulate a copy of allHeaderFields. It doesn't edit header inside NSHTTPResponse – Huy Le Nov 20 '18 at 23:38