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