Source code for duck.http.mimes


[docs] def guess_file_mimetype(filename: str) -> str: """ Determine the MIME type of a file based on its filename or content. This function first attempts to guess the MIME type using the file's extension by leveraging the `mimetypes` module. If the MIME type could not be determined from the filename, it reads the file content and attempts to infer the MIME type from the data. Args: filename (str): The path to the file for which the MIME type needs to be determined. Returns: str: The determined MIME type of the file. Defaults to 'application/octet-stream' if the type cannot be determined. """ import mimetypes mimetype = None if filename: # Attempt to guess the MIME type based on the file extension mimetype, _ = mimetypes.guess_type(filename) return mimetype
[docs] def guess_data_mimetype(data: bytes) -> str: """ Determine the MIME type of the provided content or file based on its initial bytes (magic numbers). Args: data (bytes): The input data for which the MIME type needs to be determined. Returns: str: The determined MIME type of the input data. """ if not data: return "application/octet-stream" html_tags = ( b"<html", b"<!DOCTYPE html", b"<head", b"<body", b"<title", b"<h1", b"<div", b"<span", b"<p", b"<a ", b"<img ", b"<script", b"<style", b"<meta", b"<link", b"<form", b"<table", b"<tr", b"<td", b"<th", b"<ul", b"<ol", b"<li", b"<header", b"<footer", b"<nav", b"<section", b"<article", b"<aside", b"<main", b"<figure", b"<figcaption", b"<blockquote", b"<pre", b"<code", b"<canvas", b"<svg", b"<br", b"<b", ) header = data[:512] # Images if data.startswith(b"\xFF\xD8\xFF"): return "image/jpeg" elif data.startswith(b"\x89PNG\r\n\x1A\n"): return "image/png" elif data.startswith((b"GIF87a", b"GIF89a")): return "image/gif" elif data.startswith(b"BM"): return "image/bmp" elif len(data) >= 12 and data.startswith(b"RIFF") and data[8:12] == b"WEBP": return "image/webp" elif data.startswith(b"\x00\x00\x01\x00"): return "image/vnd.microsoft.icon" elif ( len(data) >= 12 and data[4:8] == b"ftyp" and data[8:12] in ( b"heic", b"heix", b"hevc", b"hevx", b"mif1", b"msf1", b"avif", ) ): return "image/avif" if data[8:12] == b"avif" else "image/heif" elif data.startswith((b"II*\x00", b"MM\x00*")): return "image/tiff" elif b"<svg" in header: return "image/svg+xml" # Documents elif data.startswith(b"%PDF-"): return "application/pdf" elif data.startswith(b"\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1"): return "application/msword" # Archives / Compression elif data.startswith((b"PK\x03\x04", b"PK\x05\x06", b"PK\x07\x08")): return "application/zip" elif data.startswith(b"\x1F\x8B"): return "application/gzip" elif data.startswith(b"BZh"): return "application/x-bzip2" elif data.startswith(b"\xFD7zXZ\x00"): return "application/x-xz" elif data.startswith(b"7z\xBC\xAF\x27\x1C"): return "application/x-7z-compressed" elif data.startswith(b"Rar!\x1A\x07"): return "application/vnd.rar" # Audio elif data.startswith(b"OggS"): return "application/ogg" elif data.startswith(b"fLaC"): return "audio/flac" elif data.startswith(b"RIFF") and data[8:12] == b"WAVE": return "audio/wav" elif data.startswith(b"MThd"): return "audio/midi" elif data.startswith(b"ID3") or data[:2] == b"\xFF\xFB": return "audio/mpeg" # Video elif len(data) >= 12 and data[4:8] == b"ftyp": return "video/mp4" elif len(data) >= 12 and data.startswith(b"RIFF") and data[8:12] == b"AVI ": return "video/x-msvideo" elif data.startswith(b"\x1A\x45\xDF\xA3"): return "video/webm" # Text elif any(tag in header for tag in html_tags): return "text/html" elif header.lstrip().startswith(b"{") and data.rstrip().endswith(b"}"): return "application/json" elif header.lstrip().startswith(b"<"): return "application/xml" elif ( header.startswith(b"/*") or header.startswith(b"@charset") or b"{\n" in header or b"{\r\n" in header ): return "text/css" elif ( header.startswith(b"//") or header.startswith(b"/*") or b"function " in header or b"var " in header or b"let " in header or b"const " in header or b"=>" in header ): return "application/javascript" elif not data or all(32 <= byte <= 126 or byte in (9, 10, 13) for byte in data): return "text/plain" return "application/octet-stream"