- Knowledge
- technology
- OOP
- Tips
- Programming
- Tips
- Tutorial
- SEO
- Ranking
- Knowledge
- Special Day
- Seo
- Bug
- Data science
- Seo
- artificial intelligence
- Machine Learning
- Robotics
- happyNewYear2021
- newYearEve
- 2021
- Automation
- Smart Home
- Career
- Best Practices
- Git
- Logging
- Web Fundamentals
- DNS
- HTTPS
- Performance
- AI Tools
- ChatGPT
- Claude
- Gemini
- Laravel
- Eloquent
- MySQL
- HTTPS
- TLS
- Web Security
- Certificates
- Developer Life
- Debugging
- Docker
- DevOps
- Transactions
- Queues
- LLMs
- AI
- AI Coding
- Developer Tools
- React Native
- Expo
- Kate PMS
- Mobile Apps
- Laravel
- Authentication
- Sanctum
- Cookies
- API Design
- Payments
- Idempotency
- DeepSeek
- Open Source AI
- LLMs
- AI News
- Git
- Version Control
- AI Coding
- Prompting
- PHP
- Checklist
- MCP
- AI Agents
- OpenAI
- Architecture
- Microservices
- Modular Monolith
- Estimation
- Developer Life
- Project Planning
- Humour
- OAuth
- OpenID Connect
- Authentication
- Embeddings
- Vector Search
- RAG
- pgvector
- OpenAI
- GPT-4.1
- Codex CLI
- Events
- Testing
- Clean Code
- Maintainability
- Code Review
- Webhooks
- API
- Security
- Claude Code
- Workflow
- AI
- LLM
- Prompt Injection
- Mobile
- React
- Networking
- TCP
- UDP
- HTTP/3
- CLAUDE.md
- AWS
- Cloud Security
- Backups
- PHPUnit
- Software Engineering
- Leadership
- Communication
- RAG
- Embeddings
- AI Engineering
- IT Infrastructure
- Networking
- Access Control
- CI/CD
- GitHub Actions
- Gemini CLI
- Claude Code
- JavaScript
- Async/Await
- Node.js
- Promises
- Security
- Cryptography
- Passwords
- MySQL
- Database
- Vibe Coding
- Software Quality
- DNS
- Code Reading
- Onboarding
- Productivity
- Background Jobs
- Developer Humour
- Estimates
- Dev Life
- JWT
- o3-mini
- DeepSeek R1
- Rate Limiting
- Kate PMS
- E-Signing
- Audit Trail
- REST
- GraphQL
- API Design
- Laravel 12
- Upgrade Guide
- Open Source
- Self-Hosting
- Task Scheduling
- Cron
- Secrets
- CORS
- PHP
- PHP-FPM
- OPcache
- GitHub Copilot
- Software Architecture
- Engineering
- TypeScript
- JavaScript
- Type Safety
- AI Security
- React Native
- Product Design
- AI Agents
- Kiro
- Queues
- Redis
- RabbitMQ
- AWS SQS
- Nginx
- Apache
- GPT-5
- gpt-oss
- Clean Code
- Architecture
- Naming
- Documentation
- Career
- ADR
- Teamwork
- Supply Chain
- Kate HRM
- HR Software
- Permissions
- System Design
- Pagination
- SSH
- Linux
- Big O
- Databases
- Laravel Boost
- MCP
- Developer Skills
- Validation
- Databases
- Indexes
- Code Quality
- Deployment
- Developer Humour
- Feature Flags
- Code Review
- Pull Requests
- Docker
- Cursor
- Authorization
- RBAC
- Gemini
- Long Context
- PHP 8.4
- Caching
- Dependency Injection
- Web Performance
- Browser
- CSS
- Database
- Migrations
- ChatGPT
- AI for Developers
- Monitoring
- On-Call
- REST
- Backend
- SQL
- NoSQL
- Database Design
- Coding Agents
- Claude 4
- API Resources
- REST API
- Load Balancing
- Scaling
- AWS
- AI Tools
- Claude
- Sora 2
- CTE
- 2FA
- TOTP
- Programming Languages
- Prompts
- Developer Workflow
- API Gateway
- APIs
- Passport
- API Auth
- Learning
- Burnout
- Developer Growth
- Web Development
- SEO
- Kate Mall
- ChatGPT Atlas
- Agent Skills
- Middleware
- Laravel 12
- Collections
- Context Window
- Monitoring
- Commit Messages
- Self Review
- Growth
- Regex
- Programming Basics
- Text Processing
- Database Design
- Normalization
- Linux
- Server Security
- Linux Foundation
- Open Standards
- Legacy Code
- Documentation
- AI Workflow
- File Uploads
- Test Data
- Hashing
- Performance
- Caching
- Enums
- Scope Creep
- Estimation
- Codex
- Gemini CLI
- Timezones
- Carbon
- Bugs
- PHP 8.5
- Gemini 3
- GPT-5.1
- Data Integrity
- Event Loop
- Async
- Opus 4.5
- AI Models
- React
- Forms
- Frontend
- Backups
- AI Images
- DALL-E
- Midjourney
- Race Conditions
- Concurrency
- Legacy Code
- Refactoring
- Senior Engineer
- Scope
- LLM
- CDN
- Web
- Sub-Agents
- Soft Deletes
- Audit Log
- Concurrency
- AI Learning
- NestJS
- AI Evals
- Policies
- SPF DKIM DMARC
- Unicode
- UTF-8
- Knowledge Graph
- Value Objects
- Technical Debt
- Feature Flags
- Laravel Pennant
- Deployment
- Copilot
- Composer
- Dependencies
- Artisan
- Automation
- AWS S3
- Object Storage
- Cloud
- Small Language Models
- Ollama
- Production
- Sessions
- HTTP
- Mentoring
- SQL
- Virtual Machines
- Web Development
- HTTP/2
- QUIC
- Web Performance
- AI Integration
- LLM API
- SOLID
- OOP
- Hosting
- Serverless
- Merge Conflicts
- Temperature
- AI Development
- Reverse Proxy
- Nginx
- Infrastructure
- Verification
- Passkeys
- WebAuthn
- Teams
- Communication
- Stakeholders
- Monorepo
- CI/CD
- Versioning
- JSON Schema
- Livewire
- Inertia
- Meetings
- Distributed Systems
- Privacy
- Full-Stack
- T-Shaped Skills
- Money
- Notifications
- Web Security
- HTTP Headers
- CSP
- Function Calling
- Load Testing
- k6
- Data Extraction
- Debugging
- WebSockets
- SSE
- Real-Time
- Laravel Reverb
- Infrastructure as Code
- Terraform
- Side Projects
- Laravel Pint
- OpenAPI
- Swagger
- UX
- Multimodal
- Jest
- Pair Programming
- APIs
- Rate Limiting
- Resilience
- Dev Humour
- Design Tokens
- JWT
- API Keys
- Sessions
- PHPStan
- Rector
- Incidents
- Reporting
- Dashboards
- Zero Trust
- IAM
- Search
- Laravel Scout
- Junior Developers
- Mentoring
- Images
- WebP
- AVIF
- Bug Reports
- Let's Encrypt
- Design Docs
- Software Design
- Observers
- Replication
- Accountability
- Data Structures
- Reliability
- LLM Memory
- Error Handling
- Payments
- Payment Gateway
- Webhooks
- PCI DSS
- Observability
- OpenTelemetry
- Personal Brand
- Writing
- Conventions
- Dates
- Scheduling
- Disaster Recovery
- Compression
- Brotli
- Deadlines
- Developer Habits
- State Machines
- Tech Roles
- UUID
- ULID
- Horizon
- Planning
- Engineering Culture
- Ownership
- Soft Skills
- Socialite
- Cost Control
- Collations
- Unicode
- Octane
- PostgreSQL
Me vs CORS: A Love Story in Five Bad Ideas and One Good One
About Post
Every developer has a relationship with CORS. It starts the same way for all of us.
You build a lovely frontend on localhost:5173. You build a lovely API on localhost:8000. You introduce them. You open the console, and there it is, in red:
Access to fetch at 'http://localhost:8000/api/me' from origin 'http://localhost:5173' has been blocked by CORS policy.
Postman says the API works. curl says the API works. Only the browser has a problem. And so begins a love story in five bad ideas and one good one.
Stage one: denial
❌ "It works in Postman, so the browser is wrong."
Postman isn't a browser. CORS is a rule that browsers enforce to protect their users: a page from one origin can't read responses from another origin unless that other origin says it's allowed. Postman and curl don't run untrusted pages from random websites, so they don't care. The browser is doing its job. Annoyingly well.
Stage two: the wildcard
❌ "Fine. Allow everything."
header('Access-Control-Allow-Origin: *');
For a while, it works. Then you add login with cookies, and the browser refuses again. The wildcard isn't allowed when the request includes credentials. The spec does this on purpose: "any website may read this user's logged-in responses" is exactly the thing CORS exists to prevent.
Stage three: the clever reflection
❌ "I'll just echo back whatever Origin the request sends."
Now credentials work, and you've built the wildcard again, except worse: every website on the internet is now allowed to make logged-in requests to your API and read the answers. It's the CORS equivalent of losing your house key and fixing it by removing the door.
Stage four: the browser flag
❌ "I'll launch Chrome with web security disabled."
Congratulations, it works on your machine. On exactly one machine. Your users won't be launching their browser with a scary flag, and you'll now be browsing the rest of the internet with a key safety feature turned off. Close that window.
Stage five: bargaining with no-cors
❌ "The error message literally suggests mode: 'no-cors'."
It does. And the request goes through! You just can't read the response. It comes back "opaque": no body, no status you can use. You've traded a red error for a silent nothing, which is arguably worse.
Plot twist: it wasn't CORS at all
Here's the moment that saves hours. Open the Network tab and look at the actual response. Very often, the request failed with a 500, a 404 or a redirect to a login page, and that error response came back without CORS headers. The browser then reports the missing headers, not the real problem.
So the console says "CORS". The truth is "your controller threw an exception". Check the status code and your server logs before touching any CORS setting.
The real fix: say exactly who you trust
✅ Allow your own frontend's origin, by name. In Laravel 11 and 12, CORS handling is built in, but config/cors.php isn't published by default. Publish it with php artisan config:publish cors, then:
return [
'paths' => ['api/*', 'sanctum/csrf-cookie'],
'allowed_methods' => ['*'],
'allowed_origins' => [env('FRONTEND_URL', 'http://localhost:5173')],
'allowed_headers' => ['*'],
'supports_credentials' => true, // only if you use cookies
'max_age' => 0,
];
✅ Keep the origin exact. Scheme, host and port all count. https://app.example.com and https://www.app.example.com are different origins, and a trailing slash in the config won't match.
✅ Understand the preflight. For requests with JSON bodies, custom headers like Authorization, or methods like PUT and DELETE, the browser first sends an OPTIONS request to ask permission. If something (a route, a proxy, an auth middleware) rejects that OPTIONS call, the real request never happens.
✅ Or avoid cross-origin entirely. Serve the API and the frontend from the same origin, or proxy /api through your dev server. No cross-origin request, no CORS.
Remember: CORS doesn't protect your server, it protects your users' browsers. Your API still needs authentication. CORS just decides which websites are allowed to read the answers.
Happily ever after
Once it clicks, CORS stops being an enemy. It's a bouncer with a guest list, and the fix is always the same: put the right name on the list, and make sure the door (the preflight) isn't locked.
Which stage did you stay in the longest? I'll admit I spent more time in stage two than I'd like.

Be first to comment it...