Θέμα

Εικόνες OG στην Python

Αυτός ο οδηγός σάς δείχνει πώς να δημιουργείτε εικόνες OG στην Python με το FastOG — Django, FastAPI ή Flask — υπογράφοντας μια διεύθυνση URL HMAC και αποδίδοντας δυναμικές εικόνες Open Graph εν κινήσει. Με συνδρομή και δωρεάν λογαριασμό (επιλέξτε ένα πρόγραμμα Dynamic API· δημιουργήστε το κλειδί API σας στον πίνακα ελέγχου)· δοκιμάστε το Δωρεάν Εργαλείο Δοκιμής Εικόνων OG για να δείτε ένα πρότυπο πριν από την ενσωμάτωση.

Πλήρης οδηγός για την υλοποίηση διευθύνσεων URL εικόνων OG υπογεγραμμένων με HMAC στην Python.

Γρήγορη Εκκίνηση

1. Δημιουργήστε την ενότητα υπογραφής (signer module)

python
# utils/fastog.py
import hmac
import hashlib
import os
from urllib.parse import quote, urlencode

def _enc(s):
    return quote(str(s), safe='-._~')  # RFC-3986: only unreserved chars

def generate_signed_og_url(params: dict, options: dict = None) -> str:
    options = options or {}
    base_url = options.get('base_url', os.environ.get('FASTOG_BASE_URL', 'https://fastog.com/api/v1/og'))
    api_key = options.get('api_key', os.environ.get('FASTOG_API_KEY'))
    hmac_secret = options.get('hmac_secret', os.environ.get('FASTOG_HMAC_SECRET'))

    if not api_key or not hmac_secret:
        raise ValueError("Missing FASTOG_API_KEY or FASTOG_HMAC_SECRET")

    all_params = {**params, 'key': api_key}
    pairs = []
    for k, v in all_params.items():
        for vv in sorted(v if isinstance(v, list) else [v]):
            pairs.append(f"{_enc(k)}={_enc(vv)}")
    canonical = '&'.join(sorted(pairs))
    signature = hmac.new(
        hmac_secret.encode(),
        f"GET/api/v1/og\n{canonical}".encode(),
        hashlib.sha256
    ).hexdigest()

    return f"{base_url}?{urlencode({**all_params, 's': signature})}"

2. Μεταβλητές περιβάλλοντος

bash
# .env
FASTOG_API_KEY=sk_your_full_api_key_here
FASTOG_HMAC_SECRET=your_64_char_hex_secret_here
bash
pip install python-dotenv
python
# config.py
from dotenv import load_dotenv
load_dotenv()

Django

Υπηρεσία Υπογραφής (Signer Service)

python
# services/fastog.py
from utils.fastog import generate_signed_og_url

class QuickogService:
    @staticmethod
    def get_og_url(template: str, **params) -> str:
        return generate_signed_og_url({
            'template': template,
            **params,
        })

Προβολή (View)

python
# views.py
from django.shortcuts import render
from services.fastog import QuickogService

def blog_post(request, slug):
    post = get_post(slug)

    og_image_url = QuickogService.get_og_url(
        template='blog',
        title=post.title,
        subtitle=post.excerpt,
        author=post.author.name,
    )

    return render(request, 'blog/post.html', {
        'post': post,
        'og_image_url': og_image_url,
    })

Πρότυπο (Template)

django
{# templates/blog/post.html #}
<!DOCTYPE html>
<html>
<head>
    <meta property="og:image" content="{{ og_image_url }}" />
    <meta property="og:title" content="{{ post.title }}" />
    <meta property="og:description" content="{{ post.excerpt }}" />
</head>
<body>
    <h1>{{ post.title }}</h1>
    <p>{{ post.excerpt }}</p>
</body>
</html>

Προσαρμοσμένη Ετικέτα Προτύπου (Custom Template Tag)

python
# templatetags/fastog_tags.py
from django import template
from services.fastog import QuickogService

register = template.Library()

@register.simple_tag
def og_image_url(template_name, **params):
    return QuickogService.get_og_url(template_name, **params)
django
{# In template #}
{% load fastog_tags %}
<meta property="og:image" content="{% og_image_url 'blog' title=post.title subtitle=post.excerpt %}" />

FastAPI

python
# main.py
from fastapi import FastAPI, Query
from pydantic import BaseModel
from utils.fastog import generate_signed_og_url

app = FastAPI()

class OgRequest(BaseModel):
    title: str
    template: str = "default"
    subtitle: str | None = None

@app.get("/api/og")
def generate_og(title: str = Query(...), template: str = Query("default")):
    og_url = generate_signed_og_url({
        'template': template,
        'title': title,
    })
    return {"ogImageUrl": og_url}

@app.get("/blog/{slug}")
async def blog_post(slug: str):
    post = await get_post(slug)

    og_url = generate_signed_og_url({
        'template': 'blog',
        'title': post.title,
        'subtitle': post.excerpt,
    })

    return {"post": post, "ogImageUrl": og_url}

Flask

python
# app.py
from flask import Flask, render_template, request, jsonify
from utils.fastog import generate_signed_og_url

app = Flask(__name__)

@app.route("/blog/<slug>")
def blog_post(slug):
    post = get_post(slug)

    og_image_url = generate_signed_og_url({
        'template': 'blog',
        'title': post['title'],
        'subtitle': post['excerpt'],
    })

    return render_template('blog/post.html', post=post, og_image_url=og_image_url)

@app.route("/api/og")
def api_og():
    title = request.args.get('title')
    template = request.args.get('template', 'default')

    if not title:
        return jsonify({'error': 'Missing title'}), 400

    og_url = generate_signed_og_url({
        'template': template,
        'title': title,
    })

    return jsonify({'ogImageUrl': og_url})

Παράδειγμα Ηλεκτρονικού Εμπορίου

python
# views.py
def product_detail(request, product_id):
    product = get_product(product_id)

    og_image_url = generate_signed_og_url({
        'template': 'ecommerce',
        'title': product.name,
        'price': product.formatted_price,
        'image': product.image_url,
    })

    return render(request, 'products/detail.html', {
        'product': product,
        'og_image_url': og_image_url,
    })

Παράδειγμα Άρθρου Ιστολογίου

python
def user_profile(request, username):
    user = get_user(username)

    og_image_url = generate_signed_og_url({
        'template': 'blog',
        'title': user.name,
        'subtitle': user.bio,
        'author': user.name,
    })

    return render(request, 'profile/show.html', {
        'user': user,
        'og_image_url': og_image_url,
    })

Συχνά Σφάλματα

Υπογραφή Λάθος Μηνύματος

❌ Λάθος: f"GET/api/v1/og{canonical}" — λείπει ο διαχωριστής νέας γραμμής. ✅ Σωστό: f"GET/api/v1/og\n{canonical}" — μέθοδος + διαδρομή, μια νέα γραμμή και στη συνέχεια το κανονικό ερώτημα.

Παράλειψη του key από την Υπογραφή

❌ Λάθος: υπογραφή μόνο των παραμέτρων περιεχομένου σας και προσάρτηση του key στη διεύθυνση URL εκ των υστέρων. ✅ Σωστό: το key συγχωνεύεται στις παραμέτρους πριν κατασκευαστεί το κανονικό ερώτημα και εμφανίζεται στην τελική διεύθυνση URL.

Παράλειψη Κωδικοποίησης URL για Κλειδιά και Τιμές

❌ Λάθος: κατασκευή του κανονικού ερωτήματος με μη επεξεργασμένες, μη κωδικοποιημένες τιμές. ✅ Σωστό: κωδικοποιήστε με ποσοστιαία κωδικοποίηση τόσο τα κλειδιά όσο και τις τιμές με RFC-3986 (safe='-._~') πριν από την υπογραφή — χρησιμοποιήστε το quote, όχι το quote_plus (το οποίο εκπέμπει + για τα κενά και δεν θα ταιριάξει με τον διακομιστή).

401 missing_signature / invalid_signature

Το missing_signature (401) σημαίνει ότι το key ή το s λείπει από τη διεύθυνση URL. Το invalid_signature (401) σημαίνει ότι το κανονικό ερώτημα δεν ταιριάζει — επιβεβαιώστε τη νέα γραμμή στο υπογεγραμμένο μήνυμα, το ίδιο hmac_secret και στις δύο πλευρές και το quote(safe='-._~') (όχι το quote_plus) για κάθε κλειδί και τιμή.

Πλήρης Αναφορά API

Δοκιμάστε το δωρεάν — δεν απαιτείται εγγραφή

Προεπισκόπηση και δοκιμή δυναμικών εικόνων OG σε δευτερόλεπτα.

Ανοίξτε τον Δωρεάν Ελεγκτή Εικόνων OG

A BeCaSimulations site