WordPress Proxy Setup

CORS সমস্যা সমাধানের জন্য বিনামূল্যে Google Apps Script Proxy তৈরি করুন

কেন এটা দরকার?

Browser থেকে সরাসরি WordPress API call করলে CORS error আসে — বেশিরভাগ WordPress hosting এটা block করে। Google Apps Script একটি server-side proxy হিসেবে কাজ করে, তাই CORS problem থাকে না।

সম্পূর্ণ বিনামূল্যে — Google account থাকলেই হবে। Setup সময়: মাত্র 5 মিনিট

1 Google Apps Script খুলুন

নিচের বাটনে ক্লিক করে script.google.com এ যান এবং "New project" ক্লিক করুন।

script.google.com খুলুন

2 নিচের Code Copy করে Paste করুন

Default Code.gs ফাইলের সব content মুছে নিচের code paste করুন:

// ═══════════════════════════════════════════════════════════════════════ // AffiliateEngine — WordPress Full REST API Proxy v3.0 // Handles: Category Fetch (GET) + Article Publish (POST via text/plain) // Deploy : Web App → Execute as Me → Who has access: Anyone // v3.0 FIX: text/plain + base64 GET support to avoid browser CORS preflight // ═══════════════════════════════════════════════════════════════════════ // ── doGet: Category Fetch + base64 encoded proxy requests ──────────── function doGet(e) { var params = e.parameter; // ── base64 encoded proxy request (Strategy B from browser) ──────────── if (params.action === 'proxy' && params.payload) { try { var decoded = Utilities.newBlob(Utilities.base64Decode(params.payload)).getDataAsString(); var payload = JSON.parse(decoded); return handleProxyRequest(payload); } catch(err) { return makeJSON({error: 'Bad payload: ' + err.toString(), __status: 400}); } } // ── Standard category fetch ──────────────────────────────────────────── var siteUrl = params.site || ''; var endpoint = params.endpoint || '/wp/v2/categories?per_page=100'; var user = params.user || ''; var pass = params.pass || ''; if (!siteUrl) return makeJSON({error: 'Missing site parameter'}); try { siteUrl = siteUrl.replace(/\/+$/, ''); var options = buildOptions('get', user, pass, null); var apiUrl = siteUrl + '/wp-json' + endpoint; var response = UrlFetchApp.fetch(apiUrl, options); var code = response.getResponseCode(); var body = response.getContentText(); if (code !== 200) { var epBase = endpoint.split('?')[0]; var epQs = endpoint.split('?')[1] || ''; var ep2 = '/?rest_route=' + encodeURIComponent(epBase) + (epQs ? '&' + epQs : ''); var r2 = UrlFetchApp.fetch(siteUrl + ep2, options); if (r2.getResponseCode() === 200) body = r2.getContentText(); } return ContentService.createTextOutput(body).setMimeType(ContentService.MimeType.JSON); } catch(err) { return makeJSON({error: err.toString()}); } } // ── doPost: Article Publish (text/plain or application/json body) ───── function doPost(e) { try { var raw = e.postData ? e.postData.contents : ''; if (!raw) return makeJSON({error: 'Empty body', __status: 400}); var payload = JSON.parse(raw); // works for both text/plain and application/json return handleProxyRequest(payload); } catch(err) { return makeJSON({error: err.toString(), __status: 500}); } } // ── handleProxyRequest: core logic (shared by doPost + doGet base64) ── function handleProxyRequest(payload) { try { var siteUrl = (payload.site || '').replace(/\/+$/, ''); var endpoint = payload.endpoint || '/wp/v2/posts'; var method = (payload.method || 'POST').toLowerCase(); var user = payload.user || ''; var pass = payload.pass || ''; var body = payload.body || {}; if (!siteUrl) return makeJSON({error: 'Missing site', __status: 400}); var options = buildOptions(method, user, pass, JSON.stringify(body)); // Try /wp-json/ first var apiUrl = siteUrl + '/wp-json' + endpoint; var response = UrlFetchApp.fetch(apiUrl, options); var rCode = response.getResponseCode(); var rBody = response.getContentText(); // Fallback to /?rest_route= if needed if (rCode !== 200 && rCode !== 201 && rCode !== 204) { var apiUrl2 = siteUrl + '/?rest_route=' + encodeURIComponent(endpoint); var resp2 = UrlFetchApp.fetch(apiUrl2, options); if (resp2.getResponseCode() === 200 || resp2.getResponseCode() === 201) { rCode = resp2.getResponseCode(); rBody = resp2.getContentText(); } } var parsed = {}; try { parsed = JSON.parse(rBody); } catch(x) { parsed = {raw: rBody}; } parsed.__status = rCode; return ContentService.createTextOutput(JSON.stringify(parsed)).setMimeType(ContentService.MimeType.JSON); } catch(err) { return makeJSON({error: err.toString(), __status: 500}); } } // ── buildOptions: UrlFetchApp options builder ───────────────────────── function buildOptions(method, user, pass, bodyStr) { var opts = { method: method, muteHttpExceptions: true, followRedirects: true, headers: {'Content-Type': 'application/json'} }; if (user && pass) opts.headers['Authorization'] = 'Basic ' + Utilities.base64Encode(user + ':' + pass); if (bodyStr && method !== 'get') opts.payload = bodyStr; return opts; } // ── makeJSON / makeResponse: helpers ───────────────────────────────── function makeJSON(obj) { return ContentService.createTextOutput(JSON.stringify(obj)).setMimeType(ContentService.MimeType.JSON); } function makeResponse(obj) { return makeJSON(obj); }

3 Deploy করুন

  1. উপরে "Deploy" বাটন ক্লিক করুন → "New deployment"
  2. Type এ "Web app" select করুন
  3. "Execute as": Me
  4. "Who has access": Anyone (এটা অবশ্যই Anyone করুন)
  5. "Deploy" ক্লিক করুন
  6. Google permission চাইলে "Authorize access" ক্লিক করুন
  7. Web app URL copy করুন — এটাই আপনার Proxy URL
URL এর format হবে:
https://script.google.com/macros/s/XXXXXXXXXXXXXXXXXX/exec

4 Proxy URL Test করুন

Deploy করার পর নিচে Proxy URL দিয়ে test করুন:

5 WordPress Publisher এ যোগ করুন

  1. WordPress Publisher এ যান
  2. "+ Add WordPress Site" বা Edit ক্লিক করুন
  3. "Proxy URL" field এ আপনার GAS URL paste করুন
  4. Save করুন
  5. এখন "Fetch from WordPress" কাজ করবে ✅
Proxy URL একবার set করলে সব সময় কাজ করবে। Google Apps Script প্রতিদিন 6 ঘণ্টা free execution দেয় — আপনার জন্য যথেষ্ট।

সাধারণ প্রশ্ন

🔒 এটা কি নিরাপদ?

GAS script শুধু category fetch করে, কোনো data save করে না। URL টি শুধু আপনার জানা উচিত।

💰 কোনো খরচ আছে?

না, সম্পূর্ণ বিনামূল্যে। Google account থাকলেই যথেষ্ট।

⚠️ "Authorization required" error আসলে?

Deploy এর সময় "Who has access" অবশ্যই Anyone করতে হবে।