mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-11-03 20:02:27 -06:00 
			
		
		
		
	* update dependencies, bump Go version to 1.19 * bump test image Go version * update golangci-lint * update gotosocial-drone-build * sign * linting, go fmt * update swagger docs * update swagger docs * whitespace * update contributing.md * fuckin whoopsie doopsie * linterino, linteroni * fix followrequest test not starting processor * fix other api/client tests not starting processor * fix remaining tests where processor not started * bump go-runners version * don't check last-webfingered-at, processor may have updated this * update swagger command * update bun to latest version * fix embed to work the same as before with new bun Signed-off-by: kim <grufwub@gmail.com> Co-authored-by: tsmethurst <tobi.smethurst@protonmail.com>
		
			
				
	
	
		
			270 lines
		
	
	
	
		
			6.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			270 lines
		
	
	
	
		
			6.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// Copyright 2014 Manu Martinez-Almeida. All rights reserved.
 | 
						|
// Use of this source code is governed by a MIT style
 | 
						|
// license that can be found in the LICENSE file.
 | 
						|
 | 
						|
package gin
 | 
						|
 | 
						|
import (
 | 
						|
	"fmt"
 | 
						|
	"io"
 | 
						|
	"net/http"
 | 
						|
	"os"
 | 
						|
	"time"
 | 
						|
 | 
						|
	"github.com/mattn/go-isatty"
 | 
						|
)
 | 
						|
 | 
						|
type consoleColorModeValue int
 | 
						|
 | 
						|
const (
 | 
						|
	autoColor consoleColorModeValue = iota
 | 
						|
	disableColor
 | 
						|
	forceColor
 | 
						|
)
 | 
						|
 | 
						|
const (
 | 
						|
	green   = "\033[97;42m"
 | 
						|
	white   = "\033[90;47m"
 | 
						|
	yellow  = "\033[90;43m"
 | 
						|
	red     = "\033[97;41m"
 | 
						|
	blue    = "\033[97;44m"
 | 
						|
	magenta = "\033[97;45m"
 | 
						|
	cyan    = "\033[97;46m"
 | 
						|
	reset   = "\033[0m"
 | 
						|
)
 | 
						|
 | 
						|
var consoleColorMode = autoColor
 | 
						|
 | 
						|
// LoggerConfig defines the config for Logger middleware.
 | 
						|
type LoggerConfig struct {
 | 
						|
	// Optional. Default value is gin.defaultLogFormatter
 | 
						|
	Formatter LogFormatter
 | 
						|
 | 
						|
	// Output is a writer where logs are written.
 | 
						|
	// Optional. Default value is gin.DefaultWriter.
 | 
						|
	Output io.Writer
 | 
						|
 | 
						|
	// SkipPaths is an url path array which logs are not written.
 | 
						|
	// Optional.
 | 
						|
	SkipPaths []string
 | 
						|
}
 | 
						|
 | 
						|
// LogFormatter gives the signature of the formatter function passed to LoggerWithFormatter
 | 
						|
type LogFormatter func(params LogFormatterParams) string
 | 
						|
 | 
						|
// LogFormatterParams is the structure any formatter will be handed when time to log comes
 | 
						|
type LogFormatterParams struct {
 | 
						|
	Request *http.Request
 | 
						|
 | 
						|
	// TimeStamp shows the time after the server returns a response.
 | 
						|
	TimeStamp time.Time
 | 
						|
	// StatusCode is HTTP response code.
 | 
						|
	StatusCode int
 | 
						|
	// Latency is how much time the server cost to process a certain request.
 | 
						|
	Latency time.Duration
 | 
						|
	// ClientIP equals Context's ClientIP method.
 | 
						|
	ClientIP string
 | 
						|
	// Method is the HTTP method given to the request.
 | 
						|
	Method string
 | 
						|
	// Path is a path the client requests.
 | 
						|
	Path string
 | 
						|
	// ErrorMessage is set if error has occurred in processing the request.
 | 
						|
	ErrorMessage string
 | 
						|
	// isTerm shows whether gin's output descriptor refers to a terminal.
 | 
						|
	isTerm bool
 | 
						|
	// BodySize is the size of the Response Body
 | 
						|
	BodySize int
 | 
						|
	// Keys are the keys set on the request's context.
 | 
						|
	Keys map[string]any
 | 
						|
}
 | 
						|
 | 
						|
// StatusCodeColor is the ANSI color for appropriately logging http status code to a terminal.
 | 
						|
func (p *LogFormatterParams) StatusCodeColor() string {
 | 
						|
	code := p.StatusCode
 | 
						|
 | 
						|
	switch {
 | 
						|
	case code >= http.StatusOK && code < http.StatusMultipleChoices:
 | 
						|
		return green
 | 
						|
	case code >= http.StatusMultipleChoices && code < http.StatusBadRequest:
 | 
						|
		return white
 | 
						|
	case code >= http.StatusBadRequest && code < http.StatusInternalServerError:
 | 
						|
		return yellow
 | 
						|
	default:
 | 
						|
		return red
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// MethodColor is the ANSI color for appropriately logging http method to a terminal.
 | 
						|
func (p *LogFormatterParams) MethodColor() string {
 | 
						|
	method := p.Method
 | 
						|
 | 
						|
	switch method {
 | 
						|
	case http.MethodGet:
 | 
						|
		return blue
 | 
						|
	case http.MethodPost:
 | 
						|
		return cyan
 | 
						|
	case http.MethodPut:
 | 
						|
		return yellow
 | 
						|
	case http.MethodDelete:
 | 
						|
		return red
 | 
						|
	case http.MethodPatch:
 | 
						|
		return green
 | 
						|
	case http.MethodHead:
 | 
						|
		return magenta
 | 
						|
	case http.MethodOptions:
 | 
						|
		return white
 | 
						|
	default:
 | 
						|
		return reset
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// ResetColor resets all escape attributes.
 | 
						|
func (p *LogFormatterParams) ResetColor() string {
 | 
						|
	return reset
 | 
						|
}
 | 
						|
 | 
						|
// IsOutputColor indicates whether can colors be outputted to the log.
 | 
						|
func (p *LogFormatterParams) IsOutputColor() bool {
 | 
						|
	return consoleColorMode == forceColor || (consoleColorMode == autoColor && p.isTerm)
 | 
						|
}
 | 
						|
 | 
						|
// defaultLogFormatter is the default log format function Logger middleware uses.
 | 
						|
var defaultLogFormatter = func(param LogFormatterParams) string {
 | 
						|
	var statusColor, methodColor, resetColor string
 | 
						|
	if param.IsOutputColor() {
 | 
						|
		statusColor = param.StatusCodeColor()
 | 
						|
		methodColor = param.MethodColor()
 | 
						|
		resetColor = param.ResetColor()
 | 
						|
	}
 | 
						|
 | 
						|
	if param.Latency > time.Minute {
 | 
						|
		param.Latency = param.Latency.Truncate(time.Second)
 | 
						|
	}
 | 
						|
	return fmt.Sprintf("[GIN] %v |%s %3d %s| %13v | %15s |%s %-7s %s %#v\n%s",
 | 
						|
		param.TimeStamp.Format("2006/01/02 - 15:04:05"),
 | 
						|
		statusColor, param.StatusCode, resetColor,
 | 
						|
		param.Latency,
 | 
						|
		param.ClientIP,
 | 
						|
		methodColor, param.Method, resetColor,
 | 
						|
		param.Path,
 | 
						|
		param.ErrorMessage,
 | 
						|
	)
 | 
						|
}
 | 
						|
 | 
						|
// DisableConsoleColor disables color output in the console.
 | 
						|
func DisableConsoleColor() {
 | 
						|
	consoleColorMode = disableColor
 | 
						|
}
 | 
						|
 | 
						|
// ForceConsoleColor force color output in the console.
 | 
						|
func ForceConsoleColor() {
 | 
						|
	consoleColorMode = forceColor
 | 
						|
}
 | 
						|
 | 
						|
// ErrorLogger returns a HandlerFunc for any error type.
 | 
						|
func ErrorLogger() HandlerFunc {
 | 
						|
	return ErrorLoggerT(ErrorTypeAny)
 | 
						|
}
 | 
						|
 | 
						|
// ErrorLoggerT returns a HandlerFunc for a given error type.
 | 
						|
func ErrorLoggerT(typ ErrorType) HandlerFunc {
 | 
						|
	return func(c *Context) {
 | 
						|
		c.Next()
 | 
						|
		errors := c.Errors.ByType(typ)
 | 
						|
		if len(errors) > 0 {
 | 
						|
			c.JSON(-1, errors)
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// Logger instances a Logger middleware that will write the logs to gin.DefaultWriter.
 | 
						|
// By default, gin.DefaultWriter = os.Stdout.
 | 
						|
func Logger() HandlerFunc {
 | 
						|
	return LoggerWithConfig(LoggerConfig{})
 | 
						|
}
 | 
						|
 | 
						|
// LoggerWithFormatter instance a Logger middleware with the specified log format function.
 | 
						|
func LoggerWithFormatter(f LogFormatter) HandlerFunc {
 | 
						|
	return LoggerWithConfig(LoggerConfig{
 | 
						|
		Formatter: f,
 | 
						|
	})
 | 
						|
}
 | 
						|
 | 
						|
// LoggerWithWriter instance a Logger middleware with the specified writer buffer.
 | 
						|
// Example: os.Stdout, a file opened in write mode, a socket...
 | 
						|
func LoggerWithWriter(out io.Writer, notlogged ...string) HandlerFunc {
 | 
						|
	return LoggerWithConfig(LoggerConfig{
 | 
						|
		Output:    out,
 | 
						|
		SkipPaths: notlogged,
 | 
						|
	})
 | 
						|
}
 | 
						|
 | 
						|
// LoggerWithConfig instance a Logger middleware with config.
 | 
						|
func LoggerWithConfig(conf LoggerConfig) HandlerFunc {
 | 
						|
	formatter := conf.Formatter
 | 
						|
	if formatter == nil {
 | 
						|
		formatter = defaultLogFormatter
 | 
						|
	}
 | 
						|
 | 
						|
	out := conf.Output
 | 
						|
	if out == nil {
 | 
						|
		out = DefaultWriter
 | 
						|
	}
 | 
						|
 | 
						|
	notlogged := conf.SkipPaths
 | 
						|
 | 
						|
	isTerm := true
 | 
						|
 | 
						|
	if w, ok := out.(*os.File); !ok || os.Getenv("TERM") == "dumb" ||
 | 
						|
		(!isatty.IsTerminal(w.Fd()) && !isatty.IsCygwinTerminal(w.Fd())) {
 | 
						|
		isTerm = false
 | 
						|
	}
 | 
						|
 | 
						|
	var skip map[string]struct{}
 | 
						|
 | 
						|
	if length := len(notlogged); length > 0 {
 | 
						|
		skip = make(map[string]struct{}, length)
 | 
						|
 | 
						|
		for _, path := range notlogged {
 | 
						|
			skip[path] = struct{}{}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return func(c *Context) {
 | 
						|
		// Start timer
 | 
						|
		start := time.Now()
 | 
						|
		path := c.Request.URL.Path
 | 
						|
		raw := c.Request.URL.RawQuery
 | 
						|
 | 
						|
		// Process request
 | 
						|
		c.Next()
 | 
						|
 | 
						|
		// Log only when path is not being skipped
 | 
						|
		if _, ok := skip[path]; !ok {
 | 
						|
			param := LogFormatterParams{
 | 
						|
				Request: c.Request,
 | 
						|
				isTerm:  isTerm,
 | 
						|
				Keys:    c.Keys,
 | 
						|
			}
 | 
						|
 | 
						|
			// Stop timer
 | 
						|
			param.TimeStamp = time.Now()
 | 
						|
			param.Latency = param.TimeStamp.Sub(start)
 | 
						|
 | 
						|
			param.ClientIP = c.ClientIP()
 | 
						|
			param.Method = c.Request.Method
 | 
						|
			param.StatusCode = c.Writer.Status()
 | 
						|
			param.ErrorMessage = c.Errors.ByType(ErrorTypePrivate).String()
 | 
						|
 | 
						|
			param.BodySize = c.Writer.Size()
 | 
						|
 | 
						|
			if raw != "" {
 | 
						|
				path = path + "?" + raw
 | 
						|
			}
 | 
						|
 | 
						|
			param.Path = path
 | 
						|
 | 
						|
			fmt.Fprint(out, formatter(param))
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 |