package main import ( "fmt" "net" "net/http" "strings" "go.wit.com/lib/protobuf/forgepb" "go.wit.com/lib/protobuf/gitpb" "go.wit.com/lib/protobuf/httppb" "go.wit.com/log" ) // remove '?' part and trailing '/' func cleanURL(url string) string { url = "/" + strings.Trim(url, "/") return url } func getIpSimple(r *http.Request) string { host, _, err := net.SplitHostPort(r.RemoteAddr) if err != nil { log.Printf("could not split host port: %v", err) return r.RemoteAddr // Fallback } return host } // getClientIP inspects the request for common headers to find the true client IP. func getClientIP(r *http.Request) string { // Caddy sets the X-Forwarded-For header. if forwardedFor := r.Header.Get("X-Forwarded-For"); forwardedFor != "" { // The header can be a comma-separated list of IPs. The first one is the original client. ips := strings.Split(forwardedFor, ",") return strings.TrimSpace(ips[0]) } // Fallback to RemoteAddr if the header is not present. host, _, err := net.SplitHostPort(r.RemoteAddr) if err != nil { return r.RemoteAddr } return host } func whoSent(r *http.Request) string { return log.Sprintf("%s\t%s", getClientIP(r), r.Header.Get("hostname")) } func logReqPB(pb *httppb.HttpRequest) { log.Info("LOG: httppb.HttpRequest START:") for i, line := range pb.Log { log.Infof("%d, URL:%s LINE: %s\n", int(i), pb.URL, line) } log.Info("LOG: httppb.HttpRequest END") } func okHandler(w http.ResponseWriter, r *http.Request) { reqPB, err := httppb.ReqToPB(r) reqPB.Log = append(reqPB.Log, fmt.Sprintf("START: Got %d bytes from the client", len(reqPB.ClientData))) if err != nil { reqPB.Log = append(reqPB.Log, fmt.Sprintf("httppb err %v", err)) } who := whoSent(r) route := reqPB.Route parts := strings.Split(route, "?") requrl := parts[0] if route == "/" { w.Header().Set("Content-Type", "text") fmt.Fprintf(w, "go.wit.com/apps/utils/forged Version: %s\n", argv.Version()) fmt.Fprintf(w, "\n") return } reqPB.Log = append(reqPB.Log, log.Sprintf("forged REQUEST URL=%s", requrl)) if strings.HasPrefix(route, "/repos/") { pb := gitpb.NewRepos() if err := pb.Unmarshal(reqPB.ClientData); err == nil { reqPB.Log = append(reqPB.Log, log.Sprintf("Repos Unmarshal() len=%d", pb.Len())) } else { reqPB.Log = append(reqPB.Log, log.Sprintf("Repos Unmarshal() err=%v", err)) } result := gitpb.NewRepos() switch route { case "/repos/check": result = addRequest(pb, reqPB) reqPB.Log = append(reqPB.Log, log.Sprintf("repos check result.Len()=%d pb.Len()=%d\n", result.Len(), pb.Len())) case "/repos/pull": result = pullRequest(pb, reqPB) case "/repos/add": result = addRequest(pb, reqPB) default: reqPB.Log = append(reqPB.Log, log.Sprintf("repos check result.Len()=%d pb.Len()=%d\n", result.Len(), pb.Len())) log.Info("repos", route, "unknown") } if err := result.SendReply(w, reqPB); err != nil { reqPB.Log = append(reqPB.Log, log.Sprintf("Oh well, Send to client failed. err=%v", err)) } // todo: logReq(reqPB) logReqPB(reqPB) return } if strings.HasPrefix(route, "/patches/") { pb := forgepb.NewPatches() if err := pb.Unmarshal(reqPB.ClientData); err == nil { reqPB.Log = append(reqPB.Log, log.Sprintf("Patches Unmarshal() len=%d", pb.Len())) } else { reqPB.Log = append(reqPB.Log, log.Sprintf("Patches Unmarshal() err=%v", err)) } result := forgepb.NewPatches() switch route { case "/patches/new": result = addNewPatches(pb, reqPB) reqPB.Log = append(reqPB.Log, log.Sprintf("addNewPatches() pb.Len()=%d result.Len()=%d\n", pb.Len(), result.Len())) case "/patches/applied": reqPB.Log = append(reqPB.Log, log.Sprintf("not really anything needs to be done on applied patches?")) case "/patches/merged": reqPB.Log = append(reqPB.Log, log.Sprintf("a maintainer has merged these patches")) result = handleMergedPatches(pb, reqPB) // result = handleAppliedPatches(pb, reqPB) case "/patches/get": result = sendPendingPatches(pb, reqPB) default: result = addNewPatches(pb, reqPB) } if err := result.SendReply(w, reqPB); err != nil { reqPB.Log = append(reqPB.Log, log.Sprintf("Oh well, Send to client failed. err=%v", err)) } me.forge.SavePatchsets() // todo: logReq(reqPB) logReqPB(reqPB) return } if strings.HasPrefix(route, "/patchsets/") { pb, err := makePatchsetsPB(reqPB) if err != nil { reqPB.Log = append(reqPB.Log, log.Sprintf("%v", err)) } result := forgepb.NewPatchsets() switch route { case "/patches/get": result = sendPendingPatchsets(pb, reqPB) default: result = sendPendingPatchsets(pb, reqPB) } if err := result.SendReply(w, reqPB); err != nil { log.Info("Oh well, Send to client failed. err =", err) } log.Info("Send to client seems to have worked. log:", reqPB.Log) me.forge.SavePatchsets() // todo: logReq(reqPB) logReqPB(reqPB) return } logReqPB(reqPB) // used for uptime monitor checking if route == "/uptime" { writeFile(w, "uptime.html") return } /* if route == "/lookup" { log.Info("doing lookup len(reqPB.Body) =", len(reqPB.Body)) found, err := lookupRepos(reqPB.Body) if err != nil { return } found.SendPB(w) return } */ /* if strings.HasPrefix(route, "/patches/") { pb, err := forgepb.GetPatchesFromHttp(reqPB) if err != nil { log.Info("error converting to patches PB") return } handlePatches(w, pb) return } */ /* if route == "/patchset" { if err := savePatchset(w, reqPB.Body); err != nil { log.Warn("forged /patchset error", err) return } if err := me.forge.SavePatchsets(); err != nil { log.Warn("savePatchsets() failed", err) return } return } if route == "/lookup" { log.Info("doing lookup len(reqPB.Body) =", len(reqPB.Body)) found, err := lookupRepos(reqPB.Body) if err != nil { return } found.SendPB(w) return } if route == "/update" { log.Info("doing update len(reqPB.Body) =", len(reqPB.Body)) found, err := updateRepos(reqPB.Body) if err != nil { return } found.SendPB(w) return } */ /* if route == "/GetPatchsets" || route == "/patchsets/get" { data, err := me.forge.Patchsets.Marshal() if err != nil { log.Info("patchsets.Marshal() to wire failed", err) return } start := time.Now() log.Info("going to w.Write(data) with len", len(data)) w.Write(data) age := shell.FormatDuration(time.Since(start)) log.Printf("Done with xfer in (%s). happy hacking!\n", age) return } if route == "/patchsetget" { filename := r.URL.Query().Get("filename") getPatchset(w, filename) return } */ if route == "/goReference.svg" { w.Header().Set("Content-Type", "image/svg+xml") writeFile(w, "goReference.svg") return } if route == "/skeleton.v2.css" { writeFile(w, "skeleton.v2.css") return } if route == "/favicon.ico" { writeFile(w, "ipv6.png") return } log.Warn("BAD URL =", requrl, "from", who) badurl(w, r.URL.String()) } func writeFile(w http.ResponseWriter, filename string) { // fmt.Fprintln(w, "GOT TEST?") fullname := "resources/" + filename pfile, err := resources.ReadFile(fullname) if err != nil { log.Println("ERROR:", err) // w.Write(pfile) return } var repohtml string repohtml = string(pfile) fmt.Fprintln(w, repohtml) // log.Println("writeFile() found internal file:", filename) } func badurl(w http.ResponseWriter, badurl string) { fmt.Fprintln(w, "") fmt.Fprintln(w, "") fmt.Fprintln(w, "
") fmt.Fprintln(w, " ") fmt.Fprintln(w, " ") fmt.Fprintln(w, " ") fmt.Fprintln(w, " IPv4 IS NOT SUPPORTED