Mutable NSHTTPURLResponse or NSURLResponse

后端 未结 4 1674
一生所求
一生所求 2021-01-14 09:44

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

相关标签:
4条回答
  • 2021-01-14 09:57

    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.

    0 讨论(0)
  • 2021-01-14 10:02

    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

    0 讨论(0)
  • 2021-01-14 10:20

    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()
    
    0 讨论(0)
  • 2021-01-14 10:22

    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)]) {... }
    
    0 讨论(0)
提交回复
热议问题