問題內容
每當我嘗試從 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"))
}
登錄后復制






