有什么方法可以摆脱 Google Cloud Functions 中的 CORS 吗?

问题描述 投票:0回答:1

我最近部署的云函数面临 CORS 错误,即使我在代码中包含了

Access-Control-Allow-Origin: *

package controllers

import (
    "encoding/json"
    "fmt"
    "net/http"

    "cloud.google.com/go/firestore"
    "cloud.google.com/go/logging"
    "github.com/Task3/models"
    "github.com/Task3/validations"
)

func CreateEmployee(w http.ResponseWriter, r *http.Request) {

    mu.Lock()
    defer mu.Unlock()

    var employee models.Employee
    err := json.NewDecoder(r.Body).Decode(&employee)

    if err != nil {
        w.Header().Set("Content-Type", "text/plain")
        http.Error(w, "Invalid JSON", http.StatusBadRequest)

        logger.Log(logging.Entry{
            Payload:  "Invalid JSON input for type Employee during controllers.CreateEmployee function call.",
            Severity: logging.Error,
        })
        w.Header().Set("Content-Type", "application/json")
        return
    }

    err1 := validations.V.Struct(employee)

    if err1 != nil {
        w.Header().Set("Content-Type", "text/plain")
        http.Error(w, "Invalid input for employee deatails\n-First name must contain alphabets or spaces only.\n-First name must contain alphabets or spaces only.\n-Email id must be valid eg. [email protected].\n-Password must be atleast 6 charecters long.\n-Phone no. should be valid.\n-Role must be either of - 'admin', 'developer', 'manager', 'tester'. (case sensetive)\n-Salary must be a number.\n-Birthdate should be in yyyy-mm-dd format.", http.StatusUnprocessableEntity)

        logger.Log(logging.Entry{
            Payload:  fmt.Sprintf("Invalid employee data input : occured while validating employee fields during controllers.CreateEmployee function call.\n%v", err1),
            Severity: logging.Error,
        })

        w.Header().Set("Content-Type", "application/json")
        return
    }

    // Query to get the maximum employee ID
    iter := client.Collection("ems").OrderBy("ID", firestore.Desc).Limit(1).Documents(ctx)

    var lastEmployee models.Employee

    for {
        doc, err := iter.Next()
        if err != nil {
            break
        }
        doc.DataTo(&lastEmployee)
        // break
    }

    // Generate new employee ID
    EmpId := lastEmployee.ID + 1
    employee.ID = EmpId

    // Save employee data to Firestore
    _, _, err = client.Collection("ems").Add(ctx, employee)
    if err != nil {
        logger.Log(logging.Entry{
            Payload:  "Failed to create employee",
            Severity: logging.Error,
        })
        w.Header().Set("Content-Type", "text/plain")
        http.Error(w, "Failed to create employee", http.StatusInternalServerError)
        return
    }

    // Setting headers and staus codes
    // Set CORS headers for all requests
    w.Header().Set("Access-Control-Allow-Origin", "*")
    w.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS")
    w.Header().Set("Access-Control-Allow-Headers", "Content-Type")

    // Handle preflight request
    if r.Method == http.MethodOptions {
        w.WriteHeader(http.StatusNoContent)
        return
    }

    w.Header().Set("Content-Type", "application/json")
    w.WriteHeader(http.StatusCreated)
    json.NewEncoder(w).Encode(employee)

    logger.Log(logging.Entry{
        Payload:  fmt.Sprintf("Employee created successfully with emp id %v", EmpId),
        Severity: logging.Info,
    })

}

它适用于 Postman,但不适用于除 Postman 之外的其他客户端。

我通过为 CORS 添加适当的标头来部署我的云函数,但每当我尝试调用我的函数时,它仍然会给我一个 CORS 失败错误。

go google-cloud-platform google-cloud-functions cors
1个回答
1
投票

尽管 GCF 文档告诉您什么,手动实现 CORS 并不是一个好主意,因为它很容易出错。恰当的例子:Google Cloud 的 Go 示例将所有

OPTIONS
请求错误分类为 CORS 预检请求;有关此主题的更多信息,请参阅我的一篇博客文章

相反,依赖 CORS 中间件库几乎总是更好。例如,这是使用我自己的库jub0bs/fcors

配置为 CORS 的第一代基于 Go 的 Google Cloud Function 的概念证明
package p

import (
    "fmt"
    "log"
    "net/http"

    "github.com/jub0bs/fcors"
)

var Handler func(w http.ResponseWriter, r *http.Request)

func init() {
    cors, err := fcors.AllowAccess(
        fcors.FromAnyOrigin(),
        fcors.WithMethods(http.MethodPost),
        fcors.WithRequestHeaders("Content-Type"),
    )
    if err != nil {
        log.Fatal(err)
    }
    Handler = cors(http.HandlerFunc(HelloWorld)).ServeHTTP
}

func HelloWorld(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w, "Hello World!")
}

这是第二代 GCF 的等效概念证明:

package helloworld

import (
  "fmt"
  "log"
  "net/http"

  "github.com/GoogleCloudPlatform/functions-framework-go/functions"
  "github.com/jub0bs/fcors"
)

func init() {
    cors, err := fcors.AllowAccess(
        fcors.FromAnyOrigin(),
        fcors.WithMethods(http.MethodPost),
        fcors.WithRequestHeaders("Content-Type"),
    )
    if err != nil {
        log.Fatal(err)
    }
    handler := cors(http.HandlerFunc(HelloWorld)).ServeHTTP
    functions.HTTP("HelloHTTP", handler)
}

func HelloWorld(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w, "Hello World!")
}

当然,无论您选择第一代还是第二代 GCF,您还需要充分填充

go.mod
go.sum
文件:

module example.com/cloudfunction

go 1.21

require github.com/jub0bs/fcors v0.7.0

require (
    golang.org/x/net v0.18.0 // indirect
    golang.org/x/text v0.14.0 // indirect
)
github.com/jub0bs/fcors v0.7.0 h1:UVG2J1Nj+tvnYhj1BpMNR586CEEVmyDP7M2A6B4TErI=
github.com/jub0bs/fcors v0.7.0/go.mod h1:0jIYAcJa59RHDHwB+UZ64tcAbX3qU1V9xgH4nZoVDBs=
golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg=
golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
© www.soinside.com 2019 - 2024. All rights reserved.