go web框架

  • net/http
  • gin-gonic/gin
  • go-chi/chi
  • gorilla/mux

 

其中gin 我是用的最多,但是在最近的使用中我有一些特殊需求,比如 /gitlab/{uuid}/notify,我只获取{uuid}的值才能满足,gin 不能更好的满足我的需求

这时候 gorilla/mux 就能满足我的需求

 

 

 

 

package main

import (
	"context"
	"errors"
	"fmt"
	"github.com/go-playground/webhooks/v6/gitlab"
	"github.com/gorilla/handlers"
	"github.com/gorilla/mux"
	"io"
	"log"
	"net/http"
	"os"
	"os/signal"
	"time"
)

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

	ctx := r.Context()

	fmt.Println("ctx:", ctx)

	XGitlabToken, ok := ctx.Value("X-Gitlab-Token").(string)
	if !ok {
		http.Error(w, http.StatusText(422), 422)
		return
	}
	fmt.Println("X-Gitlab-Token", XGitlabToken)

	fmt.Println("r.Header.Get(\"X-Gitlab-Token\")", r.Header.Get("X-Gitlab-Token"))
	vars := mux.Vars(r)
	name := vars["uuid"]
	w.Write([]byte("Hello, " + name + "!"))
	//hook, err := gitlab.New(gitlab.Options.Secret("122333"))
	hook, err := gitlab.New()
	if err != nil {

		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	payload, err := hook.Parse(r, gitlab.PushEvents, gitlab.TagEvents, gitlab.MergeRequestEvents, gitlab.BuildEvents, gitlab.JobEvents, gitlab.PipelineEvents)
	if err != nil {
		if errors.Is(err, gitlab.ErrEventNotFound) {
			// ok event wasn't one of the ones asked to be parsed
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		if errors.Is(err, gitlab.ErrGitLabTokenVerificationFailed) {
			// ok event wasn't one of the ones asked to be parsed
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		fmt.Println("err", err.Error())
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	if payload == nil {
		fmt.Println(payload)
	}

	switch payload.(type) {

	case gitlab.MergeRequestEventPayload:
		release := payload.(gitlab.MergeRequestEventPayload)
		// Do whatever you want from here...
		fmt.Printf("%+v", release)

	case gitlab.PushEventPayload:
		pushRequest := payload.(gitlab.PushEventPayload)
		// Do whatever you want from here...
		fmt.Printf("%+v", pushRequest)

	case gitlab.TagEventPayload:
		TagRequest := payload.(gitlab.TagEventPayload)
		// Do whatever you want from here...
		fmt.Printf("%+v", TagRequest)
	}
	_, err = io.WriteString(w, r.URL.Path)
	if err != nil {
		return
	}

}

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

func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if err := h(w, r); err != nil {
		// handle returned error here.
		w.WriteHeader(503)
		w.Write([]byte("bad"))
	}
}

// MyMiddleware HTTP middleware setting a value on the request context
func MyMiddleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// create new context from `r` request context, and assign key `"user"`
		// to value of `"123"`
		ctx := context.WithValue(r.Context(), "X-Gitlab-Token", r.Header.Get("X-Gitlab-Token"))

		// call the next handler in the chain, passing the response writer and
		// the updated request object with the new context value.
		//
		// note: context.Context values are nested, so any previously set
		// values will be accessible as well, and the new `"user"` key
		// will be accessible from this point forward.
		next.ServeHTTP(w, r.WithContext(ctx))
	})
}

func main() {
	// 创建一个新的路由器
	r := mux.NewRouter()

	//// 定义一个路由
	//r.HandleFunc("/gitlab/{uuid}/notify", func(w http.ResponseWriter, r *http.Request) {
	//	vars := mux.Vars(r)
	//	name := vars["uuid"]
	//	w.Write([]byte("Hello, " + name + "!"))
	//}).Methods("POST")


	r.Use(MyMiddleware)

	r.HandleFunc("/gitlab/{uuid}/notify", gitlabWebhook).Methods("POST")


	loggedRouter := handlers.LoggingHandler(os.Stdout, r)



	srv := &http.Server{
		Addr: ":8080",
		// Good practice to set timeouts to avoid Slowloris attacks.
		WriteTimeout: time.Second * 15,
		ReadTimeout:  time.Second * 15,
		IdleTimeout:  time.Second * 60,
		Handler:      loggedRouter, // Pass our instance of gorilla/mux in.
	}



	go func() {

		// 服务连接
		if err := srv.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
			//errChan <- err
			log.Fatalf("listen: %s\n", err)

		}

	}()



	c := make(chan os.Signal, 1)
	// We'll accept graceful shutdowns when quit via SIGINT (Ctrl+C)
	// SIGKILL, SIGQUIT or SIGTERM (Ctrl+/) will not be caught.
	signal.Notify(c, os.Interrupt)

	// Block until we receive our signal.
	<-c


	wait := time.Second * 60
	// Create a deadline to wait for.
	ctx, cancel := context.WithTimeout(context.Background(), wait)
	defer cancel()
	// Doesn't block if no connections, but will otherwise wait
	// until the timeout deadline.
	srv.Shutdown(ctx)
	// Optionally, you could run srv.Shutdown in a goroutine and block on
	// <-ctx.Done() if your application should wait for other services
	// to finalize based on context cancellation.
	log.Println("shutting down")
	os.Exit(0)

}

  

posted @ 2024-05-24 18:08  上架员的code之路  阅读(24)  评论(0)    收藏  举报