196def favicon_url(authority: str) -> str:
197 """Function to generate the image URL used for favicons in SearXNG's result
198 lists. The ``authority`` argument (aka netloc / :rfc:`3986`) is usually a
199 (sub-) domain name. This function is used in the HTML (jinja) templates.
200
201 .. code:: html
202
203 <div class="favicon">
204 <img src="{{ favicon_url(result.parsed_url.netloc) }}">
205 </div>
206
207 The returned URL is a route to :py:obj:`favicon_proxy` REST API.
208
209 If the favicon is already in the cache, the returned URL is a `data URL`_
210 (something like ``data:image/png;base64,...``). By generating a data url from
211 the :py:obj:`.cache.FaviconCache`, additional HTTP roundtripps via the
212 :py:obj:`favicon_proxy` are saved. However, it must also be borne in mind
213 that data urls are not cached in the client (web browser).
214
215 .. _data URL: https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URLs
216
217 """
218
219 resolver = sxng_request.preferences.get_value('favicon_resolver')
220
221 if not resolver or resolver not in CFG.resolver_map.keys():
222 return ""
223
224 data_mime = cache.CACHE(resolver, authority)
225
226 if data_mime == (None, None):
227
228 theme = sxng_request.preferences.get_value("theme")
229 return CFG.favicon_data_url(theme=theme)
230
231 if data_mime is not None:
232 data, mime = data_mime
233 return f"data:{mime};base64,{str(base64.b64encode(data), 'utf-8')}"
234
235 h = new_hmac(CFG.secret_key, authority.encode())
236 proxy_url = flask.url_for('favicon_proxy')
237 query = urllib.parse.urlencode({"authority": authority, "h": h})
238 return f"{proxy_url}?{query}"