Skip to content

Instantly share code, notes, and snippets.

@dreness
Created March 29, 2024 06:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dreness/6ecb67e4795dd0dc42a148493ef42e15 to your computer and use it in GitHub Desktop.
Save dreness/6ecb67e4795dd0dc42a148493ef42e15 to your computer and use it in GitHub Desktop.
Favicon Force-feeder
import http.server
import socketserver
import random
import os
import uuid
from http import HTTPStatus
'''
I wanted a quick way to spawn a bunch of Safari tabs with distinct favicons, so made a little webserver
to rotate through some PNGs. A substantially smaller program was sufficient for Chrome, which does what
I expect when I manually reload a page.
Safari loads the favicon once per window, regardless of the number of tabs or reload attempts, because
Safari assumes it's safe to re-use. An 'empty cache' yields one subsequent favicon load. More importantly,
Safari looks down at you for having the temerity to engage in what might be deemed 'wasteful' behavior by
trying to generate a bunch of 'useless' network traffic, so your commands are silently degraded.
Anywho, to get Safari to load a distinct favicon in each tab, it's not enough to advertise a unique favicon
name in the rel="icon" link, you also need each tab to use a unique request URI.
'''
PORT = 9876
FAVICONS_DIR = "/Users/andre/Desktop/stuff/favs_48" # Directory where your PNG images are stored
class MyWebServer(http.server.SimpleHTTPRequestHandler):
def do_GET(self):
if self.path == '/':
self.redirect_to_uuid()
elif self.path.endswith('.ico'):
self.next_favicon()
else:
self.serve_main_page()
def redirect_to_uuid(self):
# Generate a fresh UUID
new_path = '/' + str(uuid.uuid4())
self.send_response(HTTPStatus.FOUND)
self.send_header("Location", new_path)
self.end_headers()
def serve_main_page(self):
# Serve a simple HTML page with a title and a favicon
# Use in-line css to make the text large, with a nice font.
favname = '/' + str(uuid.uuid4())
content = """
<html>
<head>
<title>MyFavs!</title>
<link rel="icon" type="image/png" href="http://127.0.0.1:9876{favname}.ico">
<style>
h1 {{
font-family: 'Arial', sans-serif;
font-size: 1em;
color: #333;
text-align: center;
margin-top: 20vh;
}}
a {{
color: #007bff;
text-decoration: none;
}}
a:hover {{
text-decoration: underline;
}}
</style>
</head>
<body>
<h1>Press on it for a random <a href="/" target="_blank">favicon</a>!</h1>
</body>
</html>
""".format(favname=favname)
content = bytes(content, 'utf-8')
self.send_response(HTTPStatus.OK)
self.send_header("Content-type", "text/html; charset=utf-8")
self.end_headers()
self.wfile.write(content)
def next_favicon(self):
try:
# Select the next favicon file
global n
n += 1
if n >= len(files):
n = 0
favicon_path = os.path.join(FAVICONS_DIR, files[n])
# Read and serve the selected file
with open(favicon_path, 'rb') as file:
self.send_response(HTTPStatus.OK)
self.send_header("Content-type", "image/png")
self.end_headers()
self.wfile.write(file.read())
# log the name of the file we sent
print(f"Sent favicon: {favicon_path}")
except Exception as e:
self.send_error(HTTPStatus.INTERNAL_SERVER_ERROR, f"Error serving favicon: {e}")
httpd = socketserver.TCPServer(("", PORT), MyWebServer)
print(f"Serving at port {PORT}")
# List all PNG files in the specified directory
files = [f for f in os.listdir(FAVICONS_DIR) if f.endswith('.png')]
if not files:
raise FileNotFoundError("No PNG files found in the directory")
n = 0
httpd.serve_forever()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment