Εικόνες OG σε Ruby on Rails
Δημιουργήστε εικόνες OG σε Ruby on Rails με τη συνδρομητική Dynamic API της FastOG — με συνδρομή στο Dynamic API (δημιουργήστε το κλειδί API σας στον πίνακα ελέγχου). Κάντε προεπισκόπηση στο Δωρεάν Εργαλείο Δοκιμής Εικόνων OG και, στη συνέχεια, αποδώστε δυναμικές εικόνες Open Graph από την εφαρμογή Rails με υπογεγραμμένα URL μέσω HMAC.
Γρήγορη εκκίνηση
1. Δημιουργήστε την υπηρεσία υπογραφής (signer service)
# app/services/fastog_signer.rb
class QuickogSigner
def self.generate_signed_og_url(params, options = {})
base_url = options[:base_url] || ENV.fetch("FASTOG_BASE_URL", "https://fastog.com/api/v1/og")
api_key = options[:api_key] || ENV.fetch("FASTOG_API_KEY")
hmac_secret = options[:hmac_secret] || ENV.fetch("FASTOG_HMAC_SECRET")
raise "Missing FASTOG_API_KEY or FASTOG_HMAC_SECRET" unless api_key && hmac_secret
all = params.merge(key: api_key)
pairs = all.flat_map do |k, v|
Array(v).sort.map { |vv| "#{enc(k)}=#{enc(vv)}" }
end
canonical = pairs.sort.join("&")
signature = OpenSSL::HMAC.hexdigest("SHA256", hmac_secret, "GET/api/v1/og\n#{canonical}")
"#{base_url}?#{URI.encode_www_form(all.merge(s: signature))}"
end
def self.enc(s)
s.to_s.gsub(/[^A-Za-z0-9\-._~]/) { |c| c.bytes.map { |b| "%%%02X" % b }.join }
end
private_class_method :enc
end
Γιατί ένα προσαρμοσμένο enc; Κωδικοποιεί με ποσοστό (percent-encode) χρησιμοποιώντας κεφαλαία δεκαεξαδικά, αφήνοντας μόνο τα -._~ μη δεσμευμένα — έτσι τα κενά γίνονται %20, ποτέ +, ταιριάζοντας με το rawurlencode του διακομιστή. Αν αντικαταστήσετε με CGI.escape ή URI.encode_www_form_component, και τα δύο εκπέμπουν + για τα κενά: κανονικοποιήστε πρώτα με .gsub('+', '%20').
2. Ρύθμιση παραμέτρων
# config/application.rb
config.fastog = ActiveSupport::OrderedOptions.new
config.fastog.api_key = ENV.fetch("FASTOG_API_KEY", nil)
config.fastog.hmac_secret = ENV.fetch("FASTOG_HMAC_SECRET", nil)
config.fastog.base_url = ENV.fetch("FASTOG_BASE_URL", "https://fastog.com/api/v1/og")
# .env
FASTOG_API_KEY=sk_your_full_api_key_here
FASTOG_HMAC_SECRET=your_64_char_hex_secret_here
Controller
# app/controllers/blog_controller.rb
class BlogController < ApplicationController
def show
@post = Post.find_by!(slug: params[:slug])
@og_image_url = QuickogSigner.generate_signed_og_url(
template: "blog",
title: @post.title,
subtitle: @post.excerpt,
author: @post.author.name
)
end
end
Προβολή
<!-- app/views/blog/show.html.erb -->
<% content_for :head do %>
<meta property="og:image" content="<%= @og_image_url %>" />
<meta property="og:title" content="<%= @post.title %>" />
<meta property="og:description" content="<%= @post.excerpt %>" />
<% end %>
<article>
<h1><%= @post.title %></h1>
<p><%= @post.excerpt %></p>
</article>
Διάταξη
<!-- app/views/layouts/application.html.erb -->
<head>
<%= yield :head %>
</head>
Βοηθητικό
# app/helpers/fastog_helper.rb
module QuickogHelper
def og_image_url(template:, **params)
QuickogSigner.generate_signed_og_url({ template: template }.merge(params))
end
end
<!-- In view -->
<meta property="og:image" content="<%= og_image_url(template: 'blog', title: @post.title) %>" />
Παράδειγμα Ηλεκτρονικού Εμπορίου
# app/controllers/products_controller.rb
class ProductsController < ApplicationController
def show
@product = Product.find(params[:id])
@og_image_url = QuickogSigner.generate_signed_og_url(
template: "ecommerce",
title: @product.name,
price: @product.formatted_price,
image: @product.image_url
)
end
end
Παράδειγμα Άρθρου Ιστολογίου
# app/controllers/users_controller.rb
class UsersController < ApplicationController
def show
@user = User.find_by!(username: params[:username])
@og_image_url = QuickogSigner.generate_signed_og_url(
template: "blog",
title: @user.name,
subtitle: @user.bio,
author: @user.name
)
end
end
Τελικό Σημείο API
# config/routes.rb
get "api/og", to: "api/og#generate"
# app/controllers/api/og_controller.rb
module Api
class OgController < ApplicationController
skip_before_action :verify_authenticity_token
def generate
title = params[:title]
template = params[:template] || "default"
unless title
return render json: { error: "Missing title" }, status: :bad_request
end
og_image_url = QuickogSigner.generate_signed_og_url(
template: template,
title: title
)
render json: { ogImageUrl: og_image_url }
end
end
end
Turbo/Hotwire
<!-- app/views/blog/_post.html.erb -->
<%= turbo_frame_tag "post_#{@post.id}" do %>
<meta property="og:image" content="<%= og_image_url(template: 'blog', title: @post.title) %>" />
<h2><%= link_to @post.title, blog_path(@post) %></h2>
<% end %>
Συνήθη Λάθη
Υπογραφή Λάθος Μηνύματος
❌ Λάθος: "GET/api/v1/og#{canonical}" — λείπει ο διαχωριστής νέας γραμμής.
✅ Σωστό: "GET/api/v1/og\n#{canonical}" — μέθοδος + διαδρομή, μια νέα γραμμή και μετά το κανονικό ερώτημα.
Παράλειψη του key από την Υπογραφή
❌ Λάθος: υπογραφή μόνο των παραμέτρων περιεχομένου και προσάρτηση του key στη διεύθυνση URL εκ των υστέρων.
✅ Σωστό: το key συγχωνεύεται στις παραμέτρους πριν δημιουργηθεί το κανονικό ερώτημα και εμφανίζεται στην τελική διεύθυνση URL.
401 missing_signature / invalid_signature
Το missing_signature (401) σημαίνει ότι το key ή το s λείπει από τη διεύθυνση URL. Το invalid_signature (401) σημαίνει ότι το κανονικό δεν ταιριάζει — επιβεβαιώστε τη νέα γραμμή στο υπογεγραμμένο μήνυμα, το ίδιο hmac_secret και στις δύο πλευρές και ότι το enc κωδικοποιεί τα κενά ως %20 (ποτέ ως +).
Έκθεση του HMAC Secret
Μην εκθέτετε ποτέ το FASTOG_HMAC_SECRET σε JavaScript στο frontend ή σε κώδικα από την πλευρά του πελάτη.