func (l *Middleware) Handler(next http.Handler) http.Handler {
	formater := l.formatDefault
	if l.apacheCombined {
		formater = l.formatApacheCombined
	}
	fn := func(w http.ResponseWriter, r *http.Request) {
		ww := newCustomResponseWriter(w)
		user := ""
		if l.userFn != nil {
			if u, err := l.userFn(r); err == nil {
				user = u
			}
		}
		body := l.getBody(r)
		t1 := time.Now()
		defer func() {
			t2 := time.Now()
			u := *r.URL  
			u.RawQuery = l.sanitizeQuery(u.RawQuery)
			rawurl := u.String()
			if unescURL, err := url.QueryUnescape(rawurl); err == nil {
				rawurl = unescURL
			}
			remoteIP := l.remoteIP(r)
			if l.ipFn != nil {  
				remoteIP = l.ipFn(remoteIP)
			}
			server := r.URL.Hostname()
			if server == "" {
				server = strings.Split(r.Host, ":")[0]
			}
			p := &logParts{
				duration:   t2.Sub(t1),
				rawURL:     rawurl,
				method:     r.Method,
				host:       server,
				remoteIP:   remoteIP,
				statusCode: ww.status,
				respSize:   ww.size,
				prefix:     l.prefix,
				user:       user,
				body:       body,
			}
			l.log.Logf(formater(r, p))
		}()
		next.ServeHTTP(ww, r)
	}
	return http.HandlerFunc(fn)
}
Handler middleware prints http log
package logger
import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"net/url"
	"regexp"
	"strconv"
	"strings"
	"time"
)
type Middleware struct {
	prefix         string
	logBody        bool
	maxBodySize    int
	ipFn           func(ip string) string
	userFn         func(r *http.Request) (string, error)
	subjFn         func(r *http.Request) (string, error)
	log            Backend
	apacheCombined bool
}
type Backend interface {
	Logf(format string, args ...interface{})
}
type logParts struct {
	duration   time.Duration
	rawURL     string
	method     string
	remoteIP   string
	statusCode int
	respSize   int
	host       string
	prefix string
	user   string
	body   string
}
type stdBackend struct{}
func (s stdBackend) Logf(format string, args ...interface{}) {
	log.Printf(format, args...)
}
func Logger(next http.Handler) http.Handler {
	l := New(Prefix("REST"))
	return l.Handler(next)
}
func New(options ...Option) *Middleware {
	res := Middleware{
		prefix:      "",
		maxBodySize: 1024,
		log:         stdBackend{},
	}
	for _, opt := range options {
		opt(&res)
	}
	return &res
}