diff --git a/examples/demo-with-py-plugin/.debugtalk_gen.py b/examples/demo-with-py-plugin/.debugtalk_gen.py index dbf8aed9..50f50e5f 100644 --- a/examples/demo-with-py-plugin/.debugtalk_gen.py +++ b/examples/demo-with-py-plugin/.debugtalk_gen.py @@ -20,4 +20,4 @@ if __name__ == "__main__": funppy.register("concatenate", concatenate) funppy.register("setup_hook_example", setup_hook_example) funppy.register("teardown_hook_example", teardown_hook_example) - funppy.serve() \ No newline at end of file + funppy.serve() diff --git a/hrp/internal/boomer/data/data.go b/hrp/internal/boomer/data/data.go index c583755f..9e0a21ea 100644 --- a/hrp/internal/boomer/data/data.go +++ b/hrp/internal/boomer/data/data.go @@ -15,30 +15,48 @@ * */ -// Package data provides convenience routines to access files in the data -// directory. package data import ( + "embed" + "os" "path/filepath" - "runtime" + + "github.com/httprunner/httprunner/v4/hrp/internal/builtin" ) -// basepath is the root directory of this package. -var basepath string +// hrpPath is .hrp directory under the user directory. +var hrpPath string + +//go:embed x509/* +var x509Dir embed.FS func init() { - _, currentFile, _, _ := runtime.Caller(0) - basepath = filepath.Dir(currentFile) -} - -// Path returns the absolute path the given relative file or directory path, -// relative to the google.golang.org/grpc/examples/data directory in the -// user's GOPATH. If rel is already absolute, it is returned unmodified. -func Path(rel string) string { - if filepath.IsAbs(rel) { - return rel + home, err := os.UserHomeDir() + if err != nil { + return } + hrpPath = filepath.Join(home, ".hrp") + _ = builtin.EnsureFolderExists(filepath.Join(hrpPath, "x509")) - return filepath.Join(basepath, rel) +} + +// Path returns the absolute path the given relative file or directory path +func Path(rel string) (destPath string) { + destPath = rel + if !filepath.IsAbs(rel) { + destPath = filepath.Join(hrpPath, rel) + } + if !builtin.IsFilePathExists(destPath) { + content, err := x509Dir.ReadFile(rel) + if err != nil { + return + } + + err = os.WriteFile(destPath, content, 0o644) + if err != nil { + return + } + } + return } diff --git a/hrp/server.go b/hrp/server.go index a42d9a33..cb1c07b9 100644 --- a/hrp/server.go +++ b/hrp/server.go @@ -2,6 +2,7 @@ package hrp import ( "context" + "errors" "fmt" "io/ioutil" "log" @@ -52,17 +53,13 @@ func parseBody(r *http.Request) (data map[string]interface{}, err error) { return data, nil } -func writeResponse(w http.ResponseWriter, status int, contentType string, body []byte) { - w.Header().Set("Content-Type", contentType) +func writeJSON(w http.ResponseWriter, body []byte, status int) { + w.Header().Set("Content-Type", jsonContentType) w.Header().Set("Content-Length", fmt.Sprintf("%d", len(body))) w.WriteHeader(status) w.Write(body) } -func writeJSON(w http.ResponseWriter, body []byte, status int) { - writeResponse(w, status, jsonContentType, body) -} - type ServerCode int // server response code @@ -169,48 +166,100 @@ func (api *apiHandler) Index(w http.ResponseWriter, r *http.Request) { func (api *apiHandler) Start(w http.ResponseWriter, r *http.Request) { var resp *CommonResponseBody - data, err := parseBody(r) + var err error + defer func() { + if err != nil { + resp = &CommonResponseBody{ + ServerStatus: EnumAPIResponseServerError(err.Error()), + } + } else { + resp = &CommonResponseBody{ + ServerStatus: EnumAPIResponseSuccess, + } + } + body, _ := json.Marshal(resp) + writeJSON(w, body, http.StatusOK) + }() + // parse body + data, err := parseBody(r) + if err != nil { + return + } req := StartRequestBody{ Profile: *api.boomer.GetProfile(), } err = mapstructure.Decode(data, &req) + if err != nil { + return + } + + // recognize invalid parameters if len(req.Other) > 0 { keys := make([]string, 0, len(req.Other)) for k := range req.Other { keys = append(keys, k) } - resp = &CommonResponseBody{ - ServerStatus: EnumAPIResponseParamError(fmt.Sprintf("failed to recognize params: %v", keys)), - } - body, _ := json.Marshal(resp) - writeJSON(w, body, http.StatusOK) + err = errors.New(fmt.Sprintf("failed to recognize params: %v", keys)) return } + + // parse testcase path if req.TestCasePath == "" { - resp = &CommonResponseBody{ - ServerStatus: EnumAPIResponseParamError(fmt.Sprint("missing testcases path")), - } - body, _ := json.Marshal(resp) - writeJSON(w, body, http.StatusOK) + err = errors.New("missing testcases path") return } paths := strings.Split(req.TestCasePath, ",") + + // set testcase path api.boomer.SetTestCasesPath(paths) - if err == nil { - err = api.boomer.Start(&req.Profile) - } + + // start boomer with profile + err = api.boomer.Start(&req.Profile) +} + +func (api *apiHandler) ReBalance(w http.ResponseWriter, r *http.Request) { + var resp *CommonResponseBody + var err error + defer func() { + if err != nil { + resp = &CommonResponseBody{ + ServerStatus: EnumAPIResponseServerError(err.Error()), + } + } else { + resp = &CommonResponseBody{ + ServerStatus: EnumAPIResponseSuccess, + } + } + body, _ := json.Marshal(resp) + writeJSON(w, body, http.StatusOK) + }() + + // parse body + data, err := parseBody(r) if err != nil { - resp = &CommonResponseBody{ - ServerStatus: EnumAPIResponseServerError(err.Error()), - } - } else { - resp = &CommonResponseBody{ - ServerStatus: EnumAPIResponseSuccess, - } + return } - body, _ := json.Marshal(resp) - writeJSON(w, body, http.StatusOK) + req := RebalanceRequestBody{ + Profile: *api.boomer.GetProfile(), + } + err = mapstructure.Decode(data, &req) + if err != nil { + return + } + + // recognize invalid parameters + if len(req.Other) > 0 { + keys := make([]string, 0, len(req.Other)) + for k := range req.Other { + keys = append(keys, k) + } + err = errors.New(fmt.Sprintf("failed to recognize params: %v", keys)) + return + } + + // rebalance boomer with profile + err = api.boomer.ReBalance(&req.Profile) } func (api *apiHandler) Stop(w http.ResponseWriter, r *http.Request) { @@ -223,18 +272,23 @@ func (api *apiHandler) Stop(w http.ResponseWriter, r *http.Request) { } var resp *CommonResponseBody - err := api.boomer.Stop() - if err != nil { - resp = &CommonResponseBody{ - ServerStatus: EnumAPIResponseStopError(err.Error()), + var err error + defer func() { + if err != nil { + resp = &CommonResponseBody{ + ServerStatus: EnumAPIResponseStopError(err.Error()), + } + } else { + resp = &CommonResponseBody{ + ServerStatus: EnumAPIResponseSuccess, + } } - } else { - resp = &CommonResponseBody{ - ServerStatus: EnumAPIResponseSuccess, - } - } - body, _ := json.Marshal(resp) - writeJSON(w, body, http.StatusOK) + body, _ := json.Marshal(resp) + writeJSON(w, body, http.StatusOK) + }() + + // stop boomer + err = api.boomer.Stop() } func (api *apiHandler) Quit(w http.ResponseWriter, r *http.Request) { @@ -245,49 +299,16 @@ func (api *apiHandler) Quit(w http.ResponseWriter, r *http.Request) { data[k] = v } } - - resp := &CommonResponseBody{ - ServerStatus: EnumAPIResponseSuccess, - } - body, _ := json.Marshal(resp) - writeJSON(w, body, http.StatusOK) - api.boomer.Quit() -} - -func (api *apiHandler) ReBalance(w http.ResponseWriter, r *http.Request) { - var resp *CommonResponseBody - data, err := parseBody(r) - - req := RebalanceRequestBody{ - Profile: *api.boomer.GetProfile(), - } - err = mapstructure.Decode(data, &req) - if len(req.Other) > 0 { - keys := make([]string, 0, len(req.Other)) - for k := range req.Other { - keys = append(keys, k) - } - resp = &CommonResponseBody{ - ServerStatus: EnumAPIResponseParamError(fmt.Sprintf("failed to recognize params: %v", keys)), + defer func() { + resp := &CommonResponseBody{ + ServerStatus: EnumAPIResponseSuccess, } body, _ := json.Marshal(resp) writeJSON(w, body, http.StatusOK) - return - } - if err == nil { - err = api.boomer.ReBalance(&req.Profile) - } - if err != nil { - resp = &CommonResponseBody{ - ServerStatus: EnumAPIResponseParamError(err.Error()), - } - } else { - resp = &CommonResponseBody{ - ServerStatus: EnumAPIResponseSuccess, - } - } - body, _ := json.Marshal(resp) - writeJSON(w, body, http.StatusOK) + }() + + // quit boomer + api.boomer.Quit() } func (api *apiHandler) GetWorkersInfo(w http.ResponseWriter, r *http.Request) { @@ -305,9 +326,9 @@ func (api *apiHandler) Handler() http.Handler { mux.HandleFunc("/", methods(api.Index, "GET")) mux.HandleFunc("/start", methods(api.Start, "POST")) + mux.HandleFunc("/rebalance", methods(api.ReBalance, "POST")) mux.HandleFunc("/stop", methods(api.Stop, "GET")) mux.HandleFunc("/quit", methods(api.Quit, "GET")) - mux.HandleFunc("/rebalance", methods(api.ReBalance, "POST")) mux.HandleFunc("/workers", methods(api.GetWorkersInfo, "GET")) return mux