func handleSearch(w http.ResponseWriter, req *http.Request) { var ( ctx context.Context cancel context.CancelFunc ) timeout, err := time.ParseDuration(req.FormValue("timeout")) if err == nil { ctx, cancel = context.WithTimeout(context.Background(), timeout) } else { ctx, cancel = context.WithCancel(context.Background()) } defer cancel() query := req.FormValue("q") if query == "" { http.Error(w, "no query", http.StatusBadRequest) return } userIP, err := userip.FromRequest(req) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } ctx = userip.NewContext(ctx, userIP) start := time.Now() results, err := google.Search(ctx, query) elapsed := time.Since(start) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } if err := resultsTemplate.Execute(w, struct { Results google.Results Timeout, Elapsed time.Duration }{ Results: results, Timeout: timeout, Elapsed: elapsed, }); err != nil { log.Print(err) return } }
// handleSearch handles URLs like /search?q=golang&timeout=1s by forwarding the // query to google.Search. If the query param includes timeout, the search is // canceled after that duration elapses. func handleSearch(w http.ResponseWriter, req *http.Request) { // ctx is the Context for this handler. Calling cancel closes the // ctx.Done channel, which is the cancellation signal for requests // started by this handler. var ( ctx context.Context cancel context.CancelFunc ) timeout, err := time.ParseDuration(req.FormValue("timeout")) if err == nil { // The request has a timeout, so create a context that is // canceled automatically when the timeout expires. ctx, cancel = context.WithTimeout(context.Background(), timeout) } else { ctx, cancel = context.WithCancel(context.Background()) } defer cancel() // Cancel ctx as soon as handleSearch returns. // Check the search query. query := req.FormValue("q") if query == "" { http.Error(w, "no query", http.StatusBadRequest) return } // Store the user IP in ctx for use by code in other packages. userIP, err := userip.FromRequest(req) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } ctx = userip.NewContext(ctx, userIP) // Run the Google search and print the results. start := time.Now() results, err := google.Search(ctx, query) elapsed := time.Since(start) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } if err := resultsTemplate.Execute(w, struct { Results google.Results Timeout, Elapsed time.Duration }{ Results: results, Timeout: timeout, Elapsed: elapsed, }); err != nil { log.Print(err) return } }
// Handle HTTP Request func handleEvent(w http.ResponseWriter, req *http.Request) { log.Println("Handle event") userIP, err := userip.FromRequest(req) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } // check if IP is requesting too frequently if ipBlocker(userIP.String()) { http.Error(w, "too many request from "+userIP.String(), http.StatusBadRequest) return } else { ipStore[userIP.String()] = time.Now() } requrl, _ := url.QueryUnescape(req.FormValue("uri")) parsedURI, _ := url.Parse(requrl) event := EventStruct{ Id: req.FormValue("id"), Event: req.FormValue("event"), IP: userIP.String(), URI: requrl, Host: parsedURI.Host, Path: parsedURI.Path, Query: parsedURI.RawQuery, UserAgent: req.UserAgent(), Timestamp: time.Now(), Action: req.FormValue("action"), } if event.Id == "" || event.Event == "" { http.Error(w, "no query", http.StatusBadRequest) return } // write back to the user, thus the HTTP(s) request // doesn't block anything at client-side w.Header().Set("Access-Control-Allow-Origin", "*") w.Write(nil) // save Event to all our cool backends / services saveEvent(event) }