部署至Heroku后调用Cloudflare托管的Cowin API返回403错误求助
It looks like the CloudFront layer in front of the Cowin API is blocking your requests from Heroku. This is common when cloud services detect non-browser-like requests or when the source IP is flagged for excessive traffic. Let’s walk through the fixes step by step:
1. Add Required Request Headers
CloudFront often blocks requests that don’t include standard browser-like headers. The most critical one is User-Agent—add this to your XMLHttpRequest to mimic a real browser:
const getMsg = () => { var url_orig = 'https://cdn-api.co-vin.in/api/v2/appointment/sessions/public/findByPin' var url = new URL(url_orig) var params = {pincode:'226006', date:'10/5/2021'} url.search = new URLSearchParams(params).toString(); request.open('GET', url, false) // Add browser-like headers request.setRequestHeader('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36'); request.setRequestHeader('Accept-Language', 'en-US,en;q=0.9'); console.log(url) request.send(); console.log(request.responseText,'hello') if (request.readyState == 4 && request.status == 200){ return request.responseText } }
2. Replace Synchronous XMLHttpRequest with Async
Synchronous requests are discouraged in server environments and can trigger odd behavior with cloud proxies. Rewrite your getMsg function to use async/await with promises:
const getMsg = () => { return new Promise((resolve, reject) => { const url_orig = 'https://cdn-api.co-vin.in/api/v2/appointment/sessions/public/findByPin'; const url = new URL(url_orig); const params = {pincode:'226006', date:'10/5/2021'}; url.search = new URLSearchParams(params).toString(); const request = new XMLHttpRequest(); request.open('GET', url, true); request.setRequestHeader('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36'); request.onload = () => { if (request.status >= 200 && request.status < 400) { resolve(request.responseText); } else { reject(new Error(`Request failed with status: ${request.status}`)); } }; request.onerror = () => reject(new Error('Network error occurred')); request.send(); }); }; // Update fetchApi to handle async logic async function fetchApi(){ try { const data = await getMsg(); const cleanedData = data.trim(); const g = JSON.parse(cleanedData); for (const centre in g) { for (const session of g[centre][0]['sessions']) { console.log(session.min_age_limit); } } } catch (err) { console.error('Failed to fetch vaccine data:', err); } }
3. Remove Unnecessary Proxy Code
Your current code includes an http-proxy setup that isn’t used by the API fetch logic. This can introduce unnecessary complexity—simplify your server code:
const express = require('express'); const { URL, URLSearchParams } = require('url'); const cron = require('node-cron'); const app = express(); const PORT = process.env.PORT || 3006; // Include your updated getMsg and fetchApi functions here cron.schedule('* * * * *', () => { fetchApi(); }); app.listen(PORT, () => { console.log(`Server running on port ${PORT}`); });
4. Adjust Request Frequency
Your cron job runs every minute, which might trigger rate limiting from Cowin’s API. Check the official Cowin API docs for rate limits, then adjust the cron schedule (e.g., every 5 minutes with */5 * * * *) to avoid being flagged as abusive.
5. Verify Heroku IP Reputation
In rare cases, Heroku’s shared IP pool might be blocked by CloudFront. If the above fixes don’t work, you could try using Heroku Private Spaces (for dedicated IPs) or check if Cowin allows server-side API calls (some public APIs restrict non-browser requests).
内容的提问来源于stack exchange,提问作者Pratyush Narain

