func ExecuteMiddlewareRemotely(middleware string, pair models.RequestResponsePair) (models.RequestResponsePair, error) { pairViewBytes, err := json.Marshal(pair.ConvertToRequestResponsePairView()) req, err := http.NewRequest("POST", middleware, bytes.NewBuffer(pairViewBytes)) if err != nil { log.WithFields(log.Fields{ "error": err.Error(), }).Error("Error when building request to remote middleware") return pair, err } resp, err := http.DefaultClient.Do(req) if err != nil { log.WithFields(log.Fields{ "error": err.Error(), }).Error("Error when communicating with remote middleware") return pair, err } if resp.StatusCode != 200 { log.Error("Remote middleware did not process payload") return pair, errors.New("Error when communicating with remote middleware") } returnedPairViewBytes, err := ioutil.ReadAll(resp.Body) if err != nil { log.WithFields(log.Fields{ "error": err.Error(), }).Error("Error when process response from remote middleware") return pair, err } var newPairView views.RequestResponsePairView err = json.Unmarshal(returnedPairViewBytes, &newPairView) if err != nil { log.WithFields(log.Fields{ "error": err.Error(), }).Error("Error when trying to serialize response from remote middleware") return pair, err } return models.NewRequestResponsePairFromRequestResponsePairView(newPairView), nil }
// ExecuteMiddleware - takes command (middleware string) and payload, which is passed to middleware func ExecuteMiddlewareLocally(middlewares string, pair models.RequestResponsePair) (models.RequestResponsePair, error) { mws := strings.Split(middlewares, "|") var cmdList []*exec.Cmd for _, v := range mws { commands := strings.Split(strings.TrimSpace(v), " ") cmd := exec.Command(commands[0], commands[1:]...) cmdList = append(cmdList, cmd) } // getting payload pairViewBytes, err := json.Marshal(pair.ConvertToRequestResponsePairView()) if log.GetLevel() == log.DebugLevel { log.WithFields(log.Fields{ "middlewares": mws, "count": len(mws), "payload": string(pairViewBytes), }).Debug("preparing to modify payload") } if err != nil { log.WithFields(log.Fields{ "error": err.Error(), }).Error("Failed to marshal json") return pair, err } // cmdList[0].Stdin = bytes.NewReader(pairViewBytes) // Run the pipeline mwOutput, stderr, err := Pipeline(cmdList...) // middleware failed to execute if err != nil { if len(stderr) > 0 { log.WithFields(log.Fields{ "sdtderr": string(stderr), "error": err.Error(), }).Error("Middleware error") } else { log.WithFields(log.Fields{ "error": err.Error(), }).Error("Middleware error") } return pair, err } // log stderr, middleware executed successfully if len(stderr) > 0 { log.WithFields(log.Fields{ "sdtderr": string(stderr), }).Info("Information from middleware") } if len(mwOutput) > 0 { var newPairView views.RequestResponsePairView err = json.Unmarshal(mwOutput, &newPairView) if err != nil { log.WithFields(log.Fields{ "mwOutput": string(mwOutput), "error": err.Error(), }).Error("Failed to unmarshal JSON from middleware") } else { if log.GetLevel() == log.DebugLevel { log.WithFields(log.Fields{ "middlewares": middlewares, "count": len(middlewares), "payload": string(mwOutput), }).Debug("payload after modifications") } // payload unmarshalled into RequestResponsePair struct, returning it return models.NewRequestResponsePairFromRequestResponsePairView(newPairView), nil } } else { log.WithFields(log.Fields{ "mwOutput": string(mwOutput), }).Warn("No response from middleware.") } return pair, nil }
// ManualAddHandler - manually add new request/responses, using a form func (d *Hoverfly) ManualAddHandler(w http.ResponseWriter, req *http.Request, next http.HandlerFunc) { err := req.ParseForm() if err != nil { log.WithFields(log.Fields{ "error": err.Error(), }).Error("Got error while parsing form") } // request details destination := req.PostFormValue("inputDestination") method := req.PostFormValue("inputMethod") path := req.PostFormValue("inputPath") query := req.PostFormValue("inputQuery") reqBody := req.PostFormValue("inputRequestBody") preq := models.RequestDetails{ Destination: destination, Method: method, Path: path, Query: query, Body: reqBody} // response respStatusCode := req.PostFormValue("inputResponseStatusCode") respBody := req.PostFormValue("inputResponseBody") contentType := req.PostFormValue("inputContentType") headers := make(map[string][]string) // getting content type if contentType == "xml" { headers["Content-Type"] = []string{"application/xml"} } else if contentType == "json" { headers["Content-Type"] = []string{"application/json"} } else { headers["Content-Type"] = []string{"text/html"} } sc, _ := strconv.Atoi(respStatusCode) presp := models.ResponseDetails{ Status: sc, Headers: headers, Body: respBody, } log.WithFields(log.Fields{ "respBody": respBody, "contentType": contentType, }).Info("manually adding request/response") p := models.RequestResponsePair{Request: preq, Response: presp} var pairViews []views.RequestResponsePairView pairViews = append(pairViews, *p.ConvertToRequestResponsePairView()) err = d.ImportRequestResponsePairViews(pairViews) w.Header().Set("Content-Type", "application/json") var response messageResponse if err != nil { response.Message = fmt.Sprintf("Got error: %s", err.Error()) w.WriteHeader(400) } else { // redirecting to home response.Message = "Record added successfuly" w.WriteHeader(201) } b, err := response.Encode() if err != nil { // failed to read response body log.WithFields(log.Fields{ "error": err.Error(), }).Error("Could not encode response body!") http.Error(w, "Failed to encode response", 500) return } w.Write(b) }
// ExecuteMiddleware - takes command (middleware string) and payload, which is passed to middleware func (this Middleware) executeMiddlewareLocally(pair models.RequestResponsePair) (models.RequestResponsePair, error) { var commandAndArgs []string if this.Binary == "" { commandAndArgs = strings.Split(strings.TrimSpace(this.FullCommand), " ") } else { commandAndArgs = []string{this.Binary, this.Script.Name()} } middlewareCommand := exec.Command(commandAndArgs[0], commandAndArgs[1:]...) // getting payload pairViewBytes, err := json.Marshal(pair.ConvertToRequestResponsePairView()) if err != nil { log.WithFields(log.Fields{ "error": err.Error(), }).Error("Failed to marshal json") return pair, err } if log.GetLevel() == log.DebugLevel { log.WithFields(log.Fields{ "middleware": this.FullCommand, "stdin": string(pairViewBytes), }).Debug("preparing to modify payload") } var stdout bytes.Buffer var stderr bytes.Buffer // Redirect standard streams middlewareCommand.Stdin = bytes.NewReader(pairViewBytes) middlewareCommand.Stdout = &stdout middlewareCommand.Stderr = &stderr if err := middlewareCommand.Start(); err != nil { log.WithFields(log.Fields{ "sdtdout": string(stdout.Bytes()), "sdtderr": string(stderr.Bytes()), "error": err.Error(), }).Error("Middleware failed to start") return pair, err } if err := middlewareCommand.Wait(); err != nil { log.WithFields(log.Fields{ "sdtdout": string(stdout.Bytes()), "sdtderr": string(stderr.Bytes()), "error": err.Error(), }).Error("Middleware failed to stop successfully") return pair, err } // log stderr, middleware executed successfully if len(stderr.Bytes()) > 0 { log.WithFields(log.Fields{ "sdtderr": string(stderr.Bytes()), }).Info("Information from middleware") } if len(stdout.Bytes()) > 0 { var newPairView v2.RequestResponsePairView err = json.Unmarshal(stdout.Bytes(), &newPairView) if err != nil { log.WithFields(log.Fields{ "stdout": string(stdout.Bytes()), "error": err.Error(), }).Error("Failed to unmarshal JSON from middleware") } else { if log.GetLevel() == log.DebugLevel { log.WithFields(log.Fields{ "middleware": this.FullCommand, "payload": string(stdout.Bytes()), }).Debug("payload after modifications") } // payload unmarshalled into RequestResponsePair struct, returning it return models.NewRequestResponsePairFromRequestResponsePairView(newPairView), nil } } else { log.WithFields(log.Fields{ "stdout": string(stdout.Bytes()), }).Warn("No response from middleware.") } return pair, nil }