問題內容
每當我嘗試從 Angular 應用程序向 Go 服務器發送 HTTP 請求時,我都會收到以下響應:
對預檢請求的響應未通過訪問控制檢查:請求的資源上不存在“Access-Control-Allow-Origin”標頭。
我添加了錯誤響應中詳細說明的標頭,但錯誤仍然存??在。
服務器.go
package rest import ( "context" "fmt" "net/http" "os" "os/signal" "sync" "syscall" "github.com/gorilla/mux" "github.com/randyVerduguez/randy-verduguez_06122023-BE-challenge/configs" "github.com/randyVerduguez/randy-verduguez_06122023-BE-challenge/http/rest/handlers" "github.com/randyVerduguez/randy-verduguez_06122023-BE-challenge/pkg/db" "github.com/rs/cors" "github.com/sirupsen/logrus" ) type Server struct { logger *logrus.Logger router *mux.Router config configs.Config } func NewServer() (*Server, error) { config, err := configs.NewParsedConfig() if err != nil { return nil, err } database, err := db.Connect(db.ConfigDB{ Host: config.Database.Host, Port: config.Database.Port, User: config.Database.User, Password: config.Database.Password, Name: config.Database.Name, }) if err != nil { return nil, err } log, err := NewLogger() if err != nil { return nil, err } router := mux.NewRouter() handlers.Register(router, log, database) server := Server{ logger: log, config: config, router: router, } return &server, nil } func (s *Server) Run(ctx context.Context) error { cors := cors.New(cors.Options{ AllowedMethods: []string{"GET, POST"}, AllowedOrigins: []string{"http://localhost:4200"}, AllowedHeaders: []string{"Content-Type", "Accept"}, }) server := http.Server{ Addr: fmt.Sprintf(":%d", s.config.ServerPort), Handler: cors.Handler(s.router), } stopServer := make(chan os.Signal, 1) signal.Notify(stopServer, syscall.SIGINT, syscall.SIGTERM) defer signal.Stop(stopServer) serverErrors := make(chan error, 1) var wg sync.WaitGroup wg.Add(1) go func(wg *sync.WaitGroup) { defer wg.Done() s.logger.Printf("REST API listening on %d", s.config.ServerPort) serverErrors <- server.ListenAndServe() }(&wg) select { case err := <-serverErrors: return fmt.Errorf("error: starting REST API server %w", err) case <-stopServer: s.logger.Warn("server recieved STOP signal") err := server.Shutdown(ctx) if err != nil { return fmt.Errorf("graceful shutdown did not complete: %w", err) } wg.Wait() s.logger.Info("server was shutdown gracefully") } return nil } func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { w.Header().Set("Access-Control-Allow-Origin", "http://localhost:4200") w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS") w.Header().Set("Access-Control-Allow-Credentials", "true") w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, Accept, origin, Cache-Control, X-Requested-With") if r.Method == "OPTIONS" { return } s.router.ServeHTTP(w, r) }
登錄后復制
路線.go
package handlers import ( "net/http" "github.com/gorilla/mux" "github.com/jmoiron/sqlx" "github.com/sirupsen/logrus" ) func Register(r *mux.Router, lg *logrus.Logger, db *sqlx.DB) { handler := newHandler(lg, db) r.Use(handler.MiddlewareLogger()) r.HandleFunc("/weather/current", handler.GetCurrentWeather()).Methods(http.MethodPost) r.HandleFunc("/weather/welcome", handler.Test()).Methods(http.MethodGet) }
登錄后復制
正確答案
我注意到的第一個問題是:
AllowedMethods: []string{"GET, POST"},
這應該是:
AllowedMethods: []string{"GET", "POST"},
(或者稍微不易出錯的 []string{http.MethodGet, http.MethodPost}
)
根據文檔,這是默認值(所以你可以省略它) :
我的下一個問題是“起源是什么”; CORS 是“跨源資源共享”,旨在 “防止從一個源運行的客戶端 Web 應用程序獲取從另一源檢索的數據”,因此了解發出請求的頁面的源非常重要。您允許 http://localhost:4200
(AllowedOrigins: []string{"http://localhost:4200"}
) 所以我假設您有兩個服務器在本地主機上運行(但如果這不是案件)。如果您希望允許所有來源,請使用 "*"
;為了進行測試,我將使用 test-cors.org – 只需轉到該網站,輸入 URL,例如“http://127.0.0.1:8080/weather/welcome”,進入“遠程URL”,點擊“發送請求”進行測試。
您的代碼有點令人困惑(例如 (s *Server) ServeHTTP
未使用 – 請旨在提供 最小,可重現的示例,當在這里提問時),所以我稍微簡化了一些事情,希望以下內容能為您指明正確的方向。
package main import ( "context" "fmt" "net/http" "github.com/gorilla/mux" "github.com/rs/cors" ) func main() { s, err := NewServer() if err != nil { panic(err) } s.Run(context.Background()) } type Server struct { router *mux.Router } func NewServer() (*Server, error) { router := mux.NewRouter() Register(router) server := Server{ router: router, } return &server, nil } func (s *Server) Run(ctx context.Context) { cors := cors.New(cors.Options{ AllowedMethods: []string{http.MethodGet, http.MethodPost}, AllowedOrigins: []string{"https://www.php.cn/link/9113c52c5f26af1782e6bf7c56973ef4"}, // AllowedOrigins: []string{"*"}, AllowedHeaders: []string{"Content-Type", "Accept"}, }) server := http.Server{ Addr: fmt.Sprintf(":%d", 8080), Handler: cors.Handler(s.router), } fmt.Println(server.ListenAndServe()) } type handler struct{} func Register(r *mux.Router) { handler := handler{} r.HandleFunc("/", handler.Index).Methods(http.MethodGet) r.HandleFunc("/weather/welcome", handler.Test).Methods(http.MethodGet) } // Index - Provide a simple page with a link to the other page to simplify testing func (h *handler) Index(w http.ResponseWriter, _ *http.Request) { w.Write([]byte(`Test Link`)) } // The real page func (h *handler) Test(w http.ResponseWriter, _ *http.Request) { fmt.Println("Test Called") w.Write([]byte("all OK")) }
登錄后復制