endpoints icon indicating copy to clipboard operation
endpoints copied to clipboard

Request parse user agent

Open Jaymon opened this issue 3 years ago • 0 comments

Found this in some old application code, could probably be moved into Request core:

    def parse_user_agent(self, user_agent):
        """parses any user agent string to the best of its ability and tries not
        to error out"""
        d = {}

        regex = "^([^/]+)" # 1 - get everything to first slash
        regex += "\/" # ignore the slash
        regex += "(\d[\d.]*)" # 2 - capture the numeric version or build
        regex += "\s+\(" # ignore whitespace before parens group
        regex += "([^\)]+)" # 3 - capture the full paren body
        regex += "\)\s*" # ignore the paren and any space if it is there
        regex += "(.*)$" # 4 - everything else (most common in browsers)
        m = re.match(regex, user_agent)
        if m:
            application = m.group(1)
            version = m.group(2)
            system = m.group(3)
            system_bits = re.split("\s*;\s*", system)
            tail = m.group(4)

            # common
            d['client_application'] = application
            d['client_version'] = version
            d['client_device'] = system_bits[0]

            if application.startswith("Mozilla"):
                for browser in ["Chrome", "Safari", "Firefox"]:
                    browser_m = re.search("{}\/(\d[\d.]*)".format(browser), tail)
                    if browser_m:
                        d['client_application'] = browser
                        d['client_version'] = browser_m.group(1)
                        break

        return d

and the test:

    def test_user_agent(self):
        user_agents = [
            (
                "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36",
                {
                    'client_application': "Chrome",
                    'client_version': "44.0.2403.157",
                    'client_device': "Windows NT 6.3"
                }
            ),
            (
                "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36",
                {
                    'client_application': "Chrome",
                    'client_version': "44.0.2403.157",
                    'client_device': "Macintosh"
                }
            ),
            (
                "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:40.0) Gecko/20100101 Firefox/40.0",
                {
                    'client_application': "Firefox",
                    'client_version': "40.0",
                    'client_device': "Macintosh"
                }
            ),
            (
                "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/600.7.12 (KHTML, like Gecko) Version/8.0.7 Safari/600.7.12", # Safari
                {
                    'client_application': "Safari",
                    'client_version': "600.7.12",
                    'client_device': "Macintosh"
                }
            ),
            (
                "curl/7.24.0 (x86_64-apple-darwin12.0) libcurl/7.24.0 OpenSSL/0.9.8x zlib/1.2.5",
                {
                    'client_application': "curl",
                    'client_version': "7.24.0",
                    'client_device': "x86_64-apple-darwin12.0"
                }
            )
        ]

        for user_agent in user_agents:
            d = self.user_agent(user_agent[0])
            self.assertDictContainsSubset(user_agent[1], d)

Jaymon avatar Mar 03 '21 20:03 Jaymon