Frontend CORS Solutions
During frontend development, Cross-Origin Resource Sharing (CORS) is a common issue. This document introduces various solutions for solving CORS problems in projects created with Lovrabet CLI.
What is the CORS Problem?
CORS refers to browsers restricting web pages from requesting resources from another domain for security reasons. When the protocol, domain, or port is different, CORS issues arise.
Important Note: Even if they are both subdomains of *.lovrabet.com, dev.lovrabet.com and api.lovrabet.com are still different domains and constitute cross-origin requests. It's just that through configuring CORS whitelist, such cross-origin access is allowed.
CORS Determination Criteria
Browsers determine whether a request is cross-origin by checking if the following three elements are exactly the same:
- Protocol:
httpvshttps - Domain:
dev.lovrabet.comvsapi.lovrabet.com - Port:
80vs443vs3000
CORS Examples
| Frontend URL | API URL | Cross-Origin? | Explanation |
|---|---|---|---|
http://localhost:3000 | https://api.lovrabet.com | Yes | Protocol, domain, and port are all different |
https://dev.lovrabet.com | https://api.lovrabet.com | Yes | Different domain (although both are lovrabet.com subdomains) |
https://dev.lovrabet.com | https://dev.lovrabet.com | Same Origin | Exactly the same domain |
http://example.com:80 | http://example.com:443 | Yes | Different ports |
https://example.com | http://example.com | Yes | Different protocols |
Note: dev.lovrabet.com → api.lovrabet.com are both subdomains of lovrabet.com, but this is still cross-origin. It's just that through server-side CORS whitelist configuration, such cross-origin access is allowed, so no CORS error occurs.
Solutions Overview
Lovrabet CLI provides multiple solutions for CORS issues, you can choose based on your scenario:
| Solution | Applicable Scenario | Pros | Cons |
|---|---|---|---|
| Solution 1: Use dev.lovrabet.com | Development phase | Auto-configured, no extra setup | Development only |
| Solution 2: Server CORS Config | Need to access own API | Simple and direct | Requires server access |
| Solution 3: Server Proxy | Complex business scenarios | Flexible, can add business logic | Requires extra development |
| Solution 4: Independent Deployment | Production environment | Fully autonomous, no CORS issues | Requires deployment resources |
Solution 1: Use dev.lovrabet.com Development Domain (Recommended)
How It Works
When starting the project with lovrabet start, CLI automatically maps your local project to the dev.lovrabet.com development domain.
Important: Although dev.lovrabet.com and api.lovrabet.com are both subdomains of lovrabet.com, they are still different domains and constitute cross-origin requests. However, dev.lovrabet.com has been added to the Lovrabet platform's CORS whitelist, and the server allows cross-origin requests from dev.lovrabet.com, so no CORS error occurs.
Usage
# Start development server
lovrabet start
# Access URL will be automatically mapped to
# https://dev.lovrabet.com/your-app-path
Advantages
- ✅ Zero Configuration: No extra setup needed, works out of the box
- ✅ Auto Mapping: CLI automatically handles domain mapping and HTTPS
- ✅ Whitelist Configured:
dev.lovrabet.comis already in CORS whitelist - ✅ Developer Friendly: Supports hot reload, smooth development experience
Notes
- This solution is only for development environment
- Need to log in to Lovrabet platform to use
dev.lovrabet.comdomain - If accessing non-
*.lovrabet.comAPIs, CORS issues may still occur
Solution 2: Server CORS Configuration
Applicable Scenario
When your frontend application runs on dev.lovrabet.com but needs to access your own server's API, you may encounter CORS issues. You can configure CORS on your server to allow dev.lovrabet.com access.
Configuration Examples
Node.js (Express)
const express = require('express');
const app = express();
// Allow dev.lovrabet.com cross-origin access
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', 'https://dev.lovrabet.com');
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
res.header('Access-Control-Allow-Credentials', 'true');
if (req.method === 'OPTIONS') {
return res.sendStatus(200);
}
next();
});
Nginx
server {
listen 80;
server_name your-api-domain.com;
location / {
# Allow dev.lovrabet.com cross-origin access
add_header 'Access-Control-Allow-Origin' 'https://dev.lovrabet.com';
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization';
add_header 'Access-Control-Allow-Credentials' 'true';
if ($request_method = 'OPTIONS') {
return 204;
}
# Your API handling logic
proxy_pass http://backend;
}
}
Spring Boot (Java)
@Configuration
public class CorsConfig {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("https://dev.lovrabet.com")
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("*")
.allowCredentials(true);
}
};
}
}
Advantages
- ✅ Simple and Direct: Only need to configure once on server side
- ✅ Good Performance: Browser directly accesses API, no middleware
- ✅ Flexible: Can precisely control allowed domains and methods
Notes
- Requires server administrator access
- For production, recommend using environment variables to configure allowed domains
- For security, don't use wildcard
*to allow all domains
Solution 3: Server Proxy (API Relay)
Applicable Scenario
When you cannot modify server CORS configuration, or need to add business logic, authentication, or data transformation in requests, use the server proxy solution.
How It Works
Frontend doesn't call target API directly, but calls its own server endpoint, which forwards requests to the target API. This allows:
- Bypassing browser CORS restrictions
- Adding business logic on server side
- Hiding API implementation details
- Unified error handling and logging
Implementation Examples
Refer to Scenario 3: API Proxy in the Next.js Demo Project.
Next.js API Route Example
// app/api/proxy/data/route.ts
import { NextRequest, NextResponse } from "next/server";
import { createServerClient } from "@/lib/sdk-client";
export async function GET(request: NextRequest) {
try {
const searchParams = request.nextUrl.searchParams;
const page = searchParams.get("page") || "1";
const size = searchParams.get("size") || "10";
// Create client on server side (no CORS issues)
const client = createServerClient();
const model = client.getModel(0);
// Call SDK to get data
const response = await model.filter({
page: parseInt(page),
pageSize: parseInt(size),
});
// Return data to frontend
return NextResponse.json({
success: true,
data: response,
});
} catch (error) {
return NextResponse.json(
{
success: false,
error: error instanceof Error ? error.message : "Unknown error",
},
{ status: 500 }
);
}
}
Frontend Call
// Frontend gets data through its own API route
const fetchData = async () => {
const response = await fetch('/api/proxy/data?page=1&size=10');
const result = await response.json();
if (result.success) {
// Use data
console.log(result.data);
}
};
Express.js Example
const express = require('express');
const axios = require('axios');
const app = express();
app.use(express.json());
// Proxy API requests
app.get('/api/proxy/data', async (req, res) => {
try {
const { page, size } = req.query;
// Call target API on server side (no CORS restrictions)
const response = await axios.get('https://api.target.com/data', {
params: { page, size },
headers: {
'Authorization': `Bearer ${process.env.API_TOKEN}`,
},
});
// Can add business logic, data transformation here
const transformedData = transformData(response.data);
res.json({
success: true,
data: transformedData,
});
} catch (error) {
res.status(500).json({
success: false,
error: error.message,
});
}
});
function transformData(data) {
// Data transformation logic
return data;
}
Advantages
- ✅ Completely Bypasses CORS: No CORS restrictions on server side
- ✅ Flexible and Controllable: Can add business logic, authentication
- ✅ Hides Implementation: Frontend doesn't need to know target API details
- ✅ Unified Handling: Can unify error handling, logging, caching, etc.
Notes
- Requires additional server resources
- Adds to request chain, may have slight latency
- Need to handle server-side errors and timeouts
Complete Example
See the complete implementation: openapi-nextjs-demo project's scenario3-proxy scenario.
Solution 4: Independent Deployment to Your Own Server
Applicable Scenario
After development is complete, deploy the project independently to your own server using your own domain. This eliminates CORS issues because both frontend and API are under your control.
Deployment Steps
1. Build Production Version
# Build project
lovrabet build
# Build output is in dist/ directory
2. Deploy to Server
Deploy the contents of dist/ directory to your web server (Nginx, Apache, CDN, etc.).
3. Configure Domain and HTTPS
# Nginx configuration example
server {
listen 80;
server_name your-domain.com;
# Redirect to HTTPS
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl;
server_name your-domain.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
root /path/to/dist;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
}
4. Configure API Address
Set production environment API address in project configuration:
// .env.production
VITE_API_BASE_URL=https://api.your-domain.com
Advantages
- ✅ Fully Autonomous: Complete control over frontend and API
- ✅ No CORS Issues: Same domain or CORS already configured
- ✅ Best Performance: Direct access, no middleware
- ✅ Production Ready: Suitable for production environment
Notes
- Requires server resources and domain
- Need to configure HTTPS certificate
- Need to handle routing and static resources
- Recommend using CDN to accelerate static resources
Solution Selection Recommendations
Choose the appropriate solution based on your scenario:
| Phase | Recommended Solution | Description |
|---|---|---|
| Local Development | Solution 1: dev.lovrabet.com | Zero config, works out of box |
| Need Own API Access | Solution 2: Server CORS | Simple and direct, good performance |
| Complex Business Scenarios | Solution 3: Server Proxy | Flexible and controllable, powerful |
| Production Environment | Solution 4: Independent Deployment | Fully autonomous, best performance |
FAQ
Q: Why doesn't using dev.lovrabet.com cause CORS issues?
A: Actually dev.lovrabet.com and api.lovrabet.com are still cross-origin (because domains are different). But dev.lovrabet.com has been added to the Lovrabet platform's CORS whitelist, and the server is configured to allow cross-origin requests from dev.lovrabet.com, so browsers don't block these requests, making it appear as if there's no CORS issue.
Q: Can I develop on local localhost?
A: Yes, but localhost is not in the CORS whitelist, accessing *.lovrabet.com APIs will have CORS issues. Recommend using dev.lovrabet.com for development.
Q: Must I deploy independently for production?
A: Not necessarily. If your frontend and API are under the same domain, or CORS is already configured, you can deploy directly. But independent deployment is usually more flexible and secure.
Q: Will server proxy affect performance?
A: There will be slight impact because it adds to the request chain. But for most applications, this impact is negligible. If you have very high performance requirements, recommend using Solution 2 or Solution 4.