// Default handler func handler(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) // Load db on first request. var err error err = nil startOnce.Do(func() { err = start(c) }) if err != nil { startOnce = sync.Once{} c.Criticalf("unable to load db:" + err.Error()) } if UpdateAt == nil { loadWait.Wait() } if UpdateAt.Before(time.Now()) && !updating { updating = true update(c) updating = false } var mac string var hw *oui.HardwareAddr // Prepare the response and queue sending the result. res := &Response{} defer func() { var j []byte var err error j, err = res.MarshalJSON() if err != nil { c.Errorf(err.Error()) } w.Write(j) }() // Set headers w.Header().Set("Cache-Control", "public, max-age=86400") // 86400 = 24*60*60 w.Header().Set("Access-Control-Allow-Origin", "*") w.Header().Set("Content-Type", "application/json") w.Header().Set("Expires", UpdateAt.Format(http.TimeFormat)) w.Header().Set("Last-Modified", db.Generated().Format(http.TimeFormat)) mac = r.URL.Query().Get("mac") if mac == "" { mac = strings.Trim(r.URL.Path, "/") } hw, err = oui.ParseMac(mac) if err != nil { res.Error = err.Error() + ". Usage 'http://" + appengine.DefaultVersionHostname(c) + "/AB-CD-EF' (dashes can be colons or omitted)." w.WriteHeader(http.StatusBadRequest) return } entry, err := db.LookUp(*hw) if err != nil { if err == oui.ErrNotFound { res.Error = "not found in db" w.WriteHeader(http.StatusNotFound) return } w.WriteHeader(http.StatusInternalServerError) res.Error = err.Error() return } res.Data = entry }
func main() { flag.Parse() runtime.GOMAXPROCS(*threads) var cron *cronexpr.Expression if *update != "" { cron = cronexpr.MustParse(*update) } var db oui.DynamicDB url := "" fileName := "" var err error if strings.HasPrefix(*ouiFile, "http") { url = *ouiFile if url == "http" { url = "http://standards-oui.ieee.org/oui.txt" } log.Println("Downloading new Db from: " + url) db, err = oui.OpenHttp(url) if err != nil { log.Fatalf("Error downloading:%s", err.Error()) } } else { fileName = *ouiFile log.Println("Opening database from: " + fileName) db, err = oui.OpenFile(fileName) if err != nil { log.Fatalf("Error updating file:%s", err.Error()) } } log.Printf("Database generated at %s\n", db.Generated().Local().String()) // Start updater if needed. if cron != nil { go func() { for { // Sleep until next update next := cron.Next(time.Now()) log.Println("Next update: " + next.String()) time.Sleep(next.Sub(time.Now())) if url != "" { log.Println("Updating db from: " + url) err := oui.UpdateHttp(db, url) if err != nil { log.Printf("Error downloading update:%s", err.Error()) } else { log.Println("Updated Successfully") } } else { log.Println("Updating db with file: " + fileName) err := oui.UpdateFile(db, fileName) if err != nil { log.Printf("Error loading update:%s", err.Error()) } else { log.Println("Updated Successfully") } } } }() } // We dereference this to avoid a pretty big penalty under heavy load. prettyL := *pretty http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { var mac string var hw *oui.HardwareAddr // Prepare the response and queue sending the result. res := &Response{} defer func() { var j []byte var err error if prettyL { j, err = json.MarshalIndent(res, "", " ") } else { j, err = res.MarshalJSON() } if err != nil { log.Fatal(err) } w.Write(j) }() // Set headers if *originPolicy != "" { w.Header().Set("Access-Control-Allow-Origin", *originPolicy) } w.Header().Set("Content-Type", "application/json") w.Header().Set("Last-Modified", db.Generated().Format(http.TimeFormat)) // Find Mac mac = req.URL.Query().Get("mac") if mac == "" { mac = strings.Trim(req.URL.Path, "/") } hw, err := oui.ParseMac(mac) if err != nil { res.Error = err.Error() w.WriteHeader(http.StatusBadRequest) return } entry, err := db.LookUp(*hw) if err != nil { if err == oui.ErrNotFound { res.Error = "not found in db" w.WriteHeader(http.StatusNotFound) return } w.WriteHeader(http.StatusInternalServerError) res.Error = err.Error() return } res.Data = entry }) log.Println("Listening on " + *listen) log.Fatal(http.ListenAndServe(*listen, nil)) }