You've already forked openaccounting-server
mirror of
https://github.com/openaccounting/oa-server.git
synced 2025-12-09 09:00:42 +13:00
initial commit
This commit is contained in:
236
vendor/github.com/ant0ine/go-json-rest/rest/access_log_apache.go
generated
vendored
Normal file
236
vendor/github.com/ant0ine/go-json-rest/rest/access_log_apache.go
generated
vendored
Normal file
@@ -0,0 +1,236 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
"text/template"
|
||||
"time"
|
||||
)
|
||||
|
||||
// TODO Future improvements:
|
||||
// * support %{strftime}t ?
|
||||
// * support %{<header>}o to print headers
|
||||
|
||||
// AccessLogFormat defines the format of the access log record.
|
||||
// This implementation is a subset of Apache mod_log_config.
|
||||
// (See http://httpd.apache.org/docs/2.0/mod/mod_log_config.html)
|
||||
//
|
||||
// %b content length in bytes, - if 0
|
||||
// %B content length in bytes
|
||||
// %D response elapsed time in microseconds
|
||||
// %h remote address
|
||||
// %H server protocol
|
||||
// %l identd logname, not supported, -
|
||||
// %m http method
|
||||
// %P process id
|
||||
// %q query string
|
||||
// %r first line of the request
|
||||
// %s status code
|
||||
// %S status code preceeded by a terminal color
|
||||
// %t time of the request
|
||||
// %T response elapsed time in seconds, 3 decimals
|
||||
// %u remote user, - if missing
|
||||
// %{User-Agent}i user agent, - if missing
|
||||
// %{Referer}i referer, - is missing
|
||||
//
|
||||
// Some predefined formats are provided as contants.
|
||||
type AccessLogFormat string
|
||||
|
||||
const (
|
||||
// CommonLogFormat is the Common Log Format (CLF).
|
||||
CommonLogFormat = "%h %l %u %t \"%r\" %s %b"
|
||||
|
||||
// CombinedLogFormat is the NCSA extended/combined log format.
|
||||
CombinedLogFormat = "%h %l %u %t \"%r\" %s %b \"%{Referer}i\" \"%{User-Agent}i\""
|
||||
|
||||
// DefaultLogFormat is the default format, colored output and response time, convenient for development.
|
||||
DefaultLogFormat = "%t %S\033[0m \033[36;1m%Dμs\033[0m \"%r\" \033[1;30m%u \"%{User-Agent}i\"\033[0m"
|
||||
)
|
||||
|
||||
// AccessLogApacheMiddleware produces the access log following a format inspired by Apache
|
||||
// mod_log_config. It depends on TimerMiddleware and RecorderMiddleware that should be in the wrapped
|
||||
// middlewares. It also uses request.Env["REMOTE_USER"].(string) set by the auth middlewares.
|
||||
type AccessLogApacheMiddleware struct {
|
||||
|
||||
// Logger points to the logger object used by this middleware, it defaults to
|
||||
// log.New(os.Stderr, "", 0).
|
||||
Logger *log.Logger
|
||||
|
||||
// Format defines the format of the access log record. See AccessLogFormat for the details.
|
||||
// It defaults to DefaultLogFormat.
|
||||
Format AccessLogFormat
|
||||
|
||||
textTemplate *template.Template
|
||||
}
|
||||
|
||||
// MiddlewareFunc makes AccessLogApacheMiddleware implement the Middleware interface.
|
||||
func (mw *AccessLogApacheMiddleware) MiddlewareFunc(h HandlerFunc) HandlerFunc {
|
||||
|
||||
// set the default Logger
|
||||
if mw.Logger == nil {
|
||||
mw.Logger = log.New(os.Stderr, "", 0)
|
||||
}
|
||||
|
||||
// set default format
|
||||
if mw.Format == "" {
|
||||
mw.Format = DefaultLogFormat
|
||||
}
|
||||
|
||||
mw.convertFormat()
|
||||
|
||||
return func(w ResponseWriter, r *Request) {
|
||||
|
||||
// call the handler
|
||||
h(w, r)
|
||||
|
||||
util := &accessLogUtil{w, r}
|
||||
|
||||
mw.Logger.Print(mw.executeTextTemplate(util))
|
||||
}
|
||||
}
|
||||
|
||||
var apacheAdapter = strings.NewReplacer(
|
||||
"%b", "{{.BytesWritten | dashIf0}}",
|
||||
"%B", "{{.BytesWritten}}",
|
||||
"%D", "{{.ResponseTime | microseconds}}",
|
||||
"%h", "{{.ApacheRemoteAddr}}",
|
||||
"%H", "{{.R.Proto}}",
|
||||
"%l", "-",
|
||||
"%m", "{{.R.Method}}",
|
||||
"%P", "{{.Pid}}",
|
||||
"%q", "{{.ApacheQueryString}}",
|
||||
"%r", "{{.R.Method}} {{.R.URL.RequestURI}} {{.R.Proto}}",
|
||||
"%s", "{{.StatusCode}}",
|
||||
"%S", "\033[{{.StatusCode | statusCodeColor}}m{{.StatusCode}}",
|
||||
"%t", "{{if .StartTime}}{{.StartTime.Format \"02/Jan/2006:15:04:05 -0700\"}}{{end}}",
|
||||
"%T", "{{if .ResponseTime}}{{.ResponseTime.Seconds | printf \"%.3f\"}}{{end}}",
|
||||
"%u", "{{.RemoteUser | dashIfEmptyStr}}",
|
||||
"%{User-Agent}i", "{{.R.UserAgent | dashIfEmptyStr}}",
|
||||
"%{Referer}i", "{{.R.Referer | dashIfEmptyStr}}",
|
||||
)
|
||||
|
||||
// Convert the Apache access log format into a text/template
|
||||
func (mw *AccessLogApacheMiddleware) convertFormat() {
|
||||
|
||||
tmplText := apacheAdapter.Replace(string(mw.Format))
|
||||
|
||||
funcMap := template.FuncMap{
|
||||
"dashIfEmptyStr": func(value string) string {
|
||||
if value == "" {
|
||||
return "-"
|
||||
}
|
||||
return value
|
||||
},
|
||||
"dashIf0": func(value int64) string {
|
||||
if value == 0 {
|
||||
return "-"
|
||||
}
|
||||
return fmt.Sprintf("%d", value)
|
||||
},
|
||||
"microseconds": func(dur *time.Duration) string {
|
||||
if dur != nil {
|
||||
return fmt.Sprintf("%d", dur.Nanoseconds()/1000)
|
||||
}
|
||||
return ""
|
||||
},
|
||||
"statusCodeColor": func(statusCode int) string {
|
||||
if statusCode >= 400 && statusCode < 500 {
|
||||
return "1;33"
|
||||
} else if statusCode >= 500 {
|
||||
return "0;31"
|
||||
}
|
||||
return "0;32"
|
||||
},
|
||||
}
|
||||
|
||||
var err error
|
||||
mw.textTemplate, err = template.New("accessLog").Funcs(funcMap).Parse(tmplText)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Execute the text template with the data derived from the request, and return a string.
|
||||
func (mw *AccessLogApacheMiddleware) executeTextTemplate(util *accessLogUtil) string {
|
||||
buf := bytes.NewBufferString("")
|
||||
err := mw.textTemplate.Execute(buf, util)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// accessLogUtil provides a collection of utility functions that devrive data from the Request object.
|
||||
// This object is used to provide data to the Apache Style template and the the JSON log record.
|
||||
type accessLogUtil struct {
|
||||
W ResponseWriter
|
||||
R *Request
|
||||
}
|
||||
|
||||
// As stored by the auth middlewares.
|
||||
func (u *accessLogUtil) RemoteUser() string {
|
||||
if u.R.Env["REMOTE_USER"] != nil {
|
||||
return u.R.Env["REMOTE_USER"].(string)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// If qs exists then return it with a leadin "?", apache log style.
|
||||
func (u *accessLogUtil) ApacheQueryString() string {
|
||||
if u.R.URL.RawQuery != "" {
|
||||
return "?" + u.R.URL.RawQuery
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// When the request entered the timer middleware.
|
||||
func (u *accessLogUtil) StartTime() *time.Time {
|
||||
if u.R.Env["START_TIME"] != nil {
|
||||
return u.R.Env["START_TIME"].(*time.Time)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// If remoteAddr is set then return is without the port number, apache log style.
|
||||
func (u *accessLogUtil) ApacheRemoteAddr() string {
|
||||
remoteAddr := u.R.RemoteAddr
|
||||
if remoteAddr != "" {
|
||||
if ip, _, err := net.SplitHostPort(remoteAddr); err == nil {
|
||||
return ip
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// As recorded by the recorder middleware.
|
||||
func (u *accessLogUtil) StatusCode() int {
|
||||
if u.R.Env["STATUS_CODE"] != nil {
|
||||
return u.R.Env["STATUS_CODE"].(int)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// As mesured by the timer middleware.
|
||||
func (u *accessLogUtil) ResponseTime() *time.Duration {
|
||||
if u.R.Env["ELAPSED_TIME"] != nil {
|
||||
return u.R.Env["ELAPSED_TIME"].(*time.Duration)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Process id.
|
||||
func (u *accessLogUtil) Pid() int {
|
||||
return os.Getpid()
|
||||
}
|
||||
|
||||
// As recorded by the recorder middleware.
|
||||
func (u *accessLogUtil) BytesWritten() int64 {
|
||||
if u.R.Env["BYTES_WRITTEN"] != nil {
|
||||
return u.R.Env["BYTES_WRITTEN"].(int64)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
Reference in New Issue
Block a user