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

Angular请求Go后端遇CORS预检403错误,求解决方案

问题描述

使用Angular前端向Go后端发送HTTP请求时,尽管已配置跨域相关头,仍收到以下错误:

Access to XMLHttpRequest at 'http://localhost:3000/rcVolume' 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.

相关代码配置如下:

Go 主函数

func main() {
    store, err := NewPostgresStore()
    if err != nil {
        log.Fatal(err)
    }

    if err := store.Init(); err != nil {
        log.Fatal(err)
    }

    server := NewAPIServer(":3000", store)
    server.Run()
}

Go 服务器配置

func (s *APIServer) Run() {
    router := mux.NewRouter()

    router.HandleFunc("/rcVolume", makeHTTPHandleFunc(s.handleRcVolume))

    log.Println("JSON API Server running on port: ", s.listenAddr)

    headers := handlers.AllowedHeaders([]string{"X-Requested-With", "Content-Type", "Authorization"})
    origins := handlers.AllowedOrigins([]string{"*"})
    methods := handlers.AllowedMethods([]string{"GET", "POST", "PUT", "DELETE", "OPTIONS"})

    http.ListenAndServe(s.listenAddr, handlers.CORS(headers, origins, methods)(router))
}

Go 请求处理方法

func (s *APIServer) handleRcVolume(w http.ResponseWriter, r *http.Request) error {
    if r.Method == "GET" {
        return s.handleGetRcVolumes(w, r)
    }
    if r.Method == "POST" {
        return s.handleCreateRcVolume(w, r)
    }

    return fmt.Errorf("method not allowed %s", r.Method)
}

func (s *APIServer) handleGetRcVolumes(w http.ResponseWriter, r *http.Request) error {
    rcVolumes, err := s.store.GetRcVolumes()
    if err != nil {
        return err
    }
    
    return writeJSON(w, http.StatusOK, rcVolumes)
}

func writeJSON(w http.ResponseWriter, status int, v any) error {
    w.Header().Set("Content-Type", "application/json")
    w.Header().Set("Access-Control-Allow-Origin", "*")
    w.Header().Set("Access-Control-Allow-Methods", "DELETE, POST, GET, OPTIONS")
    w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Requested-With")
    w.WriteHeader(status)

    return json.NewEncoder(w).Encode(v)
}

Angular 相关代码

请求头配置

export const httpOptions = {
  headers: new HttpHeaders({
    'Content-Type':  'application/json',
    'Access-Control-Allow-Origin': '*',
    'Access-Control-Allow-Methods': 'DELETE, POST, GET, OPTIONS',
    'Access-Control-Allow-Headers': 'Content-Type, Authorization, X-Requested-With'
  })
};

API服务

@Injectable({
    providedIn: 'root'
})
export class RcVolumesServiceApi {
  private url = 'http://localhost:3000'

  constructor(private httpClient: HttpClient) { }

  getRcVolumes() {
    return this.httpClient.get<any[]>('http://localhost:3000/rcVolume', httpOptions)
  }
}

解决方案

1. 清理Angular请求中的无效头

Access-Control-Allow-Origin、Access-Control-Allow-Methods、Access-Control-Allow-Headers是服务器响应头,前端无需在请求中携带;且GET请求不需要设置Content-Type: application/json(该设置会触发非简单请求的预检流程)。修改后的请求配置:

// 移除多余的CORS响应头,GET请求无需Content-Type
export const httpOptions = {
  headers: new HttpHeaders({})
};

// 或者直接不传httpOptions给GET请求
getRcVolumes() {
  return this.httpClient.get<any[]>('http://localhost:3000/rcVolume')
}

2. 确保Go后端错误响应也携带CORS头

当前代码中,当请求方法不是GET/POST时,会返回method not allowed错误,若makeHTTPHandleFunc未通过writeJSON处理错误,会导致错误响应缺少CORS头。修改错误处理逻辑:

// 确保错误响应通过writeJSON返回,自动携带CORS头
type apiFunc func(http.ResponseWriter, *http.Request) error

func makeHTTPHandleFunc(f apiFunc) http.HandlerFunc {
  return func(w http.ResponseWriter, r *http.Request) {
    if err := f(w, r); err != nil {
      writeJSON(w, http.StatusMethodNotAllowed, map[string]string{"error": err.Error()})
    }
  }
}

3. 移除writeJSON中的重复CORS配置

gorilla/handlers的CORS中间件已自动设置跨域头,无需在writeJSON中重复添加,避免配置冲突:

func writeJSON(w http.ResponseWriter, status int, v any) error {
    w.Header().Set("Content-Type", "application/json")
    w.WriteHeader(status)

    return json.NewEncoder(w).Encode(v)
}

4. 验证预检请求

用curl测试OPTIONS预检请求,确认响应包含正确的CORS头:

curl -X OPTIONS http://localhost:3000/rcVolume -H "Origin: http://localhost:4200" -H "Access-Control-Request-Method: GET"

正常响应应包含Access-Control-Allow-Origin: *、Access-Control-Allow-Methods等头。

内容的提问来源于stack exchange,提问作者Ticu Alexandru-Marian

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 11:35:24