亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

使用 Go to Cloud Run 實例的反向代理

使用 Go to Cloud Run 實例的反向代理

Go
慕仙森 2022-10-17 16:08:01
我覺得我已經接近完成這項工作,但到目前為止,我遇到了一個問題,在 Go 中構建一個小型反向代理到 GCP Cloud Run 實例。請求“通過”,但請求的響應是默認的GCP Cloud Run 404。將請求返回到 Cloud Run 時會出現主機標頭被忽略,因此請求沒有被路由更正。我可能在這里缺少什么?package mainimport (    "log"    "net/http"    "net/http/httputil"    "net/url")const apiUrl = "MY_CLOUD_RUN.a.run.app"func main() {    http.HandleFunc("/", proxy)    log.Fatal(http.ListenAndServe(":8081", nil))}func proxy(res http.ResponseWriter, req *http.Request) {    // gets past CORS checks    if req.Method == http.MethodOptions {        headers := res.Header()        headers.Add("Access-Control-Allow-Origin", "*")        headers.Add("Vary", "Origin")        headers.Add("Vary", "Access-Control-Request-Method")        headers.Add("Vary", "Access-Control-Request-Headers")        headers.Add("Access-Control-Allow-Headers", "*")        headers.Add("Access-Control-Allow-Methods", "GET,HEAD,PUT,PATCH,POST,DELETE")        res.WriteHeader(http.StatusOK)        return    }    p := httputil.NewSingleHostReverseProxy(&url.URL{        Scheme: "http",        Host:   apiUrl,    })    p.Director = func(req *http.Request) {        req.Header.Add("X-Forwarded-Host", req.Host)        req.Header.Add("X-Origin-Host", apiUrl)        req.Header.Add("Host", apiUrl)        req.Header.Add("Access-Control-Allow-Origin", "*")        req.URL.Scheme = "https"        req.URL.Host = apiUrl    }    p.ModifyResponse = func(res *http.Response) error {        res.Header.Set("Access-Control-Allow-Methods", "GET,HEAD,PUT,PATCH,POST,DELETE")        res.Header.Set("Access-Control-Allow-Credentials", "true")        res.Header.Set("Access-Control-Allow-Origin", "*")        res.Header.Set("Access-Control-Allow-Headers", "*")        return nil    }    p.ServeHTTP(res, req)}
查看完整描述

1 回答

?
莫回無

TA貢獻1865條經驗 獲得超7個贊

這比最初的最初寫的要復雜一些,但我們最終得到的結果如下。


package main


import (

    "context"

    "fmt"

    "log"

    "net/http"

    "net/http/httputil"

    "net/url"

    "os"

    "os/signal"

    "time"


    "golang.org/x/oauth2"

    "google.golang.org/api/idtoken"

)


var port = ":8080"

var backend = "[CLOUD_RUN_INSTANCE_TO_PROXY].a.run.app"


func main() {

    logger := log.New(os.Stdout, "proxy: ", log.LstdFlags)

    logger.Println(fmt.Sprintf("Proxy server is starting for: %s on port: %s", backend, port))


    router := http.NewServeMux()

    router.Handle("/", proxyHandler())


    server := &http.Server{

        Addr:         port,

        Handler:      logging(logger)(router),

        ErrorLog:     logger,

        ReadTimeout:  30 * time.Second,

        WriteTimeout: 30 * time.Second,

        IdleTimeout:  15 * time.Second,

    }


    done := make(chan bool)

    quit := make(chan os.Signal, 1)

    signal.Notify(quit, os.Interrupt)


    go func() {

        <-quit

        logger.Println("Proxy server is shutting down...")


        ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)

        defer cancel()


        server.SetKeepAlivesEnabled(false)

        if err := server.Shutdown(ctx); err != nil {

            logger.Fatalf("Could not gracefully shutdown the server: %v\n", err)

        }

        close(done)

    }()


    if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {

        logger.Fatalf("Could not listen on %s: %v\n", port, err)

    }


    <-done

    logger.Println("Server stopped")

}


func proxyHandler() http.Handler {

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

        if r.Method == http.MethodOptions {

            headers := w.Header()

            headers.Add("Access-Control-Allow-Origin", "*")

            headers.Add("Access-Control-Allow-Headers", "*")

            headers.Add("Access-Control-Allow-Methods", "GET,HEAD,PUT,PATCH,POST,DELETE")

            w.WriteHeader(http.StatusOK)

            return

        }


        path := fmt.Sprintf("https://%s%s", backend, r.RequestURI)

        at, _ := idTokenTokenSource(path)


        p := httputil.NewSingleHostReverseProxy(&url.URL{

            Scheme: "https",

            Host:   backend,

        })

        p.Director = func(r *http.Request) {

            if at != nil {

                at.SetAuthHeader(r)

            }

        }

        p.ModifyResponse = func(res *http.Response) error {

            res.Header.Set("Access-Control-Allow-Methods", "GET,HEAD,PUT,PATCH,POST,DELETE")

            res.Header.Set("Access-Control-Allow-Credentials", "true")

            res.Header.Set("Access-Control-Allow-Origin", "*")

            res.Header.Set("Access-Control-Allow-Headers", "*")

            return nil

        }


        r.URL.Scheme = "https"

        r.URL.Host = backend

        r.Header.Set("X-Forwarded-Host", r.Header.Get("Host"))

        r.Host = backend


        if at != nil {

            at.SetAuthHeader(r)

        }


        p.ServeHTTP(w, r)

    })

}


func logging(l *log.Logger) func(http.Handler) http.Handler {

    return func(next http.Handler) http.Handler {

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

            defer func() {

                requestId := r.Header.Get("X-Request-Id")

                if requestId == "" {

                    requestId = fmt.Sprintf("%d", time.Now().UnixNano())

                }

                w.Header().Set("X-Request-Id", requestId)

                l.Println(requestId, r.Method, r.URL.Path, r.RemoteAddr, r.UserAgent())

            }()


            next.ServeHTTP(w, r)

        })

    }

}


func idTokenTokenSource(audience string) (*oauth2.Token, error) {

    ts, err := idtoken.NewTokenSource(context.Background(), audience)

    if err != nil {

        return nil, err

    }


    t, err := ts.Token()

    if err != nil {

        return nil, err

    }


    return t, nil

}


一些正常關閉、http 設置和日志記錄的很大一部分來自:https ://gist.github.com/enricofoltran/10b4a980cd07cb02836f70a4ab3e72d7


查看完整回答
反對 回復 2022-10-17
  • 1 回答
  • 0 關注
  • 132 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號