feature/adding-log-file #1
			
				
			
		
		
		
	| 
						 | 
					@ -0,0 +1,52 @@
 | 
				
			||||||
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"encoding/json"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"path/filepath"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const CONFIG_LOG string = "/var/lib/gocustomurls/"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ConfigFile struct {
 | 
				
			||||||
 | 
						Mappings []struct {
 | 
				
			||||||
 | 
							Protocol  string `json:"protocol"`
 | 
				
			||||||
 | 
							VanityUrl string `json:"vanity_url"`
 | 
				
			||||||
 | 
							RealUrl   string `json:"real_url"`
 | 
				
			||||||
 | 
						} `json:"mappings"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// isFile - check if fp is a valid file
 | 
				
			||||||
 | 
					func isFile(fp string) bool {
 | 
				
			||||||
 | 
						info, err := os.Stat(fp)
 | 
				
			||||||
 | 
						if os.IsNotExist(err) || !info.Mode().IsRegular() {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return true
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// load mapping file
 | 
				
			||||||
 | 
					func LoadFile() (ConfigFile, error) {
 | 
				
			||||||
 | 
						var mapping ConfigFile
 | 
				
			||||||
 | 
						dirname, err := os.UserConfigDir()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return mapping, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						configFilePath := filepath.Join(dirname, "gocustomurls/config.json")
 | 
				
			||||||
 | 
						ok := isFile(configFilePath)
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							return mapping, fmt.Errorf("%s/gocustomurls/config.json file is not found", dirname)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						configFile, err := os.Open(configFilePath)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return mapping, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer configFile.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = json.NewDecoder(configFile).Decode(&mapping)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return mapping, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return mapping, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,148 @@
 | 
				
			||||||
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"encoding/json"
 | 
				
			||||||
 | 
						"log"
 | 
				
			||||||
 | 
						"net/http"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// some headers not worth logging
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						hdrsToNotLog = []string{
 | 
				
			||||||
 | 
							"Accept-Language",
 | 
				
			||||||
 | 
							"Cache-Control",
 | 
				
			||||||
 | 
							"Cf-Ray",
 | 
				
			||||||
 | 
							"CF-Visitor",
 | 
				
			||||||
 | 
							"CF-Connecting-IP",
 | 
				
			||||||
 | 
							"Cdn-Loop",
 | 
				
			||||||
 | 
							"Cookie",
 | 
				
			||||||
 | 
							"Connection",
 | 
				
			||||||
 | 
							"Dnt",
 | 
				
			||||||
 | 
							"If-Modified-Since",
 | 
				
			||||||
 | 
							"Sec-Fetch-Dest",
 | 
				
			||||||
 | 
							"Sec-Ch-Ua-Mobile",
 | 
				
			||||||
 | 
							// "Sec-Ch-Ua",
 | 
				
			||||||
 | 
							"Sec-Ch-Ua-Platform",
 | 
				
			||||||
 | 
							"Sec-Fetch-Site",
 | 
				
			||||||
 | 
							"Sec-Fetch-Mode",
 | 
				
			||||||
 | 
							"Sec-Fetch-User",
 | 
				
			||||||
 | 
							"Upgrade-Insecure-Requests",
 | 
				
			||||||
 | 
							"X-Request-Start",
 | 
				
			||||||
 | 
							"X-Forwarded-For",
 | 
				
			||||||
 | 
							"X-Forwarded-Proto",
 | 
				
			||||||
 | 
							"X-Forwarded-Host",
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						hdrsToNotLogMap map[string]bool
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type LogFile struct {
 | 
				
			||||||
 | 
						handle *os.File
 | 
				
			||||||
 | 
						logger *log.Logger
 | 
				
			||||||
 | 
						path   string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type LogFileRec struct {
 | 
				
			||||||
 | 
						Method string `json:"method"`
 | 
				
			||||||
 | 
						IpAddr string `json:"ipAddr"`
 | 
				
			||||||
 | 
						Url    string `json:"url"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func newFileLogger(path string) (*LogFile, error) {
 | 
				
			||||||
 | 
						f, err := os.OpenFile(path, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0666)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return &LogFile{
 | 
				
			||||||
 | 
							handle: f,
 | 
				
			||||||
 | 
							logger: log.New(f, "", 0),
 | 
				
			||||||
 | 
							path:   path,
 | 
				
			||||||
 | 
						}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (f *LogFile) Close() error {
 | 
				
			||||||
 | 
						if f == nil {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						err := f.handle.Close()
 | 
				
			||||||
 | 
						f.handle = nil
 | 
				
			||||||
 | 
						return err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func extractFirstFragment(header *http.Header, headerName string) string {
 | 
				
			||||||
 | 
						s := header.Get(headerName)
 | 
				
			||||||
 | 
						if len(strings.TrimSpace(s)) == 0 {
 | 
				
			||||||
 | 
							return s
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						fragments := strings.Split(s, ",")
 | 
				
			||||||
 | 
						return strings.TrimSpace(fragments[0])
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Get Ip Address of the client
 | 
				
			||||||
 | 
					func extractIpAddress(r *http.Request) string {
 | 
				
			||||||
 | 
						var ipAddr string
 | 
				
			||||||
 | 
						if r == nil {
 | 
				
			||||||
 | 
							return ""
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						possibleIpHeaders := []string{"CF-Connecting-IP", "X-Real-Ip", "X-Forwarded-For"}
 | 
				
			||||||
 | 
						for _, header := range possibleIpHeaders {
 | 
				
			||||||
 | 
							ipAddr = extractFirstFragment(&r.Header, header)
 | 
				
			||||||
 | 
							if len(strings.TrimSpace(ipAddr)) != 0 {
 | 
				
			||||||
 | 
								return ipAddr
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// pull ip from Request.RemoteAddr
 | 
				
			||||||
 | 
						if len(strings.TrimSpace(r.RemoteAddr)) != 0 {
 | 
				
			||||||
 | 
							index := strings.LastIndex(r.RemoteAddr, ";")
 | 
				
			||||||
 | 
							if index == -1 {
 | 
				
			||||||
 | 
								return r.RemoteAddr
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							ipAddr = r.RemoteAddr[:index]
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return ipAddr
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func canSkipExtraHeaders(r *http.Request) bool {
 | 
				
			||||||
 | 
						ref := r.Header.Get("Referer")
 | 
				
			||||||
 | 
						if len(strings.TrimSpace(ref)) == 0 {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return strings.Contains(ref, r.Host)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func shouldLogHeader(s string) bool {
 | 
				
			||||||
 | 
						if hdrsToNotLogMap == nil {
 | 
				
			||||||
 | 
							hdrsToNotLogMap = map[string]bool{}
 | 
				
			||||||
 | 
							for _, h := range hdrsToNotLog {
 | 
				
			||||||
 | 
								h = strings.ToLower(h)
 | 
				
			||||||
 | 
								hdrsToNotLogMap[h] = true
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						s = strings.ToLower(s)
 | 
				
			||||||
 | 
						return !hdrsToNotLogMap[s]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (f *LogFile) WriteLog(r *http.Request) error {
 | 
				
			||||||
 | 
						if f == nil {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						var rec = make(map[string]string)
 | 
				
			||||||
 | 
						rec["method"] = r.Method
 | 
				
			||||||
 | 
						rec["requestUri"] = r.RequestURI
 | 
				
			||||||
 | 
						rec["Host"] = r.Host
 | 
				
			||||||
 | 
						rec["ipAddr"] = extractIpAddress(r)
 | 
				
			||||||
 | 
						if !canSkipExtraHeaders(r) {
 | 
				
			||||||
 | 
							for key, val := range r.Header {
 | 
				
			||||||
 | 
								if shouldLogHeader(key) && len(val) > 0 {
 | 
				
			||||||
 | 
									rec[key] = val[0]
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						b, err := json.Marshal(rec)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						f.logger.Println(string(b))
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
		Reference in New Issue