Θέμα

Γρήγορη Εκκίνηση — Δημιουργήστε την Πρώτη σας Εικόνα OG

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

Πώς λειτουργεί — Αρχιτεκτονική

Το FastOG είναι σχεδιασμένο για εικόνες OG κατ' απαίτηση: ο ιστότοπός σας υπογράφει μια διεύθυνση URL τη στιγμή της απόδοσης της σελίδας, ο ανιχνευτής την ανακτά, το FastOG αποδίδει το PNG μία φορά και το Cloudflare το αποθηκεύει στην κρυφή μνήμη, ώστε κάθε μεταγενέστερη ανάκτηση να είναι άμεση και δωρεάν.

sequenceDiagram
    participant You as You share a link
    participant Crawler as Social crawler
    participant Site as Your website
    participant FastOG as FastOG API
    participant Edge as Edge cache

    You->>Crawler: share a link to your post
    Crawler->>Site: GET the page without JavaScript
    Site->>Site: sign the og:image URL at render time
    Site-->>Crawler: HTML with signed og:image URL
    Crawler->>Edge: fetch the og:image URL
    Edge->>FastOG: cache miss, first time
    FastOG->>FastOG: verify the HMAC covers the exact params
    FastOG-->>Edge: render PNG, counts 1 toward monthly quota, cached for 1 year
    Edge-->>Crawler: PNG
    Crawler-->>You: image shown in the post preview
    Note over Edge, Crawler: identical params and URL mean a cache hit with no render

Οι τρεις κανόνες που το κάνουν να «λειτουργεί απλά»

  1. Υπογράψτε το περιεχόμενο, όχι το ρολόι. Η υπογραφή καλύπτει κάθε παράμετρο (τίτλο, πρότυπο, …). Οι ίδιες παράμετροι παράγουν πάντα την ίδια διεύθυνση URL — αυτό είναι που κάνει την κρυφή μνήμη του edge να λειτουργεί: ίδιο περιεχόμενο → ίδια διεύθυνση URL → μόνιμο cache hit.
  2. Η εικόνα είναι μόνιμη μετά την πρώτη απόδοση. Η υπογραφή ελέγχει μόνο την πρώτη απόδοση. Μόλις αποδοθεί μια εικόνα, το edge του FastOG τη διατηρεί για ένα έτος με βάση τις παραμέτρους περιεχομένου — τα μεταγενέστερα αιτήματα με τις ίδιες παραμέτρους εξυπηρετούνται από το edge και ποτέ δεν φτάνουν στον renderer (δεν προσμετρώνται στο όριό σας). Μια εσφαλμένη υπογραφή σε αποθηκευμένο περιεχόμενο εξακολουθεί να επιστρέφει το αποθηκευμένο PNG (η απόκριση αναφέρει ποιο επίπεδο απάντησε: X-FastOG-Worker-Cache: HIT ή R2)· μόνο ένα miss στην κρυφή μνήμη λαμβάνει 401.
  3. Η μοναδική περίπτωση αποτυχίας. Μια παραποιημένη διεύθυνση URL (κάποιος αλλάζει το title/template) λαμβάνει 401 από το FastOG σε cache miss — επομένως δεν μπορεί ποτέ να χρησιμοποιηθεί για να εξαντλήσει το όριό σας. Οι νόμιμες διευθύνσεις URL δεν λήγουν ποτέ: παραμένουν έγκυρες έως ότου περιστρέψετε το μυστικό HMAC του κλειδιού.

1. Λάβετε το API Key και το HMAC Secret σας

  1. Μεταβείτε στο FastOG Dashboard → API Keys

  2. Κάντε κλικ στο "Create New API Key"

  3. Δώστε του ένα όνομα (π.χ., "Production Website")

  4. Αντιγράψτε και τις δύο τιμές (εμφανίζονται μόνο μία φορά!):

    • API Key: sk_... (32 χαρακτήρες μετά το πρόθεμα)
    • HMAC Secret: συμβολοσειρά hex 64 χαρακτήρων
  5. Αποθηκεύστε τις στο περιβάλλον σας:

env
# Your website backend .env
FASTOG_API_KEY=sk_your_full_api_key
FASTOG_HMAC_SECRET=a1b2c3d4e5f6...  # 64 chars
FASTOG_API_URL=https://fastog.com/api/v1/og

2. Υλοποίηση Συνάρτησης Υπογραφής URL

Για πλήρη σεμινάρια με πολλαπλά frameworks και μοτίβα, δείτε:

Node.js / Next.js

javascript
// lib/fastog-signer.js
import crypto from "crypto";

// RFC-3986 encode (encodeURIComponent leaves !'()* unencoded).
const enc = (s) =>
    encodeURIComponent(s).replace(
        /[!'()*]/g,
        (c) => "%" + c.charCodeAt(0).toString(16).toUpperCase(),
    );

export function generateOgImageUrl(params) {
    const baseUrl = process.env.FASTOG_API_URL;
    const apiKey = process.env.FASTOG_API_KEY;
    const hmacSecret = process.env.FASTOG_HMAC_SECRET;

    const all = { ...params, key: apiKey };

    // Canonical: every param (except s), sorted, RFC-3986 encoded, joined with "&".
    const pairs = [];
    for (const [k, v] of Object.entries(all)) {
        for (const vv of Array.isArray(v) ? v : [v])
            pairs.push(`${enc(k)}=${enc(vv)}`);
    }
    pairs.sort();
    const canonical = pairs.join("&");

    // Content-signed: message = path + canonical query. No timestamp.
    const signature = crypto
        .createHmac("sha256", hmacSecret)
        .update(`GET/api/v1/og\n${canonical}`)
        .digest("hex");

    const url = new URL(baseUrl);
    for (const [k, v] of Object.entries(all)) {
        for (const vv of Array.isArray(v) ? v : [v])
            url.searchParams.append(k, vv);
    }
    url.searchParams.set("s", signature);
    return url.toString();
}

PHP (Laravel)

php
// app/Services/QuickogSigner.php
function generateOgImageUrl(array $params): string
{
    $baseUrl = config('services.fastog.api_url', 'https://fastog.com/api/v1/og');
    $apiKey = config('services.fastog.api_key');
    $hmacSecret = config('services.fastog.hmac_secret');

    $all = array_merge($params, ['key' => $apiKey]);

    // Canonical: every param except s, keys sorted (array values sorted too),
    // RFC-3986 encoded, joined with '&'. Content-signed — no timestamp.
    $pairs = [];
    foreach ($all as $k => $v) {
        $values = is_array($v) ? $v : [$v];
        sort($values, SORT_STRING);
        foreach ($values as $vv) {
            $pairs[] = rawurlencode((string) $k) . '=' . rawurlencode((string) $vv);
        }
    }
    sort($pairs, SORT_STRING);
    $canonical = implode('&', $pairs);

    $signature = hash_hmac('sha256', 'GET/api/v1/og' . "\n" . $canonical, $hmacSecret);

    return $baseUrl . '?' . http_build_query(array_merge($all, ['s' => $signature]));
}

Python (Django/FastAPI)

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_og_image_url(params: dict) -> str:
    base_url = os.environ['FASTOG_API_URL']
    api_key = os.environ['FASTOG_API_KEY']
    hmac_secret = os.environ['FASTOG_HMAC_SECRET']

    all_params = {**params, 'key': api_key}

    # Canonical: every param except s, sorted, RFC-3986 encoded, joined with '&'.
    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))

    # Content-signed: message = path + canonical query. No timestamp.
    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})}"

3. Χρήση στο Ιστολόγιο/Ιστότοπό σας

Next.js App Router

tsx
// app/blog/[slug]/page.tsx
import { generateOgImageUrl } from "@/lib/fastog-signer";

export async function generateMetadata({ params }) {
    const post = await getPost(params.slug);

    const ogImageUrl = generateOgImageUrl({
        template: "blog",
        title: post.title,
        subtitle: post.excerpt,
        author: post.author.name,
    });

    return {
        title: post.title,
        description: post.excerpt,
        openGraph: {
            images: [ogImageUrl],
        },
    };
}

Laravel Blade

blade
{{-- resources/views/blog/show.blade.php --}}
@php
    $ogImageUrl = generateOgImageUrl([
        'template' => 'blog',
        'title' => $post->title,
        'subtitle' => $post->excerpt,
        'author' => $post->author->name,
    ]);
@endphp

<head>
    <meta property="og:image" content="{{ $ogImageUrl }}" />
    <meta property="og:title" content="{{ $post->title }}" />
    <meta property="og:description" content="{{ $post->excerpt }}" />
</head>

Πρότυπο Django

django
{# blog/post_detail.html #}
{% load fastog_tags %}

<head>
    <meta property="og:image" content="{% generate_og_image_url post %}" />
    <meta property="og:title" content="{{ post.title }}" />
    <meta property="og:description" content="{{ post.excerpt }}" />
</head>

4. Δοκιμάστε την Υλοποίησή σας

bash
# Generate a test URL
node -e "
const { generateOgImageUrl } = require('./lib/fastog-signer');
console.log(generateOgImageUrl({ title: 'Test', template: 'default' }));
"

# Test with curl
curl "https://fastog.com/api/v1/og?title=Test&key=sk_quick_123abc&s=<sig>"

Αναμενόμενο αποτέλεσμα:

  • ✅ Έγκυρη υπογραφή → Επιστρέφει εικόνα OG
  • ❌ Παραποιημένη παράμετρος (π.χ. title άλλαξε) → {"code": "invalid_signature"}
  • ❌ Μη έγκυρη υπογραφή → {"code": "invalid_signature"}

5. Λίστα ελέγχου ασφαλείας

  • [ ] Το μυστικό HMAC αποθηκεύεται σε μεταβλητές περιβάλλοντος (όχι στον κώδικα)
  • [ ] Χρήση HTTPS για όλα τα αιτήματα
  • [ ] Το μυστικό δεν εκτίθεται ποτέ σε JavaScript από την πλευρά του πελάτη
  • [ ] Παρακολούθηση αποτυχημένων προσπαθειών υπογραφής

6. Χειρισμός Σφαλμάτων

javascript
if (response.status === 401) {
    const error = await response.json();

    switch (error.code) {
        case "missing_signature":
            // URL is missing `key` or `s` — re-generate it with your signer.
            break;
        case "invalid_signature":
            // A param changed after signing, or the secret doesn't match.
            // Re-sign the URL after any content change; verify the secret on both sides.
            break;
    }
}

Επόμενα Βήματα

  1. Υλοποιήστε την υπογραφή στο backend του ιστοτόπου σας (δείτε τα σεμινάρια)
  2. Δοκιμάστε με το FastOG API
  3. Παρακολουθήστε τα αρχεία καταγραφής για αποτυχημένες προσπάθειες υπογραφής
  4. Ρυθμίστε ειδοποιήσεις για επαναλαμβανόμενες αποτυχίες

Για πλήρη τεκμηρίωση, δείτε τον Οδηγό Υπογραφής HMAC.

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

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

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

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

A BeCaSimulations site