代码之家  ›  专栏  ›  技术社区  ›  Ari

启动Go-HTTP服务器,做一些事情,然后在任务完成后关闭它

go
  •  1
  • Ari  · 技术社区  · 3 年前

    我正在使用CLI应用程序设置OAuth2流。我需要为提供者创建一个临时的HTTP服务器来发送回调,例如。 localhost:8080/callback

    一旦提供者发送了我需要的详细信息,我希望能够关闭HTTP服务器,只是为了保持一切干净。我想我要找的是例行程序和等待小组,但我对这个领域还是比较陌生的。

    这就是我目前所拥有的。我已经修改了将用户发送到提供者的部分,因为我的主要问题只是如何在服务完成后关闭HTTP服务器 token

    1. 服务器启动
    2. 用户被定向到提供程序站点上的授权URL
    3. 用户批准请求
    4. 提供程序将用户引导回 本地主机:8080/回拨
    5. URL只包含客户端参数,所以我必须使用服务器HTML来使用JS捕获值并将其发送回服务器
    6. 服务器接收令牌,然后可以关闭
    package main
    
    import (
        "fmt"
        "log"
        "net/http"
        "sync"
    )
    
    func main() {
        // Start local HTTP serevr to listen for response
        serverDone := &sync.WaitGroup{}
        serverDone.Add(1)
        Start(serverDone)
    
        // ... Process to start OAuth2 flow
        // User is directed to provider website
        // User approves
        // Provider direct user back to localhost/callback
        
        serverDone.Wait()
    }
    
    func Start(wg *sync.WaitGroup) {
    
        srv := &http.Server{Addr: ":8080"}
        http.HandleFunc("/callback", func(w http.ResponseWriter, r *http.Request) {
            token := r.URL.Query().Get("token")
            if token != "" {
                fmt.Println("Found Token:", token)
                // Shut down server here
            } else {
                // Server HTML page to fetch token and return to server at /callback
            }
        })
    
        go func() {
            // let main know we are done cleaning up
            defer wg.Done()
    
            // ErrServerClosed on graceful close
            if err := srv.ListenAndServe(); err != http.ErrServerClosed {
                log.Fatalf("ListenAndServe(): %v", err)
            }
        }()
    }
    
    1 回复  |  直到 3 年前
        1
  •  1
  •   wasmup Prog_is_life    3 年前

    var ctxShutdown, cancel = context.WithCancel(context.Background())
    

    然后:

    cancel() // to say sorry, above.
    // graceful-shutdown
    err := srv.Shutdown(context.Background())
    

    试试这个:

    package main
    
    import (
        "context"
        "fmt"
        "log"
        "net/http"
        "sync"
    )
    
    func main() {
        serverDone := &sync.WaitGroup{}
        serverDone.Add(1)
        Start(serverDone)
        serverDone.Wait()
        fmt.Println("Done that.")
    }
    
    var ctxShutdown, cancel = context.WithCancel(context.Background())
    
    func Start(wg *sync.WaitGroup) {
        srv := &http.Server{Addr: ":8080"}
        http.HandleFunc("/callback", func(w http.ResponseWriter, r *http.Request) {
            select {
            case <-ctxShutdown.Done():
                fmt.Println("Sorry: Shuting down ...")
                return
            default:
            }
            token := r.URL.Query().Get("token")
            if token != "" {
                fmt.Println("Found Token:", token)
                fmt.Println("Shuting down ...")
                // Shut down server here
                cancel() // to say sorry, above.
                // graceful-shutdown
                err := srv.Shutdown(context.Background())
                if err != nil {
                    log.Println("server.Shutdown:", err)
                }
    
            } else {
                fmt.Fprintln(w, "Hi") // Server HTML page to fetch token and return to server at /callback
            }
        })
    
        go func() {
            defer wg.Done()
            if err := srv.ListenAndServe(); err != http.ErrServerClosed {
                log.Fatalf("ListenAndServe(): %v", err)
            }
            fmt.Println("Bye.")
        }()
    }
    
    

    跑开 http://127.0.0.1:8080/callback?token=2

    输出:

    Found Token: 2
    Shuting down ...
    Bye.
    Done that.