Working With CORS
You're building an API. Your frontend screams. The browser blocks it.
"CORS error!"
Relax!
This is not a Trongate problem.
This is browser security - and we’re fixing it, Native PHP style.
What Is CORS?
CORS = Cross-Origin Resource Sharing
Your page at https://example.com tries to fetch from https://api.com/users.
The browser says:
→ “Different domain. Not allowed… unless the server says yes.”
The server must send special headers:
→ “Yes, you’re allowed.”
That’s it. Just headers.
The Nuclear Option (Public APIs)
Add this code to the __construct() method of any API controller:
Done. Your API now works with any frontend.
Warning: * means everyone. Use only for public APIs.
Lock It Down (Production-Ready)
The "Nuclear Option" allows any website to access your API. That's fine for public APIs, but for private applications, you need to restrict access to only your authorized domains.
Here's how to whitelist specific domains - correctly:
Note: The example above assumes that we are allowing a partner website, https://trusted-website.com, to submit HTTP requests to own website at https://example.com.
Same-origin requests are never blocked by CORS.
Therefore, you do not need to whitelist your own domain.
Pro tip: Need CORS on one method only?
Call $this->set_cors_headers(); inside that method instead of __construct().
Preventing Cross-Origin Cache Issues
There’s a small line of code, in the example above, that deserves special attention:
It’s a simple line of pure PHP - but a very powerful one.
Let’s take a moment to clarify what it does, and why it’s so important.
Imagine two browsers:
- One from
https://trusted-website.com→ getsAccess-Control-Allow-Origin: https://trusted-website.com - One from
https://hacker.com→ gets blocked
If your server is behind a cache (Cloudflare, Varnish, etc.), that cache might serve the same stored response to both browsers.
Vary: Origin tells the server: “Don’t serve a cached response that belongs to a different origin - keep separate versions for each one.”
Beginner summary: It prevents cached responses from leaking to the wrong sites.
Preflight Requests (Quick Recap)
Complex requests trigger an OPTIONS “preflight” before the real request.
| Request | Preflight? | Why |
|---|---|---|
GET (simple) | No | Standard headers only |
POST + form-data | No | Simple content type |
POST + application/json | Yes | Custom Content-Type |
PUT, DELETE | Yes | Non-simple method |
Any + Authorization header | Yes | Custom header |
Server must reply to preflight with: 204 + full CORS headers.
Final Thoughts
Other frameworks? Middleware. Config files. Third-party packages.
Trongate? Native PHP.
The difference is clear.