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

时间:2021-02-20 08:14:59

标签: go

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

一旦提供商发送了我需要的详细信息,我希望能够关闭 HTTP 服务器,以保持一切干净。我想我正在寻找的是 Routines 和 Wait Groups,但我对这个领域还是很陌生。

这是我目前所拥有的。我已经编辑了将用户发送到提供程序的部分,因为我的主要问题只是如何在捕获 token 变量后关闭 HTTP 服务器。

  1. 服务器启动
  2. 用户被定向到提供商站点上的授权 URL
  3. 用户批准请求
  4. 提供商将用户引导回 localhost:8080/callback
  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 个答案:

答案 0 :(得分:1)

使用:

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.
相关问题