diff --git a/cmd/dlv/main.go b/cmd/dlv/main.go index 7702f230..11f57ce5 100644 --- a/cmd/dlv/main.go +++ b/cmd/dlv/main.go @@ -13,7 +13,6 @@ import ( sys "golang.org/x/sys/unix" "github.com/derekparker/delve/service" - "github.com/derekparker/delve/service/rest" "github.com/derekparker/delve/service/rpc" "github.com/derekparker/delve/terminal" ) @@ -40,13 +39,11 @@ func main() { var addr string var logEnabled bool var headless bool - var http bool flag.BoolVar(&printv, "version", false, "Print version number and exit.") flag.StringVar(&addr, "addr", "localhost:0", "Debugging server listen address.") flag.BoolVar(&logEnabled, "log", false, "Enable debugging server logging.") flag.BoolVar(&headless, "headless", false, "Run in headless mode.") - flag.BoolVar(&http, "http", false, "Start HTTP server instead of RPC.") flag.Parse() if flag.NFlag() == 0 && len(flag.Args()) == 0 { @@ -64,12 +61,12 @@ func main() { os.Exit(0) } - status := run(addr, logEnabled, headless, http) + status := run(addr, logEnabled, headless) fmt.Println("[Hope I was of service hunting your bug!]") os.Exit(status) } -func run(addr string, logEnabled, headless, http bool) int { +func run(addr string, logEnabled, headless bool) int { // Collect launch arguments var processArgs []string var attachPid int @@ -127,30 +124,18 @@ func run(addr string, logEnabled, headless, http bool) int { // Create and start a debugger server var server service.Server - if http { - server = rest.NewServer(&service.Config{ - Listener: listener, - ProcessArgs: processArgs, - AttachPid: attachPid, - }, logEnabled) - } else { - server = rpc.NewServer(&service.Config{ - Listener: listener, - ProcessArgs: processArgs, - AttachPid: attachPid, - }, logEnabled) - } + server = rpc.NewServer(&service.Config{ + Listener: listener, + ProcessArgs: processArgs, + AttachPid: attachPid, + }, logEnabled) go server.Run() var status int if !headless { // Create and start a terminal var client service.Client - if http { - client = rest.NewClient(listener.Addr().String()) - } else { - client = rpc.NewClient(listener.Addr().String()) - } + client = rpc.NewClient(listener.Addr().String()) term := terminal.New(client) err, status = term.Run() } else { diff --git a/service/rest/client.go b/service/rest/client.go deleted file mode 100644 index f5667234..00000000 --- a/service/rest/client.go +++ /dev/null @@ -1,410 +0,0 @@ -package rest - -import ( - "bytes" - "encoding/json" - "fmt" - "io/ioutil" - "net/http" - "net/url" - "strconv" - - "github.com/derekparker/delve/service" - "github.com/derekparker/delve/service/api" -) - -// Client is a REST service.Client. -type RESTClient struct { - addr string - httpClient *http.Client -} - -// ClientError is an error from the debugger. -type ClientError struct { - // Message is the specific error from the debugger. - Message string - // Status is the HTTP error from the debugger request. - Status string -} - -func (e *ClientError) Error() string { return e.Message } - -// Ensure the implementation satisfies the interface. -var _ service.Client = &RESTClient{} - -// NewClient creates a new RESTClient. -func NewClient(addr string) *RESTClient { - return &RESTClient{ - addr: addr, - httpClient: &http.Client{}, - } -} - -func (c *RESTClient) Detach(killProcess bool) error { - params := [][]string{{"kill", strconv.FormatBool(killProcess)}} - err := c.doGET("/detach", nil, params...) - if err != nil { - return err - } - return nil -} - -func (c *RESTClient) GetState() (*api.DebuggerState, error) { - var state *api.DebuggerState - err := c.doGET("/state", &state) - if err != nil { - return nil, err - } - return state, nil -} - -func (c *RESTClient) Continue() (*api.DebuggerState, error) { - var state *api.DebuggerState - err := c.doPOST("/command", &api.DebuggerCommand{Name: api.Continue}, &state) - if err != nil { - return nil, err - } - return state, nil -} - -func (c *RESTClient) Next() (*api.DebuggerState, error) { - var state *api.DebuggerState - err := c.doPOST("/command", &api.DebuggerCommand{Name: api.Next}, &state) - if err != nil { - return nil, err - } - return state, nil -} - -func (c *RESTClient) Step() (*api.DebuggerState, error) { - var state *api.DebuggerState - err := c.doPOST("/command", &api.DebuggerCommand{Name: api.Step}, &state) - if err != nil { - return nil, err - } - return state, nil -} - -func (c *RESTClient) SwitchThread(threadID int) (*api.DebuggerState, error) { - var state *api.DebuggerState - err := c.doPOST("/command", &api.DebuggerCommand{ - Name: api.SwitchThread, - ThreadID: threadID, - }, &state) - if err != nil { - return nil, err - } - return state, nil -} - -func (c *RESTClient) Halt() (*api.DebuggerState, error) { - var state *api.DebuggerState - err := c.doPOST("/command", &api.DebuggerCommand{Name: api.Halt}, &state) - if err != nil { - return nil, err - } - return state, nil -} - -func (c *RESTClient) GetBreakpoint(id int) (*api.Breakpoint, error) { - var breakPoint *api.Breakpoint - err := c.doGET(fmt.Sprintf("/breakpoints/%d", id), &breakPoint) - if err != nil { - return nil, err - } - return breakPoint, nil -} - -func (c *RESTClient) CreateBreakpoint(breakPoint *api.Breakpoint) (*api.Breakpoint, error) { - var newBreakpoint *api.Breakpoint - err := c.doPOST("/breakpoints", breakPoint, &newBreakpoint) - if err != nil { - return nil, err - } - return newBreakpoint, nil -} - -func (c *RESTClient) ListBreakpoints() ([]*api.Breakpoint, error) { - var breakPoints []*api.Breakpoint - err := c.doGET("/breakpoints", &breakPoints) - if err != nil { - return nil, err - } - return breakPoints, nil -} - -func (c *RESTClient) ClearBreakpoint(id int) (*api.Breakpoint, error) { - var breakPoint *api.Breakpoint - err := c.doDELETE(fmt.Sprintf("/breakpoints/%d", id), &breakPoint) - if err != nil { - return nil, err - } - return breakPoint, nil -} - -func (c *RESTClient) ListThreads() ([]*api.Thread, error) { - var threads []*api.Thread - err := c.doGET("/threads", &threads) - if err != nil { - return nil, err - } - return threads, nil -} - -func (c *RESTClient) GetThread(id int) (*api.Thread, error) { - var thread *api.Thread - err := c.doGET(fmt.Sprintf("/threads/%d", id), &thread) - if err != nil { - return nil, err - } - return thread, nil -} - -func (c *RESTClient) EvalVariable(symbol string) (*api.Variable, error) { - var v *api.Variable - err := c.doGET(fmt.Sprintf("/eval/%s", symbol), &v) - if err != nil { - return nil, err - } - return v, nil -} - -func (c *RESTClient) EvalVariableFor(threadID int, symbol string) (*api.Variable, error) { - var v *api.Variable - err := c.doGET(fmt.Sprintf("/threads/%d/eval/%s", threadID, symbol), &v) - if err != nil { - return nil, err - } - return v, nil -} - -func (c *RESTClient) ListSources(filter string) ([]string, error) { - params := [][]string{} - if len(filter) > 0 { - params = append(params, []string{"filter", filter}) - } - var sources []string - err := c.doGET("/sources", &sources, params...) - if err != nil { - return nil, err - } - return sources, nil -} - -func (c *RESTClient) ListFunctions(filter string) ([]string, error) { - params := [][]string{} - if len(filter) > 0 { - params = append(params, []string{"filter", filter}) - } - var funcs []string - err := c.doGET("/functions", &funcs, params...) - if err != nil { - return nil, err - } - return funcs, nil -} - -func (c *RESTClient) ListPackageVariables(filter string) ([]api.Variable, error) { - params := [][]string{} - if len(filter) > 0 { - params = append(params, []string{"filter", filter}) - } - var vars []api.Variable - err := c.doGET(fmt.Sprintf("/vars"), &vars, params...) - if err != nil { - return nil, err - } - return vars, nil -} - -func (c *RESTClient) ListPackageVariablesFor(threadID int, filter string) ([]api.Variable, error) { - params := [][]string{} - if len(filter) > 0 { - params = append(params, []string{"filter", filter}) - } - var vars []api.Variable - err := c.doGET(fmt.Sprintf("/threads/%d/vars", threadID), &vars, params...) - if err != nil { - return nil, err - } - return vars, nil -} - -func (c *RESTClient) ListLocalVariables() ([]api.Variable, error) { - var vars []api.Variable - err := c.doGET("/localvars", &vars) - if err != nil { - return nil, err - } - return vars, nil -} - -func (c *RESTClient) ListRegisters() (string, error) { - var regs string - err := c.doGET("/regs", ®s) - if err != nil { - return "", err - } - return regs, nil -} - -func (c *RESTClient) ListFunctionArgs() ([]api.Variable, error) { - var vars []api.Variable - err := c.doGET("/args", &vars) - if err != nil { - return nil, err - } - return vars, nil -} - -func (c *RESTClient) ListGoroutines() ([]*api.Goroutine, error) { - var goroutines []*api.Goroutine - err := c.doGET("/goroutines", &goroutines) - if err != nil { - return nil, err - } - return goroutines, nil -} - -func (c *RESTClient) Stacktrace(goroutineId, depth int) ([]*api.Location, error) { - var locations []*api.Location - err := c.doGET(fmt.Sprintf("/goroutines/%d/trace?depth=%d", goroutineId, depth), &locations) - if err != nil { - return nil, err - } - return locations, nil -} - -// TODO: how do we use http.Client with a UNIX socket URI? -func (c *RESTClient) url(path string) string { - return fmt.Sprintf("http://%s%s", c.addr, path) -} - -// doGET performs an HTTP GET to path and stores the resulting API object in -// obj. Query parameters are passed as an array of 2-element string arrays -// representing key-value pairs. -func (c *RESTClient) doGET(path string, obj interface{}, params ...[]string) error { - url, err := url.Parse(c.url(path)) - if err != nil { - return err - } - - // Add any supplied query parameters to the URL - q := url.Query() - for _, p := range params { - q.Set(p[0], p[1]) - } - url.RawQuery = q.Encode() - - // Create the request - req, err := http.NewRequest("GET", url.String(), nil) - if err != nil { - return err - } - req.Header.Set("Accept", "application/json") - - // Execute the request - resp, err := c.httpClient.Do(req) - if err != nil { - return err - } - defer resp.Body.Close() - - // Extract error text and return - if resp.StatusCode != http.StatusOK { - contents, _ := ioutil.ReadAll(resp.Body) - return &ClientError{Message: string(contents), Status: resp.Status} - } - - // Decode result object - decoder := json.NewDecoder(resp.Body) - err = decoder.Decode(&obj) - if err != nil { - return err - } - return nil -} - -// doPOST performs an HTTP POST to path, sending 'out' as the body and storing -// the resulting API object to 'in'. -func (c *RESTClient) doPOST(path string, out interface{}, in interface{}) error { - jsonString, err := json.Marshal(out) - if err != nil { - return err - } - - req, err := http.NewRequest("POST", c.url(path), bytes.NewBuffer(jsonString)) - req.Header.Set("Content-Type", "application/json") - - resp, err := c.httpClient.Do(req) - if err != nil { - return err - } - defer resp.Body.Close() - - if resp.StatusCode != http.StatusCreated { - contents, _ := ioutil.ReadAll(resp.Body) - return &ClientError{Message: string(contents), Status: resp.Status} - } - - decoder := json.NewDecoder(resp.Body) - err = decoder.Decode(&in) - if err != nil { - return err - } - return nil -} - -// doDELETE performs an HTTP DELETE to path, storing the resulting API object -// to 'obj'. -func (c *RESTClient) doDELETE(path string, obj interface{}) error { - req, err := http.NewRequest("DELETE", c.url(path), nil) - - resp, err := c.httpClient.Do(req) - if err != nil { - return err - } - defer resp.Body.Close() - - if resp.StatusCode != http.StatusOK { - contents, _ := ioutil.ReadAll(resp.Body) - return &ClientError{Message: string(contents), Status: resp.Status} - } - - decoder := json.NewDecoder(resp.Body) - err = decoder.Decode(&obj) - if err != nil { - return err - } - return nil -} - -// doPUT performs an HTTP PUT to path, sending 'out' as the body and storing -// the resulting API object to 'in'. -func (c *RESTClient) doPUT(path string, out interface{}, in interface{}) error { - jsonString, err := json.Marshal(out) - if err != nil { - return err - } - - req, err := http.NewRequest("PUT", c.url(path), bytes.NewBuffer(jsonString)) - req.Header.Set("Content-Type", "application/json") - - resp, err := c.httpClient.Do(req) - if err != nil { - return err - } - defer resp.Body.Close() - - if resp.StatusCode != http.StatusOK { - contents, _ := ioutil.ReadAll(resp.Body) - return &ClientError{Message: string(contents), Status: resp.Status} - } - - decoder := json.NewDecoder(resp.Body) - err = decoder.Decode(&in) - if err != nil { - return err - } - return nil -} diff --git a/service/rest/doc.go b/service/rest/doc.go deleted file mode 100644 index 7158e8f1..00000000 --- a/service/rest/doc.go +++ /dev/null @@ -1,2 +0,0 @@ -// Package rest provides RESTful HTTP client and server implementations. -package rest diff --git a/service/rest/server.go b/service/rest/server.go deleted file mode 100644 index 1c461d9a..00000000 --- a/service/rest/server.go +++ /dev/null @@ -1,442 +0,0 @@ -package rest - -import ( - "io/ioutil" - "log" - "net" - "net/http" - "strconv" - - restful "github.com/emicklei/go-restful" - - "github.com/derekparker/delve/service" - "github.com/derekparker/delve/service/api" - "github.com/derekparker/delve/service/debugger" -) - -// RESTServer exposes a Debugger via a HTTP REST API. -type RESTServer struct { - // config is all the information necessary to start the debugger and server. - config *service.Config - // listener is used to serve HTTP. - listener net.Listener - // debugger is a debugger service. - debugger *debugger.Debugger -} - -// NewServer creates a new RESTServer. -func NewServer(config *service.Config, logEnabled bool) *RESTServer { - log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile) - if !logEnabled { - log.SetOutput(ioutil.Discard) - } - - return &RESTServer{ - config: config, - listener: config.Listener, - } -} - -// Run starts a debugger and exposes it with an HTTP server. The debugger -// itself can be stopped with the `detach` API. Run blocks until the HTTP -// server stops. -func (s *RESTServer) Run() error { - var err error - // Create and start the debugger - if s.debugger, err = debugger.New(&debugger.Config{ - ProcessArgs: s.config.ProcessArgs, - AttachPid: s.config.AttachPid, - }); err != nil { - return err - } - - // Set up the HTTP server - container := restful.NewContainer() - ws := new(restful.WebService) - ws. - Path(""). - Consumes(restful.MIME_JSON). - Produces(restful.MIME_JSON). - Route(ws.GET("/state").To(s.getState)). - Route(ws.GET("/breakpoints").To(s.listBreakpoints)). - Route(ws.GET("/breakpoints/{breakpoint-id}").To(s.getBreakpoint)). - Route(ws.POST("/breakpoints").To(s.createBreakpoint)). - Route(ws.DELETE("/breakpoints/{breakpoint-id}").To(s.clearBreakpoint)). - Route(ws.GET("/threads").To(s.listThreads)). - Route(ws.GET("/threads/{thread-id}").To(s.getThread)). - Route(ws.GET("/threads/{thread-id}/vars").To(s.listThreadPackageVars)). - Route(ws.GET("/threads/{thread-id}/eval/{symbol}").To(s.evalThreadSymbol)). - Route(ws.GET("/goroutines").To(s.listGoroutines)). - Route(ws.GET("/goroutines/{goroutine-id}/trace").To(s.stacktraceGoroutine)). - Route(ws.POST("/command").To(s.doCommand)). - Route(ws.GET("/sources").To(s.listSources)). - Route(ws.GET("/functions").To(s.listFunctions)). - Route(ws.GET("/regs").To(s.listRegisters)). - Route(ws.GET("/vars").To(s.listPackageVars)). - Route(ws.GET("/localvars").To(s.listLocalVars)). - Route(ws.GET("/args").To(s.listFunctionArgs)). - Route(ws.GET("/eval/{symbol}").To(s.evalSymbol)). - // TODO: GET might be the wrong verb for this - Route(ws.GET("/detach").To(s.detach)) - container.Add(ws) - - // Start the HTTP server - log.Printf("server listening on %s", s.listener.Addr()) - return http.Serve(s.listener, container) -} - -// Stop detaches from the debugger and waits for it to stop. -func (s *RESTServer) Stop(kill bool) error { - return s.debugger.Detach(kill) -} - -// writeError writes a simple error response. -func writeError(response *restful.Response, statusCode int, message string) { - response.AddHeader("Content-Type", "text/plain") - response.WriteErrorString(statusCode, message) -} - -// detach stops the debugger and waits for it to shut down before returning an -// OK response. Clients expect this to be a synchronous call. -func (s *RESTServer) detach(request *restful.Request, response *restful.Response) { - kill, err := strconv.ParseBool(request.QueryParameter("kill")) - if err != nil { - writeError(response, http.StatusBadRequest, "invalid kill parameter") - return - } - - err = s.Stop(kill) - if err != nil { - writeError(response, http.StatusInternalServerError, err.Error()) - return - } - - response.WriteHeader(http.StatusOK) -} - -func (s *RESTServer) getState(request *restful.Request, response *restful.Response) { - state, err := s.debugger.State() - if err != nil { - writeError(response, http.StatusInternalServerError, err.Error()) - return - } - response.WriteEntity(state) -} - -func (s *RESTServer) doCommand(request *restful.Request, response *restful.Response) { - command := new(api.DebuggerCommand) - err := request.ReadEntity(command) - if err != nil { - writeError(response, http.StatusInternalServerError, err.Error()) - return - } - - state, err := s.debugger.Command(command) - if err != nil { - writeError(response, http.StatusInternalServerError, err.Error()) - return - } - - response.WriteHeader(http.StatusCreated) - response.WriteEntity(state) -} - -func (s *RESTServer) getBreakpoint(request *restful.Request, response *restful.Response) { - id, err := strconv.Atoi(request.PathParameter("breakpoint-id")) - if err != nil { - writeError(response, http.StatusBadRequest, "invalid breakpoint id") - return - } - - found := s.debugger.FindBreakpoint(id) - if found == nil { - writeError(response, http.StatusNotFound, "breakpoint not found") - return - } - response.WriteHeader(http.StatusOK) - response.WriteEntity(found) -} - -func (s *RESTServer) stacktraceGoroutine(request *restful.Request, response *restful.Response) { - goroutineId, err := strconv.Atoi(request.PathParameter("goroutine-id")) - if err != nil { - writeError(response, http.StatusBadRequest, "invalid goroutine id") - return - } - - depth, err := strconv.Atoi(request.QueryParameter("depth")) - if err != nil { - writeError(response, http.StatusBadRequest, "invalid depth") - return - } - - locations, err := s.debugger.Stacktrace(goroutineId, depth) - if err != nil { - writeError(response, http.StatusBadRequest, err.Error()) - return - } - - response.WriteHeader(http.StatusOK) - response.WriteEntity(locations) -} - -func (s *RESTServer) listBreakpoints(request *restful.Request, response *restful.Response) { - response.WriteEntity(s.debugger.Breakpoints()) -} - -func (s *RESTServer) createBreakpoint(request *restful.Request, response *restful.Response) { - incomingBp := new(api.Breakpoint) - err := request.ReadEntity(incomingBp) - if err != nil { - writeError(response, http.StatusInternalServerError, err.Error()) - return - } - - if len(incomingBp.File) == 0 && len(incomingBp.FunctionName) == 0 { - writeError(response, http.StatusBadRequest, "no file or function name provided") - return - } - - createdbp, err := s.debugger.CreateBreakpoint(incomingBp) - - if err != nil { - writeError(response, http.StatusInternalServerError, err.Error()) - return - } - - response.WriteHeader(http.StatusCreated) - response.WriteEntity(createdbp) -} - -func (s *RESTServer) clearBreakpoint(request *restful.Request, response *restful.Response) { - id, err := strconv.Atoi(request.PathParameter("breakpoint-id")) - if err != nil { - writeError(response, http.StatusBadRequest, "invalid breakpoint id") - return - } - - found := s.debugger.FindBreakpoint(id) - if found == nil { - writeError(response, http.StatusNotFound, "breakpoint not found") - return - } - - deleted, err := s.debugger.ClearBreakpoint(found) - if err != nil { - writeError(response, http.StatusInternalServerError, err.Error()) - return - } - response.WriteHeader(http.StatusOK) - response.WriteEntity(deleted) -} - -func (s *RESTServer) listThreads(request *restful.Request, response *restful.Response) { - response.WriteEntity(s.debugger.Threads()) -} - -func (s *RESTServer) getThread(request *restful.Request, response *restful.Response) { - id, err := strconv.Atoi(request.PathParameter("thread-id")) - if err != nil { - writeError(response, http.StatusBadRequest, "invalid thread id") - return - } - - found := s.debugger.FindThread(id) - if found == nil { - writeError(response, http.StatusNotFound, "thread not found") - return - } - response.WriteHeader(http.StatusOK) - response.WriteEntity(found) -} - -func (s *RESTServer) listPackageVars(request *restful.Request, response *restful.Response) { - state, err := s.debugger.State() - if err != nil { - writeError(response, http.StatusInternalServerError, err.Error()) - return - } - - current := state.CurrentThread - if current == nil { - writeError(response, http.StatusBadRequest, "no current thread") - return - } - - filter := request.QueryParameter("filter") - vars, err := s.debugger.PackageVariables(current.ID, filter) - - if err != nil { - writeError(response, http.StatusInternalServerError, err.Error()) - return - } - - response.WriteHeader(http.StatusOK) - response.WriteEntity(vars) -} - -func (s *RESTServer) listThreadPackageVars(request *restful.Request, response *restful.Response) { - id, err := strconv.Atoi(request.PathParameter("thread-id")) - if err != nil { - writeError(response, http.StatusBadRequest, "invalid thread id") - return - } - - if found := s.debugger.FindThread(id); found == nil { - writeError(response, http.StatusNotFound, "thread not found") - return - } - - filter := request.QueryParameter("filter") - vars, err := s.debugger.PackageVariables(id, filter) - - if err != nil { - writeError(response, http.StatusInternalServerError, err.Error()) - return - } - - response.WriteHeader(http.StatusOK) - response.WriteEntity(vars) -} - -func (s *RESTServer) listRegisters(request *restful.Request, response *restful.Response) { - state, err := s.debugger.State() - if err != nil { - writeError(response, http.StatusInternalServerError, err.Error()) - return - } - - regs, err := s.debugger.Registers(state.CurrentThread.ID) - if err != nil { - writeError(response, http.StatusInternalServerError, err.Error()) - return - } - - response.WriteHeader(http.StatusOK) - response.WriteEntity(regs) -} - -func (s *RESTServer) listLocalVars(request *restful.Request, response *restful.Response) { - state, err := s.debugger.State() - if err != nil { - writeError(response, http.StatusInternalServerError, err.Error()) - return - } - - vars, err := s.debugger.LocalVariables(state.CurrentThread.ID) - if err != nil { - writeError(response, http.StatusInternalServerError, err.Error()) - return - } - - response.WriteHeader(http.StatusOK) - response.WriteEntity(vars) -} - -func (s *RESTServer) listFunctionArgs(request *restful.Request, response *restful.Response) { - state, err := s.debugger.State() - if err != nil { - writeError(response, http.StatusInternalServerError, err.Error()) - return - } - - vars, err := s.debugger.FunctionArguments(state.CurrentThread.ID) - if err != nil { - writeError(response, http.StatusInternalServerError, err.Error()) - return - } - - response.WriteHeader(http.StatusOK) - response.WriteEntity(vars) -} - -func (s *RESTServer) evalSymbol(request *restful.Request, response *restful.Response) { - symbol := request.PathParameter("symbol") - if len(symbol) == 0 { - writeError(response, http.StatusBadRequest, "invalid symbol") - return - } - - state, err := s.debugger.State() - if err != nil { - writeError(response, http.StatusInternalServerError, err.Error()) - return - } - - current := state.CurrentThread - if current == nil { - writeError(response, http.StatusBadRequest, "no current thread") - return - } - - v, err := s.debugger.EvalVariableInThread(current.ID, symbol) - if err != nil { - writeError(response, http.StatusInternalServerError, err.Error()) - return - } - - response.WriteHeader(http.StatusOK) - response.WriteEntity(v) -} - -func (s *RESTServer) evalThreadSymbol(request *restful.Request, response *restful.Response) { - id, err := strconv.Atoi(request.PathParameter("thread-id")) - if err != nil { - writeError(response, http.StatusBadRequest, "invalid thread id") - return - } - - if found := s.debugger.FindThread(id); found == nil { - writeError(response, http.StatusNotFound, "thread not found") - return - } - - symbol := request.PathParameter("symbol") - if len(symbol) == 0 { - writeError(response, http.StatusNotFound, "invalid symbol") - return - } - - v, err := s.debugger.EvalVariableInThread(id, symbol) - if err != nil { - writeError(response, http.StatusInternalServerError, err.Error()) - return - } - - response.WriteHeader(http.StatusOK) - response.WriteEntity(v) -} - -func (s *RESTServer) listSources(request *restful.Request, response *restful.Response) { - filter := request.QueryParameter("filter") - sources, err := s.debugger.Sources(filter) - if err != nil { - writeError(response, http.StatusInternalServerError, err.Error()) - return - } - - response.WriteHeader(http.StatusOK) - response.WriteEntity(sources) -} - -func (s *RESTServer) listFunctions(request *restful.Request, response *restful.Response) { - filter := request.QueryParameter("filter") - funcs, err := s.debugger.Functions(filter) - if err != nil { - writeError(response, http.StatusInternalServerError, err.Error()) - return - } - - response.WriteHeader(http.StatusOK) - response.WriteEntity(funcs) -} - -func (s *RESTServer) listGoroutines(request *restful.Request, response *restful.Response) { - gs, err := s.debugger.Goroutines() - if err != nil { - writeError(response, http.StatusInternalServerError, err.Error()) - return - } - response.WriteHeader(http.StatusOK) - response.WriteEntity(gs) -} diff --git a/service/test/integration_test.go b/service/test/integration_test.go index 203d320f..4dcb165d 100644 --- a/service/test/integration_test.go +++ b/service/test/integration_test.go @@ -1,7 +1,6 @@ package servicetest import ( - "fmt" "net" "os" "path/filepath" @@ -13,7 +12,6 @@ import ( "github.com/derekparker/delve/service" "github.com/derekparker/delve/service/api" - "github.com/derekparker/delve/service/rest" "github.com/derekparker/delve/service/rpc" ) @@ -31,32 +29,14 @@ func withTestClient(name string, t *testing.T, fn func(c service.Client)) { t.Fatalf("couldn't start listener: %s\n", err) } defer listener.Close() - // Test REST service - restService := func() { - fmt.Println("---- RUNNING TEST WITH REST CLIENT ----") - server := rest.NewServer(&service.Config{ - Listener: listener, - ProcessArgs: []string{protest.BuildFixture(name).Path}, - }, false) - go server.Run() - client := rest.NewClient(listener.Addr().String()) - defer client.Detach(true) - fn(client) - } - // Test RPC service - rpcService := func() { - fmt.Println("---- RUNNING TEST WITH RPC CLIENT ----") - server := rpc.NewServer(&service.Config{ - Listener: listener, - ProcessArgs: []string{protest.BuildFixture(name).Path}, - }, false) - go server.Run() - client := rpc.NewClient(listener.Addr().String()) - defer client.Detach(true) - fn(client) - } - rpcService() - restService() + server := rpc.NewServer(&service.Config{ + Listener: listener, + ProcessArgs: []string{protest.BuildFixture(name).Path}, + }, false) + go server.Run() + client := rpc.NewClient(listener.Addr().String()) + defer client.Detach(true) + fn(client) } func TestClientServer_exit(t *testing.T) {