\r\n

51Degrees Device Detection Python  4.3Newer Version 4.4

Device Detection services for 51Degrees Pipeline

onpremise/useragentclienthints-web.py

This example demonstrates device detection using user-agent client hints in a real-world scenario. When a clint-hints-enabled user first visits a website, the server will recieve the sec-ch-ua and sec-ch-ua-mobile headers. Along with the user-agent. This information is then used to determine if the client supports user-agent client hints and request them if needed by setting the Accept-CH header in the response. Clicking the button below will cause a new request to be sent to the server, along with any additional headers that have been requested.

This example requires a local data file. The free 'Lite' data file can be acquired by pulling the git submodules under this repository (run `git submodule update --recursive`) or from the device-detection-data GitHub repository.

The Lite data file is only used for illustration, and has limited accuracy and capabilities. Find out about the more capable data files that are available on our pricing page

Expected output:

1 User Agent Client Hints Example
2 
3 Hardware Vendor: Unknown
4 Hardware Name: Array
5 Device Type: Desktop
1 # *********************************************************************
2 # This Original Work is copyright of 51 Degrees Mobile Experts Limited.
3 # Copyright 2019 51 Degrees Mobile Experts Limited, 5 Charlotte Close,
4 # Caversham, Reading, Berkshire, United Kingdom RG4 7BY.
5 #
6 # This Original Work is licensed under the European Union Public Licence (EUPL)
7 # v.1.2 and is subject to its terms as set out below.
8 #
9 # If a copy of the EUPL was not distributed with this file, You can obtain
10 # one at https://opensource.org/licenses/EUPL-1.2.
11 #
12 # The 'Compatible Licences' set out in the Appendix to the EUPL (as may be
13 # amended by the European Commission) shall be deemed incompatible for
14 # the purposes of the Work and the provisions of the compatibility
15 # clause in Article 5 of the EUPL shall not apply.
16 #
17 # If using the Work as, or as part of, a network application, by
18 # including the attribution notice(s) required under Article 5 of the EUPL
19 # in the end user terms of the application under an appropriate heading,
20 # such notice(s) shall fulfill the requirements of that article.
21 # ********************************************************************
22 
23 
39 
40 from fiftyone_devicedetection_onpremise.devicedetection_onpremise_pipelinebuilder import DeviceDetectionOnPremisePipelineBuilder
41 from fiftyone_pipeline_core.web import *
42 from flask.helpers import make_response
43 from fiftyone_devicedetection_examples.example_utils import ExampleUtils
44 
45 data_file = ExampleUtils.find_file("51Degrees-LiteV4.1.hash")
46 
47 # First create the device detection pipeline with the desired settings and include required UACH
48 # properties that follows the following format.
49 # SetHeader[Component name][Response header name]
50 # e.g. for browser, platform and hardware component properties to be set in Accept-CH response header
51 # include SetHeaderBrowserAccept-CH, SetHeaderPlatformAccept-CH and SetHeaderHardwareAccept-CH
52 # properties respectively.
53 
54 pipeline = DeviceDetectionOnPremisePipelineBuilder(
55  data_file_path = data_file,
56  licence_keys = "",
57  performance_profile = 'MaxPerformance',
58  auto_update=False).build()
59 
60 from flask import Flask, request
61 
62 app = Flask(__name__)
63 
64 # Helper function to get a property value if it exists and return
65 # the reason why if it doesn't
66 
67 def get_value_helper(flowdata, engine, property_key):
68 
69  engine_properties = getattr(flowdata, engine)
70 
71  try:
72  property_value = getattr(engine_properties, property_key)
73 
74  if property_value.has_value():
75  return property_value.value()
76  else:
77  return property_value.no_value_message()
78  except:
79  return "Not found in datafile"
80 
81 # Create a main route for the device detections
82 
83 @app.route('/')
84 def server():
85 
86  # Create the flowdata object for the device detection
87 
88  flowdata = pipeline.create_flowdata()
89 
90  # Add any information from the request (headers, cookies and any other additional information)
91 
92  flowdata.evidence.add_from_dict(webevidence(request))
93 
94  # Process the flowdata
95 
96  flowdata.process()
97 
98  # Generate the HTML
99 
100  output = "<h2>User Agent Client Hints Example</h2>"
101 
102  output += """
103 
104  <p>
105  By default, the user-agent, sec-ch-ua and sec-ch-ua-mobile HTTP headers
106  are sent.
107  <br />
108  This means that on the first request, the server can determine the
109  browser from sec-ch-ua while other details must be derived from the
110  user-agent.
111  <br />
112  If the server determines that the browser supports client hints, then
113  it may request additional client hints headers by setting the
114  Accept-CH header in the response.
115  <br />
116  Select the <strong>Make second request</strong> button below,
117  to use send another request to the server. This time, any
118  additional client hints headers that have been requested
119  will be included.
120  </p>
121 
122  <button type="button" onclick="redirect()">Make second request</button>
123  <script>
124 
125  // This script will run when button will be clicked and device detection request will again
126  // be sent to the server with all additional client hints that was requested in the previous
127  // response by the server.
128  // Following sequence will be followed.
129  // 1. User will send the first request to the web server for detection.
130  // 2. Web Server will return the properties in response based on the headers sent in the request. Along
131  // with the properties, it will also send a new header field Accept-CH in response indicating the additional
132  // evidence it needs. It builds the new response header using SetHeader[Component name]Accept-CH properties
133  // where Component Name is the name of the component for which properties are required.
134  // 3. When "Make second request" button will be clicked, device detection request will again
135  // be sent to the server with all additional client hints that was requested in the previous
136  // response by the server.
137  // 4. Web Server will return the properties based on the new User Agent CLient Hint headers
138  // being used as evidence.
139 
140  function redirect() {
141  sessionStorage.reloadAfterPageLoad = true;
142  window.location.reload(true);
143  }
144 
145  window.onload = function () {
146  if ( sessionStorage.reloadAfterPageLoad ) {
147  document.getElementById('description').innerHTML = "<p>The information shown below is determined using <strong>User Agent Client Hints</strong> that was sent in the request to obtain additional evidence. If no additional information appears then it may indicate an external problem such as <strong>User Agent Client Hints</strong> being disabled in your browser.</p>";
148  sessionStorage.reloadAfterPageLoad = false;
149  }
150  else{
151  document.getElementById('description').innerHTML = "<p>The following values are determined by sever-side device detection on the first request.</p>";
152  }
153  }
154 
155  </script>
156 
157  <div id="evidence">
158  <strong></br>Evidence values used: </strong>
159  <table>
160  <tr>
161  <th>Key</th>
162  <th>Value</th>
163  </tr>
164 
165  """
166  evidences = pipeline.get_element("device").filter_evidence(flowdata)
167  for key, value in evidences.items():
168  output += "<tr>"
169  output += "<td>" + str(key) + "</td>"
170  output += "<td>" + str(value) + "</td>"
171  output += "</>"
172  output += "</table>"
173  output += "</div>"
174 
175  output += "<div id=description></div>"
176  output += "<div id=\"content\">"
177  output += "<strong>Detection results:</strong></br>"
178  output += "<p>"
179  output += "<b>Hardware Vendor:</b> " + str(get_value_helper(flowdata, "device", "hardwarevendor"))
180  output += "<br />"
181  output += "<b>Hardware Name:</b> " + str(get_value_helper(flowdata, "device", "hardwarename"))
182  output += "<br />"
183  output += "<b>Device Type:</b> " + str(get_value_helper(flowdata, "device", "devicetype"))
184  output += "<br />"
185  output += "<b>Platform Vendor:</b> " + str(get_value_helper(flowdata, "device", "platformvendor"))
186  output += "<br />"
187  output += "<b>Platform Name:</b> " + str(get_value_helper(flowdata, "device", "platformname"))
188  output += "<br />"
189  output += "<b>Platform Version:</b> " + str(get_value_helper(flowdata, "device", "platformversion"))
190  output += "<br />"
191  output += "<b>Browser Vendor:</b> " + str(get_value_helper(flowdata, "device", "browservendor"))
192  output += "<br />"
193  output += "<b>Browser Name:</b> " + str(get_value_helper(flowdata, "device", "browsername"))
194  output += "<br />"
195  output += "<b>Browser Version:</b> " + str(get_value_helper(flowdata, "device", "browserversion"))
196  output += "<br /></div>"
197 
198  # Create a response variable and add response object
199 
200  response = make_response(output)
201 
202  # Some browsers require that extra HTTP headers are explicitly
203  # requested. So set whatever headers are required by the browser in
204  # order to return the evidence needed by the pipeline.
205  # More info on this can be found at
206  # https://51degrees.com/blog/user-agent-client-hints
207 
208  response = set_response_header(flowdata, response)
209 
210  return response