You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular调用第三方API遇CORS错误:缺少Access-Control-Allow-Origin头

解决Angular调用Alternative.me API的CORS错误

问题描述

调用API https://api.alternative.me/fng/?limit=1&format=csv&date_format=us 获取数据时遭遇CORS错误,完整错误信息:

Access to XMLHttpRequest at 'https://api.alternative.me/fng/?limit=1&format=csv&date_format=us' from origin 'http://localhost:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

现有代码

服务类代码

const httpOptions = {
  headers: new HttpHeaders({
  'Content-Type':  'application/json',
  'Access-Control-Allow-Origin': '*' ,
  })
};

@Injectable({
  providedIn: 'root'
})
export class CryptoCoinsService {
 constructor(private http: HttpClient) { }

   fng: string = 'https://api.alternative.me/fng/?limit=1&format=csv&date_format=us';

   getFng(): Observable<any[]> {
    return this.http.get<any[]>(this.fng, httpOptions);
   }
}

组件代码

ngOnInit(){
   this.getFng();
}

getFng() {
  this.cryptoCoinService.getFng()
  .subscribe((data:any) => {
    this.fng = data;
  })
}

同一项目中调用CoinGecko API可正常工作,相关代码:

CoinGecko服务类代码

api: string = 'https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&order=market_cap_desc&per_page=20&page=1&sparkline=false';

getCoinData(): Observable<Coin[]> {
 return this.http.get<Coin[]>(this.api, httpOptions);
}

CoinGecko组件代码

ngOnInit(): void {
   this.getTopCoins();
}

getTopCoins() {
  this.cryptoCoinService.getCoinData()
   .subscribe(data => {
     this.topCoins = data;
   });
}

尝试过以下代理配置,但不确定是否正确:

{
  "/fng":{
     "target": "https://api.alternative.me",
     "secure": false,
     "logLevel": "debug",
     "changeOrigin": true
 }
}

疑问:错误提示缺少Access-Control-Allow-Origin头,但已在请求头设置该字段为*,请问哪里操作错误,该如何解决?


错误原因分析

  1. 请求头设置完全无效:Access-Control-Allow-Origin是服务端返回的响应头,不是客户端请求头,你在请求里添加这个字段对解决CORS问题没有任何帮助。
  2. API跨域策略差异:CoinGecko的API配置了允许跨域的响应头,所以能正常访问;而Alternative.me的这个API未配置相关响应头,导致浏览器拦截请求。
  3. 代理配置未生效:你编写了代理规则,但没有修改API请求路径,代理根本没起作用。

解决步骤

步骤1:修正请求头配置

删掉httpOptions里的Access-Control-Allow-Origin字段,同时注意你请求的是CSV格式,不需要设置Content-Type: application/json:

// 修正后的请求头配置
const httpOptions = {
  headers: new HttpHeaders({
    // CSV请求无需application/json,可留空或设置为text/csv
    // 'Content-Type': 'text/csv'
  })
};

步骤2:正确配置并启用代理

  1. 修改代理配置文件(通常为proxy.conf.json):
{
  "/api/fng": {
    "target": "https://api.alternative.me",
    "secure": true, // 目标为HTTPS,设为true更安全
    "logLevel": "debug",
    "changeOrigin": true,
    "pathRewrite": { "^/api/fng": "/fng" } // 路径重写,将前缀替换为实际API路径
  }
}
  1. 修改服务类中的API路径,使用代理前缀:
// 不再直接调用第三方API,改用代理地址
fng: string = '/api/fng/?limit=1&format=csv&date_format=us';
  1. 指定代理配置启动项目:
    修改package.json的启动命令:
"scripts": {
  "start": "ng serve --proxy-config proxy.conf.json"
}

执行npm start启动项目,代理即可生效。

步骤3:处理CSV格式响应

HttpClient默认会将响应解析为JSON,但你请求的是CSV,需要指定响应类型为文本,之后手动解析:

// 服务类中修改get请求的响应类型
getFng(): Observable<string> {
  return this.http.get(this.fng, { ...httpOptions, responseType: 'text' });
}

组件中订阅并解析CSV:

getFng() {
  this.cryptoCoinService.getFng()
  .subscribe((data:string) => {
    // 简单解析CSV字符串
    const rows = data.split('\n').filter(row => row);
    const headers = rows[0].split(',').map(h => h.trim());
    this.fng = rows.slice(1).map(row => {
      const values = row.split(',').map(v => v.trim());
      return headers.reduce((obj, header, index) => {
        obj[header] = values[index];
        return obj;
      }, {} as any);
    });
  })
}

内容的提问来源于stack exchange,提问作者Marrs

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 06:05:22