func()

in plugins/listeners/httplistener/httplistener.go [96:219]


func (h *apiHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	verb := strings.TrimLeft(r.URL.Path, "/")
	var (
		httpStatus = http.StatusOK
		resp       api.Response
		errMsg     string
		err        error
	)
	// This is only used by status, stop, and reply. Ignored for other
	// methods. If not set by the client, this is an empty string.
	if r.Method != "POST" {
		h.reply(w, http.StatusBadRequest, "Only POST requests are supported")
		return
	}
	jobIDStr := r.PostFormValue("jobID")
	jobDesc := r.PostFormValue("jobDesc")
	requestor := api.EventRequestor(r.PostFormValue("requestor"))

	ctx := h.ctx.WithTags(xcontext.Fields{
		"http_verb":      verb,
		"http_requestor": requestor,
	}).WithField("http_job_id", jobIDStr)

	switch verb {
	case "start":
		if jobDesc == "" {
			httpStatus = http.StatusBadRequest
			errMsg = "Missing job description"
			break
		}
		if resp, err = h.api.Start(ctx, requestor, jobDesc); err != nil {
			httpStatus = http.StatusBadRequest
			errMsg = fmt.Sprintf("Start failed: %v", err)
		}
	case "status":
		jobID, err := strToJobID(jobIDStr)
		if err != nil {
			httpStatus = http.StatusBadRequest
			errMsg = fmt.Sprintf("Status failed: %v", err)
			break
		}
		if resp, err = h.api.Status(ctx, requestor, jobID); err != nil {
			httpStatus = http.StatusBadRequest
			errMsg = fmt.Sprintf("Status failed: %v", err)
		}
	case "stop":
		jobID, err := strToJobID(jobIDStr)
		if err != nil {
			httpStatus = http.StatusBadRequest
			errMsg = fmt.Sprintf("Stop failed: %v", err)
			break
		}
		if resp, err = h.api.Stop(ctx, requestor, jobID); err != nil {
			httpStatus = http.StatusBadRequest
			errMsg = fmt.Sprintf("Stop failed: %v", err)
		}
	case "retry":
		jobID, err := strToJobID(jobIDStr)
		if err != nil {
			httpStatus = http.StatusBadRequest
			errMsg = fmt.Sprintf("Retry failed: %v", err)
			break
		}
		if resp, err = h.api.Retry(ctx, requestor, jobID); err != nil {
			httpStatus = http.StatusBadRequest
			errMsg = fmt.Sprintf("Retry failed: %v", err)
		}
	case "list":
		var fields []storage.JobQueryField
		if statesStr := r.PostFormValue("states"); len(statesStr) > 0 {
			var states []job.State
			for _, sts := range strings.Split(statesStr, ",") {
				st, err := job.EventNameToJobState(event.Name(sts))
				if err != nil {
					httpStatus = http.StatusBadRequest
					errMsg = fmt.Sprintf("List failed: %v", err)
					break
				}
				states = append(states, st)
			}
			fields = append(fields, storage.QueryJobStates(states...))
		}
		if tagsStr := r.PostFormValue("tags"); len(tagsStr) > 0 {
			fields = append(fields, storage.QueryJobTags(strings.Split(tagsStr, ",")...))
		}
		jobQuery, err := storage.BuildJobQuery(fields...)
		if err != nil {
			httpStatus = http.StatusBadRequest
			errMsg = fmt.Sprintf("Invalid query: %v", err)
			break
		}
		if resp, err = h.api.List(ctx, requestor, jobQuery); err != nil {
			httpStatus = http.StatusBadRequest
			errMsg = fmt.Sprintf("List failed: %v", err)
		}
	case "version":
		resp = h.api.Version()
	default:
		errMsg = fmt.Sprintf("unknown verb: %s", verb)
		httpStatus = http.StatusBadRequest
	}
	if httpStatus != http.StatusOK {
		errResp := HTTPAPIError{
			Msg: errMsg,
		}
		msg, err := json.Marshal(errResp)
		if err != nil {
			panic(fmt.Sprintf("cannot marshal HTTPAPIError: %v", err))
		}
		h.reply(w, httpStatus, string(msg))
		return
	}
	apiResp := NewHTTPAPIResponse(&resp)

	buffer := &bytes.Buffer{}
	encoder := json.NewEncoder(buffer)
	encoder.SetEscapeHTML(false)
	err = encoder.Encode(apiResp)
	if err != nil {
		panic(fmt.Sprintf("cannot marshal HTTPAPIResponse: %v", err))
	}
	msg := buffer.Bytes()
	h.reply(w, httpStatus, string(msg))
}