iOS HttpUrlResponse Header Field Case Sensitivity

1k views Asked by At

When attempting to get the headers from an HttpUrlResponse, I am finding the iOS simulator is case-insensitive and a real device is case-sensitive.

The web service returns an HTTP header "Grandmas-Cookies: XXXX"

When the header key has uppercase letters: urlResponse.response.allHeaderFields["Grandmas-Cookies"] as? String

  • The simulator does NOT find the key.
  • A real device sees the key.

When the header key has all lowercase letters: urlResponse.response.allHeaderFields["grandmas-cookies"] as? String

  • The simulator does find the key.
  • A real device does NOT see the key.

Is there a setting I can make to the simulator to behave similarly to the real device? Changing the HTTP headers in the web service to lowercase is not desirable at this point but it is strange this started occurring only recently (yeah it's one of those fun times).

1

There are 1 answers

1
Michael Eakins On

Edit:

@Adam I found a better way to ensure that this isn't an issue.

I created this function that makes the check case insensitive.

func find(header: String) -> String? {
        let keyValues = allHeaderFields.map { (String(describing: $0.key).lowercased(), String(describing: $0.value)) }

        if let headerValue = keyValues.filter({ $0.0 == header.lowercased() }).first {
            return headerValue.1
        }
        return nil
    }

The below may still be useful for some people.

To solve this issue I created a struct. Inside the struct I created a static variable grandmasCookies that can now be referenced from anywhere within your app. This returns the upper case

Grandmas-Cookies

when you are running on a phone device.

This returns lowercase

grandmas-cookies

when you are running in a simulator on a device such as a MacBook Pro.

struct Platform {

    static let grandmasCookies: String = {
        var xtoken = "Grandmas-Cookies"
        #if arch(i386) || arch(x86_64)
            xtoken = "grandmas-cookies"
        #endif
        return xtoken
    }()

    static let isSimulator: Bool = {
        var isSim = false
        #if arch(i386) || arch(x86_64)
            isSim = true
        #endif
        return isSim
    }()
}

I created a second convenience variable isSimulator which returns true when running from a simulator and false when running on a phone device.

I adapted code from this StackOverflow post to make a solution that works for your scenario and one that I faced as well.