Mutable NSHTTPURLResponse or NSURLResponse

别说谁变了你拦得住时间么 提交于 2019-12-19 09:56:48

问题


I need to modify response headers in an NSURLResponse. Is this possible?


回答1:


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.




回答2:


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)]) {... }



回答3:


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




回答4:


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()


来源:https://stackoverflow.com/questions/2096651/mutable-nshttpurlresponse-or-nsurlresponse

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!