golang 服务检查收集器 - #poc

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了golang 服务检查收集器 - #poc相关的知识,希望对你有一定的参考价值。

package main

import (
	"net/http"
	"sync"

	"github.com/gin-gonic/gin"
)

func main() {
	r := gin.Default()

	r.GET("/service/check", ListChecks)
	r.POST("/service/check", AddCheck)
	r.DELETE("/service/check/:service/:host", RmCheck)

	r.Run(":8080")
}

type ServiceCheck struct {
	Timestamp int    `json:"timestamp"`
	Service   string `json:"service"`
	Hostname  string `json:"hostname"`
	Status    int    `json:"status"`
	Output    string `json:"output"`
}

var (
	mutex  sync.RWMutex
	checks = map[string]ServiceCheck{}
)

func ListChecks(c *gin.Context) {
	mutex.RLock()
	defer mutex.RUnlock()

	c.JSON(http.StatusOK, checks)
}

func AddCheck(c *gin.Context) {
	mutex.Lock()
	defer mutex.Unlock()

	var check ServiceCheck
	if !bindJSON(c, &check) {
		return
	}

	checks[check.Service+"@"+check.Hostname] = check

	c.JSON(http.StatusOK, check)
}

func RmCheck(c *gin.Context) {
	mutex.Lock()
	defer mutex.Unlock()

	service := c.Param("service")
	hostname := c.Param("hostname")

	if _, ok := checks[service+"@"+hostname]; !ok {
		c.JSON(http.StatusBadRequest, gin.H{
			"message": "No check found for " + service + "/" + hostname,
		})
	}

	delete(checks, service+hostname)

	c.JSON(http.StatusNoContent, nil)
}

func bindJSON(c *gin.Context, obj interface{}) bool {
	err := c.BindJSON(&obj)
	isError := err != nil
	if isError {
		c.JSON(http.StatusBadRequest, gin.H{
			"message": err.Error(),
		})
	}
	return !isError
}

golang 一个简单的golang Web服务器,具有基本的日志记录,跟踪,运行状况检查,正常关闭和零依赖关系

package main

import (
	"context"
	"fmt"
	"log"
	"net/http"
	"os"
	"os/signal"
	"strconv"
	"sync/atomic"
	"syscall"
	"time"
)

type middleware func(http.Handler) http.Handler
type middlewares []middleware

func (mws middlewares) apply(hdlr http.Handler) http.Handler {
	if len(mws) == 0 {
		return hdlr
	}
	return mws[1:].apply(mws[0](hdlr))
}

func (c *controller) shutdown(ctx context.Context, server *http.Server) context.Context {
	ctx, done := context.WithCancel(ctx)

	quit := make(chan os.Signal, 1)
	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
	go func() {
		defer done()

		<-quit
		signal.Stop(quit)
		close(quit)

		atomic.StoreInt64(&c.healthy, 0)
		server.ErrorLog.Printf("Server is shutting down...\n")

		ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
		defer cancel()

		server.SetKeepAlivesEnabled(false)
		if err := server.Shutdown(ctx); err != nil {
			server.ErrorLog.Fatalf("Could not gracefully shutdown the server: %s\n", err)
		}
	}()

	return ctx
}

type controller struct {
	logger        *log.Logger
	nextRequestID func() string
	healthy       int64
}

func main() {
	listenAddr := ":5000"
	if len(os.Args) == 2 {
		listenAddr = os.Args[1]
	}

	logger := log.New(os.Stdout, "http: ", log.LstdFlags)
	logger.Printf("Server is starting...")

	c := &controller{logger: logger, nextRequestID: func() string { return strconv.FormatInt(time.Now().UnixNano(), 36) }}
	router := http.NewServeMux()
	router.HandleFunc("/", c.index)
	router.HandleFunc("/healthz", c.healthz)

	server := &http.Server{
		Addr:         listenAddr,
		Handler:      (middlewares{c.tracing, c.logging}).apply(router),
		ErrorLog:     logger,
		ReadTimeout:  5 * time.Second,
		WriteTimeout: 10 * time.Second,
		IdleTimeout:  15 * time.Second,
	}
	ctx := c.shutdown(context.Background(), server)

	logger.Printf("Server is ready to handle requests at %q\n", listenAddr)
	atomic.StoreInt64(&c.healthy, time.Now().UnixNano())

	if err := server.ListenAndServe(); err != http.ErrServerClosed {
		logger.Fatalf("Could not listen on %q: %s\n", listenAddr, err)
	}
	<-ctx.Done()
	logger.Printf("Server stopped\n")
}

func (c *controller) index(w http.ResponseWriter, req *http.Request) {
	if req.URL.Path != "/" {
		http.NotFound(w, req)
		return
	}
	fmt.Fprintf(w, "Hello, World!\n")
}

func (c *controller) healthz(w http.ResponseWriter, req *http.Request) {
	if h := atomic.LoadInt64(&c.healthy); h == 0 {
		w.WriteHeader(http.StatusServiceUnavailable)
	} else {
		fmt.Fprintf(w, "uptime: %s\n", time.Since(time.Unix(0, h)))
	}
}

func (c *controller) logging(hdlr http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		defer func(start time.Time) {
			requestID := w.Header().Get("X-Request-Id")
			if requestID == "" {
				requestID = "unknown"
			}
			c.logger.Println(requestID, req.Method, req.URL.Path, req.RemoteAddr, req.UserAgent(), time.Since(start))
		}(time.Now())
		hdlr.ServeHTTP(w, req)
	})
}

func (c *controller) tracing(hdlr http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		requestID := req.Header.Get("X-Request-Id")
		if requestID == "" {
			requestID = c.nextRequestID()
		}
		w.Header().Set("X-Request-Id", requestID)
		hdlr.ServeHTTP(w, req)
	})
}

// main_test.go
var (
	_ http.Handler = http.HandlerFunc((&controller{}).index)
	_ http.Handler = http.HandlerFunc((&controller{}).healthz)
	_ middleware   = (&controller{}).logging
	_ middleware   = (&controller{}).tracing
)

以上是关于golang 服务检查收集器 - #poc的主要内容,如果未能解决你的问题,请参考以下文章

hash碰撞POC

所有可用的和最新的CVE及其PoC合集

网站指纹收集及其利用方式

Python十几行代码获取db库新增的poc

golang 一个简单的golang Web服务器,具有基本的日志记录,跟踪,运行状况检查,正常关闭和零依赖关系

golang 一个简单的golang Web服务器,具有基本的日志记录,跟踪,运行状况检查,正常关闭和零依赖关系