Sử dụng Cloudflare Workers (gói Miễn phí vô cùng rộng rãi, cho phép 100.000 yêu cầu/ngày) làm "trạm trung chuyển" là giải pháp bảo mật tối ưu nhất.
Khi áp dụng phương pháp này, quy trình xử lý sẽ là:
Blogger của bạn → Cloudflare Worker → Gemini API.
Người dùng xem bằng DevTools (F12) chỉ thấy URL của Cloudflare Worker chứ hoàn toàn không thấy Gemini API Key.
1. Bước 1: Tạo tài khoản & Worker trên Cloudflare: Miễn phí & không cần thẻ tín dụng.
-
Truy cập Cloudflare.com và đăng ký một tài khoản miễn phí.
-
Tại menu bên trái, chọn Build > Workers & Pages > nhấn Create application > chọn Create Worker.(có thể chọn Hello World rồi sửa code sau)
-
Đặt tên cho Worker (ví dụ:
my-gemini-proxy) rồi nhấn Deploy.
2. Bước 2: Giấu API Key vào biến môi trường (Environment Variable):
Lưu trữ bảo mật.
-
Sau khi Deploy thành công, nhấn vào Settings của Worker đó.
-
Chọn mục Variables and Secrets (hoặc Variables) ở menu bên trái.
-
Tại phần Secrets, nhấn Add variable:
-
Variable name:
GEMINI_API_KEY -
Value: Dán Gemini API Key của bạn vào đây (lấy trong trang https://aistudio.google.com/)
-
-
Nhấn Encrypt and Save (Mã hóa và Lưu). Lúc này Key đã được lưu an toàn phía Server của Cloudflare.
3. Bước 3: Viết mã xử lý cho Cloudflare Worker: Nhận Prompt & Gọi Gemini.
-
Quay lại trang quản lý Worker, chọn Edit code (hoặc nút Quick Edit ở góc trên bên phải).
-
Xóa toàn bộ đoạn mã mặc định và dán đoạn mã bên dưới vào:
- Ghi chú: Gemini lỗi quá nên đổi sang Groq dùng model OpenAI
export default {
async fetch(request, env) {
// 1. Cho phép tất cả Domain & Method kết nối
const corsHeaders = {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "*",
"Access-Control-Allow-Headers": "*",
};
// 2. Xử lý Preflight CORS thành công lập tức
if (request.method === "OPTIONS") {
return new Response(null, { status: 204, headers: corsHeaders });
}
// 3. Đọc prompt từ mọi nguồn (POST Body hoặc GET Query trên URL)
let userPrompt = "";
try {
if (request.method === "POST") {
const body = await request.json();
userPrompt = body.prompt || body.message || body.text || "";
} else {
const url = new URL(request.url);
userPrompt = url.searchParams.get("prompt") || "";
}
} catch (e) {
userPrompt = "";
}
// 4. Khi nhấn Send trên tab Test của Cloudflare hoặc mở link trực tiếp trên trình duyệt
if (!userPrompt) {
return new Response("Worker đang chạy ngon lành! Không còn lỗi 405.", {
status: 200,
headers: { ...corsHeaders, "Content-Type": "text/plain; charset=utf-8" }
});
}
const apiKey = env.GROQ_API_KEY;
if (!apiKey) {
return new Response(JSON.stringify({ error: "Chưa cấu hình GROQ_API_KEY trong Variables" }), {
status: 500,
headers: { ...corsHeaders, "Content-Type": "application/json" }
});
}
// 5. Gửi request sang Groq API
try {
const response = await fetch("https://api.groq.com/openai/v1/chat/completions", {
method: "POST",
headers: {
"Authorization": `Bearer ${apiKey}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
model: "openai/gpt-oss-120b",
messages: [
{ role: "system", content: "Bạn là trợ lý AI trên lophocvitinh.com. Hãy trả lời ngắn gọn bằng tiếng Việt." },
{ role: "user", content: userPrompt }
]
})
});
const data = await response.json();
if (data.error) {
return new Response(JSON.stringify({ error: data.error.message }), {
status: 400,
headers: { ...corsHeaders, "Content-Type": "application/json" }
});
}
const text = data.choices[0]?.message?.content || "Không có phản hồi";
return new Response(JSON.stringify({
candidates: [{ content: { parts: [{ text: text }] } }]
}), {
headers: { ...corsHeaders, "Content-Type": "application/json" }
});
} catch (err) {
return new Response(JSON.stringify({ error: err.message }), {
status: 500,
headers: { ...corsHeaders, "Content-Type": "application/json" }
});
}
}
};
-
Nhấn Save and Deploy.
-
Copy lại đường dẫn Worker của bạn (ví dụ:
[https://my-gemini-proxy.your-subdomain.workers.dev](https://my-gemini-proxy.your-subdomain.workers.dev))).
4. Bước 4: Cập nhật JavaScript trên giao diện Blogger: Cập nhật Front-end Blogger.
Thay thế đoạn mã JavaScript trong tiện ích HTML/JavaScript cũ trên Blogger thành mã mới dưới đây:
<div class="ai-search-container">
<input type="text" id="ai-prompt-input" placeholder="Hỏi AI bất cứ điều gì..." />
<button id="ai-submit-btn" onclick="sendPromptToAI()">Hỏi AI</button>
</div>
<div id="ai-response-box" style="margin-top: 15px; padding: 12px; border: 1px solid #ddd; background: #f9f9f9; display: none;">
<strong style="color: #333;">Trả lời từ AI:</strong>
<div id="ai-output" style="margin-top: 8px; white-space: pre-wrap;"></div>
</div>
<script>
async function sendPromptToAI() {
const promptInput = document.getElementById('ai-prompt-input').value.trim();
const outputBox = document.getElementById('ai-output');
const responseContainer = document.getElementById('ai-response-box');
const submitBtn = document.getElementById('ai-submit-btn');
if (!promptInput) {
alert('Vui lòng nhập nội dung câu hỏi!');
return;
}
const WORKER_URL = "https://my-gemini-proxy.email.workers.dev/";
responseContainer.style.display = 'block';
outputBox.innerText = 'AI đang suy nghĩ, vui lòng đợi...';
submitBtn.disabled = true;
try {
const response = await fetch(WORKER_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ prompt: promptInput })
});
const data = await response.json();
if (data.error) {
outputBox.innerText = 'Lỗi: ' + data.error;
} else if (data.candidates && data.candidates[0]?.content?.parts[0]?.text) {
outputBox.innerText = data.candidates[0].content.parts[0].text;
} else {
outputBox.innerText = 'Không nhận được phản hồi hợp lệ từ AI.';
}
} catch (error) {
console.error('Lỗi kết nối:', error);
outputBox.innerText = 'Đã xảy ra lỗi kết nối. Vui lòng thử lại!';
} finally {
submitBtn.disabled = false;
}
}
</script>
Kết quả sau khi thiết lập:
-
Khi người dùng mở DevTools (F12) trên trang Blogger của bạn, họ chỉ thấy duy nhất yêu cầu
POSTgửi tớiWORKER_URL. -
API Key nằm an toàn trong Secrets của Cloudflare.
-
Tên miền ngoài list
allowedOriginsẽ bị chặn ngay bởi cơ chế CORS của Worker, tránh tình trạng ai đó copy URL Worker của bạn đi dán vào trang của họ.



Không có nhận xét nào:
Đăng nhận xét