Пример #1
0
func (s *server) ServeAPISearch(ctx context.Context, w http.ResponseWriter, r *http.Request) {
	backendName := r.URL.Query().Get(":backend")
	var backend *Backend
	if backendName != "" {
		backend = s.bk[backendName]
		if backend == nil {
			writeError(ctx, w, 400, "bad_backend",
				fmt.Sprintf("Unknown backend: %s", backendName))
			return
		}
	} else {
		for _, backend = range s.bk {
			break
		}
	}

	q, err := extractQuery(ctx, r)

	if err != nil {
		writeError(ctx, w, 400, "bad_query", err.Error())
		return
	}

	if q.Line == "" {
		writeError(ctx, w, 400, "bad_query",
			"You must specify a regex to match")
		return
	}

	var reply *api.ReplySearch

	for tries := 0; tries < MaxRetries; tries++ {
		reply, err = s.doSearch(ctx, backend, &q)
		if err == nil {
			break
		}
		if err == ErrTimedOut {
			break
		}
		if _, ok := err.(client.QueryError); ok {
			break
		}
		log.Printf(ctx, "error querying try=%d err=%q", tries, err)
	}

	if err != nil {
		log.Printf(ctx, "error in search err=%s", err)
		writeQueryError(ctx, w, err)
		return
	}

	log.Printf(ctx,
		"responding success results=%d why=%s stats=%s",
		len(reply.Results),
		reply.Info.ExitReason,
		asJSON{reply.Info})

	replyJSON(ctx, w, 200, reply)
}
Пример #2
0
func (s *server) doSearch(ctx context.Context, backend *Backend, q *client.Query) (*api.ReplySearch, error) {
	var cl client.Client
	var search client.Search
	var err error

	select {
	case cl = <-backend.Clients:
	case <-ctx.Done():
		return nil, ErrTimedOut
	}
	defer backend.CheckIn(cl)

	search, err = cl.Query(q)
	if err != nil {
		log.Printf(ctx, "error talking to backend err=%s", err)
		return nil, err
	}

	reply := &api.ReplySearch{Results: make([]*client.Result, 0)}

	for r := range search.Results() {
		reply.Results = append(reply.Results, r)
	}

	reply.Info, err = search.Close()
	if err != nil {
		return nil, err
	}
	return reply, nil
}
Пример #3
0
func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	ctx := context.Background()
	ctx, cancel := context.WithTimeout(ctx, RequestTimeout)
	defer cancel()
	ctx = reqid.NewContext(ctx, reqid.New())
	log.Printf(ctx, "http request: remote=%q method=%q url=%q",
		r.RemoteAddr, r.Method, r.URL)
	h(ctx, w, r)
}
Пример #4
0
func replyJSON(ctx context.Context, w http.ResponseWriter, status int, obj interface{}) {
	w.WriteHeader(status)
	enc := json.NewEncoder(w)
	if err := enc.Encode(obj); err != nil {
		log.Printf(ctx, "writing http response, data=%s err=%q",
			asJSON{obj},
			err.Error())
	}
}
Пример #5
0
func extractQuery(ctx context.Context, r *http.Request) client.Query {
	params := r.URL.Query()
	var query client.Query
	if q, ok := params["q"]; ok {
		query = ParseQuery(q[0])
		log.Printf(ctx, "parsing query q=%q out=%s", q[0], asJSON{query})
	}
	if line, ok := params["line"]; ok {
		query.Line = line[0]
	}
	if file, ok := params["file"]; ok {
		query.File = file[0]
	}
	if repo, ok := params["repo"]; ok {
		query.Repo = repo[0]
	}
	if fc, ok := params["fold_case"]; ok && fc[0] != "" {
		query.FoldCase = true
	}
	return query
}
Пример #6
0
func writeError(ctx context.Context, w http.ResponseWriter, status int, code, message string) {
	log.Printf(ctx, "error status=%d code=%s message=%q",
		status, code, message)
	replyJSON(ctx, w, status, &api.ReplyError{Err: api.InnerError{Code: code, Message: message}})
}