Ang HTTP/HTTPS Debugging Nightmare: Isang 24-Oras na Paglalakbay sa Mixed Content Hell
Gumugol ako ng 24 oras sa pag-debug kung bakit patuloy na gumagawa ang aking React app ng HTTP requests mula sa HTTPS pages—kahit kino-convert ng code ko ang mga ito. Nakagulat ang salarin.
---
Update (Nobyembre 2025): Live na ang STRATUM sa Private Alpha! Ang 9-agent marketing platform na binanggit sa post na ito ay tumatanggap ng mga maagang testers. Mag-request ng access sa stratum.chandlernguyen.com o basahin ang buong launch story.
---
Context: Nagpapatuloy ang Marketing Platform Journey
Naaalala mo yung September post kung saan sinabi kong speed-running ako ng 10-agent marketing platform habang natutulog ng tanghali? Apat na linggo pa lang, mayroon akong 3 working agents at target ko ang Oktubre/Nobyembre para sa alpha launch.
Well, late October na ngayon. Oras na para sa progress update.
Ang Magandang Balita:
- Sa wakas may pangalan na ang platform: STRATUM (Intelligence Over Execution)
- Kumpletong brand guidelines at design system (ang branding pala ay mas matagal pa kaysa sa coding)
- 9 sa 10 agents ay nagawa at integrated
- Gumagana na ang multi-tenant architecture
- Final stage: paghahanda para sa pre-alpha, invitation-only testing
Ang Reality Check:
Nagkasakit ako ng 10 araw pagkatapos mag-leave ng 8 araw (alam ko, ganoon talaga ang buhay.) Nag-pause ang lahat at lumipat ang aking timeline. Ayun na ang October launch, diba?
Pero ito ang bagay tungkol sa solo development: ikaw ang kontrolado ng bilis. Walang presyur na mag-ship kung hindi ka pa handa. Walang investors na humihinga sa leeg mo. Basta... buuin itong tama.
Ang blog post na ito ay tungkol sa isa sa mga "buuin itong tama" na sandali na naging 6-oras na debugging marathon. Dahil pagbalik ko sa bilis pagkatapos magkasakit, may ibang plano pala ang aking deployment platform.
Kapag Nag-Down ang AWS, Nagiging Creative ang mga Engineers (at Minsan Nagsisisi)
Narito ang isang bagay na hindi itinuturo sa mga coding bootcamps: minsan ang iyong deployment platform ay basta na lang... nawawala. Hindi dahil may nagawa kang mali, kundi dahil nagdesisyon ang AWS na magkaroon ng malawakang outage na naaapektuhan ang Vercel deployments globally.
Ganoon nagsimula ang Lunes ko. Down ang production site ko, nagpapakita ng errors ang Vercel, at isa lang ang iniisip ko: "Kailangan ko ng backup. Mabilis."
Pasok ang Cloudflare Pages. Narinig ko ang magagandang bagay tungkol dito. Magandang CDN, automatic deployments, simpleng setup. Ano ang maaaring magkamali?
Narrator: Lahat. Lahat ay maaaring magkamali.
Ang Switch na Mukhang Sobrang Dali
Ang migration sa Cloudflare Pages ay surprisingly smooth. Kinonekta ko ang GitHub repo ko, nag-set ng environment variables sa dashboard, nag-push sa main. Tatlong minuto mamaya: deployed.
"Wow," sabi ko. "Halos sobrang dali nito."
Tapos binuksan ko ang production site.
```
Mixed Content: The page at 'https://my-site.com/...' was loaded over HTTPS,
but requested an insecure resource 'http://stratum-api.us-central1.run.app/...'
```
Yung pakiramdam na ang iyong pagdiriwang ay premature? Oo, ganoon.
Ang Problema: HTTP Calls Mula sa HTTPS Page
Gumagawa ang aking React app ng HTTP requests sa aking backend API habang naka-load ang page mismo sa HTTPS. Tama lang na bina-block ito ng mga browsers bilang security risk. Mixed Content errors. Bawat API call ay nabibigo.
"Pero teka," sabi ko sa sarili ko, "mayroon akong `ensureHttpsInProduction()` sa code ko! Dapat nito i-convert ang HTTP sa HTTPS nang automatic!"
Tiningnan ko ang deployed bundle. Nandoon ang function. Tama ang logic. Nakikita ng browser console ang conversion na nangyayari. Kaya bakit may HTTP requests pa ring nago-go through?
Unang Debugging Attempt: Ang Environment Variable Hunt
Baka hindi na-pick up ang environment variables sa Cloudflare?
```bash
# Checked Cloudflare Dashboard
VITE_API_URL=https://stratum-api.us-central1.run.app ✓
VITE_SUPABASE_URL=https://your-project.supabase.co ✓
```
Lahat HTTPS. Lahat tama.
Nag-trigger ako ng rebuild. Naghintay. Na-deploy. Binuksan ang site.
Parehong error. HTTP requests pa rin.
Pangalawang Attempt: Ang Great Reimport
Baka hindi ginagamit ng mga files ang centralized na `API_BASE_URL`?
Isang oras akong gumugol sa pag-update ng 24 files para mag-import mula sa `@/lib/api` imbes na direktang gumamit ng `import.meta.env.VITE_API_URL`. Lahat ng component na gumagawa ng API calls ay trinato.
```typescript
// Before
const response = await fetch(`${import.meta.env.VITE_API_URL}/api/v1/...`);
// After
import { API_BASE_URL } from '@/lib/api';
const response = await fetch(`${API_BASE_URL}/api/v1/...`);
```
Na-push. Na-deploy. Naghintay.
Sira pa rin.
Sa puntong ito, kinukuwestiyon ko na ang mga life choices ko.
Ang Plot Twist: Mga Nawawalang Files sa Git
Pero teka, lumalala pa.
Habang iniimbestigahan kung bakit hindi gumagana ang HTTPS enforcement ko, may natuklasan akong nakakatakot. Ang `api.ts` file na naglalaman ng `ensureHttpsInProduction()` ay wala sa aking Git repo.
Pati ang `authService.ts`. O ang `csvSanitizer.ts`. Tatlong kritikal na frontend files, basta na lang... nawawala.
Paano? Ang `.gitignore` file ay ganito:
```
# Python stuff
lib/
build/
dist/
```
Mukhang makatwiran para sa Python, diba? Maliban na ang aking mga frontend utilities ay nasa `apps/web/src/lib/`. Ang malawak na `lib/` pattern ay aksidenteng nag-ignore sa aking buong frontend lib directory!
Ibig sabihin nito:
1. Nagbu-build ang Cloudflare mula sa repo (nawawala ang mga files na ito)
2. Ang lokal na development ko ay mayroon ng mga files na ito (gumagana nang maayos locally)
3. WALANG ALAM akong hindi sila nasusubaybayan
Ang fix:
```diff
# .gitignore - Before
-lib/
# .gitignore - After
+apps/api/lib/ # Python-specific
+!apps/web/src/lib/ # Explicitly include frontend lib
```
Na-add ang nawawalang mga files, nag-commit, nag-push. Ngayon mayroon na ang Cloudflare ng HTTPS enforcement code!
Maliban na... nagpatuloy ang mga HTTP errors.
Pangatlong Attempt: Build-Time Validation
Sa puntong ito, kinukuwestiyon ko ang lahat. "Alam mo ano?" sabi ko. "Kung patuloy itong nangyayari, kailangan kong PIGILAN ito bago maabot ang production."
Sumulat ako ng Vite plugin na nagfe-fail sa build kung may madetect na HTTP URLs sa production:
```typescript
function validateProductionUrls(mode: string) {
if (mode !== 'production') return;
const apiUrl = process.env.VITE_API_URL || '';
if (apiUrl && apiUrl.trim().startsWith('http://')) {
if (!apiUrl.includes('localhost') && !apiUrl.includes('127.0.0.1')) {
throw new Error(
`❌ HTTPS ENFORCEMENT FAILED
Environment Variable: VITE_API_URL
Current Value: ${apiUrl}
This will cause Mixed Content errors in production!`
);
}
}
}
```
Genius, diba? Ngayon IMPOSIBLE nang mag-deploy na may HTTP URLs.
Na-deploy ulit. Pumasa ang build (HTTPS ang environment variables). Nag-load ang site.
Parehong. Error.
Ang Lightbulb Moment: Mga Lokal na Files ang Naide-Deploy
Gabing-gabi na, nagkaroon ako ng realization.
Tiningnan ko ulit ang deployed JavaScript bundle. Talagang tiningnan ko nang mabuti ngayong pagkakataon. Ang URL sa loob ay:
```javascript
"http://stratum-api.us-central1.run.app"
```
Pero HTTPS ang Cloudflare environment variables ko. Kaya saan nanggagaling ang HTTP URL na ito?
Tapos tumama sa akin. Ang lokal na `.env.production` file ko.
```bash
# apps/web/.env.production (LOCAL FILE)
VITE_API_URL=http://stratum-api.us-central1.run.app
```
Dine-deploy ng Cloudflare Pages ang aking lokal na environment file sa halip na gamitin ang dashboard variables!
Tiningnan ko ang `.cloudflare-pages-ignore`:
```
# Environment files
.env
.env.local
.env.development
.env.test
# .env.production ← NAWAWALA!
```
Face. Palm.
Ang Fix: Isang Linya
```diff
# apps/web/.cloudflare-pages-ignore
.env
.env.local
.env.development
.env.test
+.env.production
```
Na-deploy. Naghintay.
Iba ang error ngayong pagkakataon! Progress!
```
Access to fetch at 'https://stratum-api.us-central1.run.app/...'
from origin 'https://preview-xyz.stratum-marketing-suite.pages.dev'
has been blocked by CORS policy
```
CORS errors! Maganda, magandang CORS errors! Ibig sabihin gumagana na ang HTTPS!
Pero Sandali, May Dagdag Pa: Ang Cache Conspiracy
Na-fix ang CORS. Na-deploy ulit. Binuksan ang custom domain ko.
HTTP errors ulit.
Ano?!
Lumabas na agresibong kine-cache ng Cloudflare CDN ang lumang bundle. Ang bagong deployment (na may HTTPS) ay live na sa preview URL, pero ang custom domain ko ay nagse-serve ng naka-cache na content na may HTTP URLs.
Ang cache purging ng Cloudflare ay nangangailangan ng:
1. Paghahanap ng tamang zone settings (wala sa Pages dashboard)
2. Pag-navigate sa domain settings (hindi obvious)
3. Manual na pag-purge ng cache (para sa bawat deployment)
Pagkatapos ng ilang oras na pag-debug ng HTTP/HTTPS issues, gumawa ako ng desisyon.
Ang Pagbabalik sa Vercel: Minsan Mas Maganda ang Boring
Balik na ang AWS. Gumagana na ulit ang Vercel.
Inilipat ko ang lahat pabalik sa Vercel. Bakit?
1. Automatic cache invalidation - Walang manual na pag-purge
2. Mas simpleng environment variable handling - Ang ini-set mo ang nakukuha mo
3. Mas mabilis na debugging - Mas kaunting infrastructure ang kailangang pag-isipan
4. Battle-tested - Kilala ko ang mga quirks nito
Ang Vercel deployment ay tumagal ng 3 minuto. Walang HTTP errors. Walang cache issues. Basta... gumana.
Ang Natutunan Ko (Sa Mahirap na Paraan)
1. Laging I-Ignore ang .env.production sa mga Deployment Platforms
```
# .vercelignore
# .cloudflare-pages-ignore
# .netlify-ignore
.env
.env.local
.env.development
.env.test
.env.production ← HUWAG KALIMUTAN ITO
```
2. Mapanganib ang Malawak na .gitignore Patterns sa mga Monorepos
```diff
# ❌ Masama - Nag-ignore ng frontend AT backend lib folders
-lib/
-build/
-dist/
# ✅ Maganda - Specific sa bawat context
+apps/api/lib/ # Python-specific
+apps/api/build/
+apps/api/dist/
+apps/web/dist/ # Vite output only
```
Laging itanong: "Maaari bang aksidenteng mag-ignore ang pattern na ito ng isang bagay na mahalaga?"
Sa isang monorepo na may maraming wika (Python + TypeScript), ang malawak na patterns na para sa isang ecosystem ay maaaring aksidenteng mag-ignore ng mga kritikal na files sa isa pa.
3. Sulit Pa Rin ang Build-Time Validation
Kahit hindi nito na-catch ang lokal na file issue, pinipigilan ng build-time validation ang hinaharap na mga misconfiguration:
```typescript
// vite.config.ts
export default defineConfig(({ mode }) => {
validateProductionUrls(mode);
return {
// ... config
};
});
```
4. Gumagana ang Multi-Layer Defense
Ang aming final architecture ay may TATLONG layer:
- Build-time: Nagfe-fail sa build kung may nadetect na HTTP URLs
- Runtime: Kino-convert ang HTTP → HTTPS kung naka-load ang page sa HTTPS
- Deployment: Hindi kasama ang lokal na .env files
5. Kaibigan Mo ang Preview URLs
Laging mag-test sa preview URL muna. Kung gumagana iyon pero hindi ang custom domain mo, karaniwang caching ang problema.
6. Alamin ang mga Quirks ng Iyong Platform
- Vercel: Simple, auto-invalidates ang cache, "just work" ang environment variables
- Cloudflare Pages: Magandang CDN, pero manual ang cache purging at mas complex ang setup
Ang Code na Nagligtas sa Akin
Narito ang final na `ensureHttpsInProduction()` function:
```typescript
function ensureHttpsInProduction(url: string): string {
// Only convert in browser context when site is loaded over HTTPS
if (typeof window !== 'undefined' && window.location.protocol === 'https:') {
// Don't convert localhost/127.0.0.1 URLs (local development)
if (url.startsWith('http://') &&
!url.includes('localhost') &&
!url.includes('127.0.0.1')) {
console.warn('[API] Converting HTTP to HTTPS:', url);
return url.replace('http://', 'https://');
}
}
return url;
}
```
At ang build-time validation sa `vite.config.ts`:
```typescript
function validateProductionUrls(mode: string) {
if (mode !== 'production') return;
const apiUrl = process.env.VITE_API_URL || '';
// Check for HTTP (should be HTTPS)
if (apiUrl && apiUrl.trim().startsWith('http://')) {
if (!apiUrl.includes('localhost') && !apiUrl.includes('127.0.0.1')) {
throw new Error(`
❌ HTTPS ENFORCEMENT FAILED
Environment Variable: VITE_API_URL
Current Value: ${apiUrl}
Mixed Content Error Prevention:
Browsers block HTTP requests from HTTPS pages.
Fix: Update environment variables to use HTTPS URLs.
`);
}
}
}
```
Ang Tunay na Aral: Detective Work ang Debugging
Hindi ito coding problem. Ito ay configuration archaeology expedition.
Ang mga tunay na bugs ay:
1. Malawak na `.gitignore` patterns na nag-ignore ng kritikal na frontend files
2. Nawawalang `.env.production` sa `.cloudflare-pages-ignore`
3. Agresibong CDN caching na nagtatago sa fix
4. Pag-aakala ng environment variable precedence
Ang teknikal na solusyon ay isang linya sa isang `.ignore` file.
Ang debugging? Tumagal iyon ng 6 oras, 14 deployments, at sobrang daming kape.
Sulit Ba?
Absolutely. Narito ang aking nakuha:
1. Malalim na pag-unawa sa Mixed Content security policies
2. Build-time validation na pumipigil sa mga hinaharap na isyu
3. Multi-layer HTTPS enforcement na platform-agnostic
4. Tunay na pagpapahalaga sa simplicity ng Vercel
At pinakamahalaga: isang mahusay na debugging story na mababahagi. :P
Ikinukwento ng Git Log
```bash
2033b9a fix: add .env.production to .vercelignore
3555390 docs: migrate deployment documentation from Cloudflare Pages to Vercel
a4edb09 chore: force clean Cloudflare Pages rebuild
590c271 fix: enhance ensureHttpsInProduction logging
15d69c6 chore: force rebuild of UserProfile bundle
a1c345f fix: add .env.production to cloudflare-pages-ignore ← THE .ENV FIX
635d80d docs: update documentation for Cloudflare Pages migration
edfa611 feat: add build-time HTTPS enforcement
802c1e9 fix: enforce HTTPS for all API calls across frontend
26f6b87 refactor: comprehensive .gitignore audit and cleanup
3758a9c fix: unignore frontend lib directory and add missing files ← THE GITIGNORE FIX
```
Bawat commit ay kumakatawan sa isang oras ng debugging sa lumang mundo pero sa Claude Code, salamat sa Diyos, mas mabilis ang speed ko. Isang hypothesis na na-test. Isang aral na natutuhan.
Para sa Ibang mga Engineers na Lumalaban sa Mixed Content Errors
Kung binabasa mo ito dahil nagde-debug ka ng parehong isyu, narito ang checklist mo:
1. I-Check ang Iyong Environment Variables:
```bash
# Print actual values being used
console.log('API URL:', import.meta.env.VITE_API_URL);
```
2. I-Check ang Iyong Deployed Bundle:
```bash
# Download and search the JavaScript bundle
curl https://your-site.com/assets/index-ABC123.js | grep "http://"
```
3. I-Check ang Iyong Ignore Files:
```bash
# Make sure .env.production is excluded
cat .vercelignore
cat .cloudflare-pages-ignore
cat .netlify-ignore
```
4. I-Check ang Iyong .gitignore (Monorepos):
```bash
# Make sure critical files aren't being ignored
git ls-files apps/web/src/lib/ # Should show api.ts, etc.
# If empty, check for broad patterns
grep "^lib/" .gitignore # ❌ Too broad
grep "^apps/api/lib/" .gitignore # ✅ Specific
```
5. I-Check ang Iyong Cache:
```bash
# Test on preview URL first
# If preview works but production doesn't = cache issue
```
6. Magdagdag ng Build-Time Validation:
```typescript
// Prevent it from ever happening again
if (mode === 'production' && url.startsWith('http://')) {
throw new Error('HTTPS required in production!');
}
```
Ang Migration Checklist na Sana Mayroon Ako
Kapag nagpapalit ng deployment platforms:
- [ ] I-list ang LAHAT ng environment variables mula sa lumang platform
- [ ] I-setup ang environment variables sa bagong platform MUNA
- [ ] I-add ang LAHAT ng .env files sa .ignore (kasama ang .env.production)
- [ ] I-verify na hindi nag-ignore ng kritikal na files ang .gitignore (patakbuhin ang `git ls-files` para i-check)
- [ ] I-test sa preview URL bago ang custom domain
- [ ] I-check ang deployed bundle para sa mga HTTP URL
- [ ] I-verify ang CORS settings kung hiwalay ang backend
- [ ] I-document ang platform-specific quirks
Nagco-code Pa Rin, Natututo Pa Rin, Nagsisira Pa Rin ng mga Bagay (Minsan)
Anim na oras ng debugging para sa isang one-line fix. Iyan ang software engineering sa madaling salita.
Mahalaga ang code na sine-ship natin, oo. Pero ang debugging skills na dine-develop natin? Iyon ang nagpapagaling sa atin bilang mga engineers.
Sa susunod na mag-down ang deployment platform ko (at magkakaroon ng susunod na pagkakataon), handa na ako. Mayroon akong:
- Platform-agnostic HTTPS enforcement
- Build-time validation
- Mas mahusay na pag-unawa sa environment variable precedence
- Isang backup deployment strategy
At sana, ang blog post na ito ay makakapag-save sa iba ng ilang sa mga 6 oras na iyon. :)
May nagkaroon ka na ba ng "one-line fix" na tumagal nang nakapahiyang matagal bago mo mahanap? Gusto kong marinig ang iyong mga debugging detective stories — gusto ng miserable na may kasama!
Maraming salamat,
Chandler





