AliSoftware / OHHTTPStubs

Stub your network requests easily! Test your apps with fake network data and custom response time, response code and headers!
MIT License
5.03k stars 601 forks source link

Can't get HTTP headers from stubbed request #274

Open Denages opened 6 years ago

Denages commented 6 years ago

New Issue Checklist

Environment

Issue Description

I always get request.allHTTPHeaderFields == nil. At least there should be an auto-generated user-agent header.

Here is my stub code with redirection to the same url with substituted headers to set my custom cookie. request.allHTTPHeaderFields == nil in both cases: before and after redirection.

[OHHTTPStubs stubRequestsPassingTest:^BOOL(NSURLRequest * _Nonnull request) {
    return YES;
} withStubResponse:^OHHTTPStubsResponse * _Nonnull(NSURLRequest * _Nonnull request) {
    //allHTTPHeaderFields is always nil
    NSDictionary<NSString *,NSString *> *allHTTPHeaderFields = request.allHTTPHeaderFields;    
    return [OHHTTPStubsResponse responseWithData:[NSData data]
                                  statusCode:302
                                     headers:@{@"Location"   : downloadURL,
                                               @"Set-Cookie" : @"cookie_name=value"
                                               }];
}];

Network request code:

AFHTTPSessionManager *sessionManager = [AFHTTPSessionManager manager];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
//.....
NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request progress:nil destination:nil
  completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) {
    //....
}];
[downloadTask resume];
janckoch commented 6 years ago

Same for the HTTPBody...

AliSoftware commented 6 years ago

Hi

You've checked the "have read the OHHTTPStubs wiki to see if there wasn't a detailed page talking about my issue" checkbox in your issue description, does that mean that the wiki page that exists there for this exact problem already didn't solve your issue either?

markalbert commented 5 years ago

Hi, It sounds like I am having the same / similar issue as the OP is having, but I wanted to clarify that it is.

I have read the issue in the OHHTTPStubs wiki, but it's in reference to the httpBody. I just wanted some clarity that it is the same thing which is happening with request headers?


Test Steps

  1. Login request is made to get an authentication cookie from the server
  2. Cookie is automatically stored in the shared cookie store
  3. Successful logout test (session delete) is then ran

Expected result:

Cookie is automatically added to the headers, and matcher hasHeaderNamed("Cookie") is successful

Actual result:

Cookie is not automatically added to the headers, is not present on the request and the matcher hasHeaderNamed("Cookie") fails and my stub is not used.


I was confused as to why it wasn't working, but wanted to make sure it wasn't Alamofire, or something I had done incorrectly, so I created my own node.js server to fire my log in and logout requests into and pointed the "successful logout" test to my node server and ran it again - the test passed and sure enough my server logs showed that the cookie was included with the request, so it wasn't something I was doing wrong with the actual request.

See here my stub for the "successful logout" test:

func stubApiToRespond() {        
        stub(condition: isAbsoluteURLString(AuthenticationWebApiDeleteSessionTests.sessionsUrl.absoluteString) &&
            isMethodDELETE() && hasHeaderNamed("Cookie"), response: { (request) -> OHHTTPStubsResponse in
                var response: OHHTTPStubsResponse? = nil
                do {
                    let json = try JSONSerialization.data(withJSONObject: [:], options: .prettyPrinted)
                    response = OHHTTPStubsResponse(data: json, statusCode: 204, headers: nil)
                } catch {
                    XCTFail("Error converting credentials to JSON \(error)")
                }
                return response!
        })
    }

Initialiser:

let configuration = URLSessionConfiguration.default
afManager = Alamofire.SessionManager(configuration: configuration)

Code for logout (delete session):

public func deleteSession(withSuccessHandler aSuccess: @escaping DeleteSessionSuccessHandler,
                              andErrorHandler aError: @escaping DeleteSessionErrorHandler) throws {

        afManager.request(self.sessionsUrl, method: .delete, parameters: nil, encoding: JSONEncoding.default)
            .responseJSON { (response: DataResponse<Any>) in
                if (response.response === nil) {
                    aError(DeleteSessionApiError.Network)
                } else if response.response?.statusCode == 204 {
                    aSuccess(response.result.value as? JSONObject ?? [:])
                } else if response.response?.statusCode == 401 {
                    aError(DeleteSessionApiError.Unauthorized)
                } else {
                    aError(DeleteSessionApiError.HTTP(statusCode: response.response!.statusCode))
                }
        }
    }

Again, I have read the issue in the OHHTTPStubs wiki, but it's in reference to the httpBody. I just wanted some clarity that it is the same thing which is happening with request headers, and that I'm not going mad?

maciejtreder commented 4 years ago

@markalbert I am running into exactly same issue. Did you figure out how to retrieve cookies from the request, within the stub?

zachwaugh commented 3 years ago

I'm hitting this issue as well and curious if anyone has found a workaround? It seems that when URLSession sets the Cookie header automatically from the cookie storage, it does not appear in the request.allHTTPHeaderFields dictionary. If I set the Cookie header manually, it does come through correctly in the stub. I'm guessing that the Cookie header gets applied at a lower-level than OHHTTPStubs can intercept?