diff --git a/cmd/ios/tunnel.go b/cmd/ios/tunnel.go new file mode 100644 index 00000000..3bce55c9 --- /dev/null +++ b/cmd/ios/tunnel.go @@ -0,0 +1,39 @@ +package ios + +import ( + "context" + "github.com/danielpaulus/go-ios/ios" + "github.com/httprunner/httprunner/v5/internal/sdk" + "github.com/httprunner/httprunner/v5/pkg/uixt" + "github.com/rs/zerolog/log" + "github.com/spf13/cobra" + "os" + "strings" + "time" +) + +var tunnelCmd = &cobra.Command{ + Use: "tunnel", + Short: "tunnel start", + RunE: func(cmd *cobra.Command, args []string) (err error) { + startTime := time.Now() + defer func() { + sdk.SendGA4Event("hrp_ios_tunnel", map[string]interface{}{ + "args": strings.Join(args, "-"), + "success": err == nil, + "engagement_time_msec": time.Since(startTime).Milliseconds(), + }) + }() + ctx := context.TODO() + err = uixt.StartTunnel(ctx, os.TempDir(), ios.HttpApiPort(), true) + if err != nil { + log.Error().Err(err).Msg("failed to start tunnel") + } + <-ctx.Done() + return err + }, +} + +func init() { + iosRootCmd.AddCommand(tunnelCmd) +} diff --git a/internal/builtin/utils.go b/internal/builtin/utils.go index e4accadc..d29180c0 100644 --- a/internal/builtin/utils.go +++ b/internal/builtin/utils.go @@ -5,16 +5,13 @@ import ( "bytes" "context" "crypto/hmac" - "crypto/md5" "crypto/sha256" "encoding/csv" builtinJSON "encoding/json" "fmt" - "io" "math" "math/rand" "net" - "net/http" "os" "os/exec" "path/filepath" @@ -23,7 +20,6 @@ import ( "strings" "time" - "github.com/BurntSushi/locker" "github.com/pkg/errors" "github.com/rs/zerolog/log" "gopkg.in/yaml.v3" @@ -382,7 +378,7 @@ func GetCurrentDay() string { return formattedDate } -func fileExists(filepath string) bool { +func FileExists(filepath string) bool { _, err := os.Stat(filepath) if os.IsNotExist(err) { return false // 文件不存在 @@ -390,61 +386,6 @@ func fileExists(filepath string) bool { return err == nil // 文件存在,且没有其他错误 } -func DownloadFileByUrl(fileUrl string) (filePath string, err error) { - // 使用 UUID 生成唯一文件名 - cwd, err := os.Getwd() - if err != nil { - return "", err - } - hash := md5.Sum([]byte(fileUrl)) - fileName := fmt.Sprintf("%x", hash) - filePath = filepath.Join(cwd, fileName) - locker.Lock(filePath) - defer locker.Unlock(filePath) - if fileExists(filePath) { - return filePath, nil - } - - fmt.Printf("Downloading file to %s from URL %s\n", filePath, fileUrl) - - // Create an HTTP client with default settings. - client := &http.Client{} - - // Build the HTTP GET request. - req, err := http.NewRequest("GET", fileUrl, nil) - if err != nil { - return "", err - } - - // Perform the request. - resp, err := client.Do(req) - if err != nil { - return "", err - } - defer resp.Body.Close() - - // Check the HTTP status code. - if resp.StatusCode != http.StatusOK { - return "", fmt.Errorf("failed to download file: %s", resp.Status) - } - - // Create the output file. - outFile, err := os.Create(fileName) - if err != nil { - return "", err - } - defer outFile.Close() - - // Copy the response body to the file. - _, err = io.Copy(outFile, resp.Body) - if err != nil { - return "", err - } - - fmt.Printf("File downloaded successfully: %s\n", fileName) - return filePath, nil -} - func RunCommand(cmdName string, args ...string) error { cmd := exec.Command(cmdName, args...) log.Info().Str("command", cmd.String()).Msg("exec command") diff --git a/internal/config/config.go b/internal/config/config.go index 8c99e7af..6076f217 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -12,6 +12,7 @@ import ( const ( ResultsDirName = "results" + DownloadsDirName = "downloads" ScreenshotsDirName = "screenshots" ActionLogDirName = "action_log" ) @@ -20,6 +21,7 @@ var ( RootDir string ResultsDir string ResultsPath string + DownloadsPath string ScreenShotsPath string StartTime = time.Now() StartTimeStr = StartTime.Format("20060102150405") @@ -36,6 +38,7 @@ func init() { ResultsDir = filepath.Join(ResultsDirName, StartTimeStr) ResultsPath = filepath.Join(RootDir, ResultsDir) + DownloadsPath = filepath.Join(RootDir, filepath.Join(DownloadsDirName, StartTimeStr)) ScreenShotsPath = filepath.Join(ResultsPath, ScreenshotsDirName) ActionLogFilePath = filepath.Join(ResultsDir, ActionLogDirName) DeviceActionLogFilePath = "/sdcard/Android/data/io.appium.uiautomator2.server/files/hodor" diff --git a/pkg/uixt/driver.go b/pkg/uixt/driver.go index 41139d86..1e063c5b 100644 --- a/pkg/uixt/driver.go +++ b/pkg/uixt/driver.go @@ -96,3 +96,14 @@ type XTDriver struct { // cache screenshot results screenResults []*ScreenResult } + +func (dExt *XTDriver) GetIDriver() IDriver { + return dExt.IDriver +} + +type IXTDriver interface { + IDriver + GetIDriver() IDriver + GetScreenResult(opts ...option.ActionOption) (screenResult *ScreenResult, err error) + DoAction(action MobileAction) (err error) +} diff --git a/pkg/uixt/driver_ext/android_stub_driver.go b/pkg/uixt/driver_ext/android_stub_driver.go index aa1258a2..22d2e8a4 100644 --- a/pkg/uixt/driver_ext/android_stub_driver.go +++ b/pkg/uixt/driver_ext/android_stub_driver.go @@ -50,9 +50,6 @@ func NewStubAndroidDriver(dev *uixt.AndroidDevice) (*StubAndroidDriver, error) { return nil, err } - // register driver session reset handler - driver.Session.RegisterResetHandler(driver.Setup) - return driver, nil } diff --git a/pkg/uixt/driver_ext/ext.go b/pkg/uixt/driver_ext/ext.go index 28cacebb..b55a1f91 100644 --- a/pkg/uixt/driver_ext/ext.go +++ b/pkg/uixt/driver_ext/ext.go @@ -4,7 +4,6 @@ import ( "fmt" "time" - "github.com/httprunner/httprunner/v5/internal/builtin" "github.com/httprunner/httprunner/v5/pkg/uixt" "github.com/httprunner/httprunner/v5/pkg/uixt/ai" "github.com/httprunner/httprunner/v5/pkg/uixt/option" @@ -34,7 +33,7 @@ type XTDriver struct { } func (dExt *XTDriver) InstallByUrl(url string, opts ...option.InstallOption) error { - appPath, err := builtin.DownloadFileByUrl(url) + appPath, err := uixt.DownloadFileByUrl(url) if err != nil { return err } diff --git a/pkg/uixt/driver_ext/ios_stub_driver.go b/pkg/uixt/driver_ext/ios_stub_driver.go index 8738c0f6..eb8e8022 100644 --- a/pkg/uixt/driver_ext/ios_stub_driver.go +++ b/pkg/uixt/driver_ext/ios_stub_driver.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/httprunner/httprunner/v5/pkg/uixt/types" "net/url" + "os" "time" "github.com/httprunner/httprunner/v5/code" @@ -44,9 +45,6 @@ func NewStubIOSDriver(dev *uixt.IOSDevice) (*StubIOSDriver, error) { return nil, err } - // register driver session reset handler - driver.Session.RegisterResetHandler(driver.Setup) - return driver, nil } @@ -565,9 +563,12 @@ func (s *StubIOSDriver) PressButton(devBtn types.DeviceButton) error { } func (s *StubIOSDriver) ScreenShot(opts ...option.ActionOption) (*bytes.Buffer, error) { + if os.Getenv("WINGS_LOCAL") == "true" { + return s.Device.ScreenShot() + } err := s.setUpWda() if err != nil { - return s.Device.ScreenShot() + return nil, err } return s.wdaDriver.ScreenShot() } diff --git a/pkg/uixt/driver_utils.go b/pkg/uixt/driver_utils.go index d343ac6d..cab66cb9 100644 --- a/pkg/uixt/driver_utils.go +++ b/pkg/uixt/driver_utils.go @@ -1,9 +1,17 @@ package uixt import ( + "crypto/md5" "fmt" + "github.com/BurntSushi/locker" + "github.com/httprunner/httprunner/v5/internal/builtin" + "github.com/httprunner/httprunner/v5/internal/config" + "io" "math" "math/rand/v2" + "net/http" + "os" + "path/filepath" "time" "github.com/pkg/errors" @@ -259,3 +267,53 @@ func sleepStrict(startTime time.Time, strictMilliseconds int64) { Msg("sleep remaining duration time") time.Sleep(time.Duration(dur) * time.Millisecond) } + +func DownloadFileByUrl(fileUrl string) (filePath string, err error) { + hash := md5.Sum([]byte(fileUrl)) + fileName := fmt.Sprintf("%x", hash) + filePath = filepath.Join(config.DownloadsPath, fileName) + locker.Lock(filePath) + defer locker.Unlock(filePath) + if builtin.FileExists(filePath) { + return filePath, nil + } + + fmt.Printf("Downloading file to %s from URL %s\n", filePath, fileUrl) + + // Create an HTTP client with default settings. + client := &http.Client{} + + // Build the HTTP GET request. + req, err := http.NewRequest("GET", fileUrl, nil) + if err != nil { + return "", err + } + + // Perform the request. + resp, err := client.Do(req) + if err != nil { + return "", err + } + defer resp.Body.Close() + + // Check the HTTP status code. + if resp.StatusCode != http.StatusOK { + return "", fmt.Errorf("failed to download file: %s", resp.Status) + } + + // Create the output file. + outFile, err := os.Create(fileName) + if err != nil { + return "", err + } + defer outFile.Close() + + // Copy the response body to the file. + _, err = io.Copy(outFile, resp.Body) + if err != nil { + return "", err + } + + fmt.Printf("File downloaded successfully: %s\n", fileName) + return filePath, nil +} diff --git a/pkg/uixt/ios_device.go b/pkg/uixt/ios_device.go index ec452b04..c3ed4968 100644 --- a/pkg/uixt/ios_device.go +++ b/pkg/uixt/ios_device.go @@ -28,7 +28,7 @@ import ( "github.com/httprunner/httprunner/v5/pkg/uixt/types" ) -func StartTunnel(recordsPath string, tunnelInfoPort int, userspaceTUN bool) (err error) { +func StartTunnel(ctx context.Context, recordsPath string, tunnelInfoPort int, userspaceTUN bool) (err error) { pm, err := tunnel.NewPairRecordManager(recordsPath) if err != nil { return err @@ -38,7 +38,7 @@ func StartTunnel(recordsPath string, tunnelInfoPort int, userspaceTUN bool) (err ticker := time.NewTicker(1 * time.Second) defer ticker.Stop() for { - err := tm.UpdateTunnels(context.Background()) + err := tm.UpdateTunnels(ctx) if err != nil { log.Error().Err(err).Msg("failed to update tunnels") } @@ -62,7 +62,7 @@ func RebootTunnel() (err error) { if tunnelManager != nil { _ = tunnelManager.Close() } - return StartTunnel(os.TempDir(), ios.HttpApiPort(), true) + return StartTunnel(context.Background(), os.TempDir(), ios.HttpApiPort(), true) } func NewIOSDevice(opts ...option.IOSDeviceOption) (device *IOSDevice, err error) { diff --git a/server/app.go b/server/app.go index edc6c564..ef77580e 100644 --- a/server/app.go +++ b/server/app.go @@ -5,8 +5,8 @@ import ( "github.com/httprunner/httprunner/v5/pkg/uixt" ) -func foregroundAppHandler(c *gin.Context) { - driver, err := GetDriver(c) +func (r *Router) foregroundAppHandler(c *gin.Context) { + driver, err := r.GetDriver(c) if err != nil { return } @@ -18,7 +18,7 @@ func foregroundAppHandler(c *gin.Context) { RenderSuccess(c, appInfo) } -func appInfoHandler(c *gin.Context) { +func (r *Router) appInfoHandler(c *gin.Context) { var appInfoReq AppInfoRequest if err := c.ShouldBindQuery(&appInfoReq); err != nil { RenderErrorValidateRequest(c, err) @@ -47,18 +47,18 @@ func appInfoHandler(c *gin.Context) { } } -func clearAppHandler(c *gin.Context) { +func (r *Router) clearAppHandler(c *gin.Context) { var appClearReq AppClearRequest if err := c.ShouldBindJSON(&appClearReq); err != nil { RenderErrorValidateRequest(c, err) return } - driver, err := GetDriver(c) + driver, err := r.GetDriver(c) if err != nil { return } - err = driver.IDriver.(*uixt.ADBDriver).AppClear(appClearReq.PackageName) + err = driver.GetIDriver().(*uixt.ADBDriver).AppClear(appClearReq.PackageName) if err != nil { RenderError(c, err) return @@ -66,13 +66,13 @@ func clearAppHandler(c *gin.Context) { RenderSuccess(c, true) } -func launchAppHandler(c *gin.Context) { +func (r *Router) launchAppHandler(c *gin.Context) { var appLaunchReq AppLaunchRequest if err := c.ShouldBindJSON(&appLaunchReq); err != nil { RenderErrorValidateRequest(c, err) return } - driver, err := GetDriver(c) + driver, err := r.GetDriver(c) if err != nil { return } @@ -84,13 +84,13 @@ func launchAppHandler(c *gin.Context) { RenderSuccess(c, true) } -func terminalAppHandler(c *gin.Context) { +func (r *Router) terminalAppHandler(c *gin.Context) { var appTerminalReq AppTerminalRequest if err := c.ShouldBindJSON(&appTerminalReq); err != nil { RenderErrorValidateRequest(c, err) return } - driver, err := GetDriver(c) + driver, err := r.GetDriver(c) if err != nil { return } @@ -102,13 +102,13 @@ func terminalAppHandler(c *gin.Context) { RenderSuccess(c, true) } -func uninstallAppHandler(c *gin.Context) { +func (r *Router) uninstallAppHandler(c *gin.Context) { var appUninstallReq AppUninstallRequest if err := c.ShouldBindJSON(&appUninstallReq); err != nil { RenderErrorValidateRequest(c, err) return } - driver, err := GetDriver(c) + driver, err := r.GetDriver(c) if err != nil { return } diff --git a/server/context.go b/server/context.go index 40bee258..4cf82f96 100644 --- a/server/context.go +++ b/server/context.go @@ -14,7 +14,7 @@ import ( "github.com/httprunner/httprunner/v5/pkg/uixt/option" ) -func GetDriver(c *gin.Context) (driverExt *uixt.XTDriver, err error) { +func (r *Router) GetDriver(c *gin.Context) (driverExt uixt.IXTDriver, err error) { deviceObj, exists := c.Get("device") var device uixt.IDevice var driver uixt.IDriver diff --git a/server/device.go b/server/device.go index 33fde5c9..267cbb98 100644 --- a/server/device.go +++ b/server/device.go @@ -7,14 +7,13 @@ import ( "github.com/Masterminds/semver" "github.com/danielpaulus/go-ios/ios" "github.com/gin-gonic/gin" - "github.com/httprunner/httprunner/v5/internal/builtin" "github.com/httprunner/httprunner/v5/pkg/gadb" "github.com/httprunner/httprunner/v5/pkg/uixt" "github.com/httprunner/httprunner/v5/pkg/uixt/option" "github.com/rs/zerolog/log" ) -func listDeviceHandler(c *gin.Context) { +func (r *Router) listDeviceHandler(c *gin.Context) { var deviceList []interface{} client, err := gadb.NewClient() if err == nil { @@ -88,17 +87,17 @@ func listDeviceHandler(c *gin.Context) { RenderSuccess(c, deviceList) } -func pushImageHandler(c *gin.Context) { +func (r *Router) pushImageHandler(c *gin.Context) { var pushMediaReq PushMediaRequest if err := c.ShouldBindJSON(&pushMediaReq); err != nil { RenderErrorValidateRequest(c, err) return } - driver, err := GetDriver(c) + driver, err := r.GetDriver(c) if err != nil { return } - imagePath, err := builtin.DownloadFileByUrl(pushMediaReq.ImageUrl) + imagePath, err := uixt.DownloadFileByUrl(pushMediaReq.ImageUrl) if path.Ext(imagePath) == "" { err = os.Rename(imagePath, imagePath+".png") if err != nil { @@ -122,8 +121,8 @@ func pushImageHandler(c *gin.Context) { RenderSuccess(c, true) } -func clearImageHandler(c *gin.Context) { - driver, err := GetDriver(c) +func (r *Router) clearImageHandler(c *gin.Context) { + driver, err := r.GetDriver(c) if err != nil { return } @@ -135,6 +134,6 @@ func clearImageHandler(c *gin.Context) { RenderSuccess(c, true) } -func videoHandler(c *gin.Context) { +func (r *Router) videoHandler(c *gin.Context) { RenderSuccess(c, "") } diff --git a/server/ext/app.go b/server/ext/app.go index 32880b8c..7ddc2728 100644 --- a/server/ext/app.go +++ b/server/ext/app.go @@ -2,26 +2,26 @@ package server_ext import ( "fmt" + "github.com/httprunner/httprunner/v5/pkg/uixt/driver_ext" "os" "github.com/gin-gonic/gin" - "github.com/httprunner/httprunner/v5/internal/builtin" "github.com/httprunner/httprunner/v5/pkg/uixt" "github.com/httprunner/httprunner/v5/server" ) -func installAppHandler(c *gin.Context) { +func (r *RouterExt) installAppHandler(c *gin.Context) { var appInstallReq AppInstallRequest if err := c.ShouldBindJSON(&appInstallReq); err != nil { server.RenderErrorValidateRequest(c, err) return } - driver, err := GetDriver(c) + driver, err := r.GetDriver(c) if err != nil { return } - err = driver.InstallByUrl(appInstallReq.AppUrl) + err = driver.(*driver_ext.XTDriver).InstallByUrl(appInstallReq.AppUrl) if err != nil { server.RenderError(c, err) return @@ -32,7 +32,7 @@ func installAppHandler(c *gin.Context) { server.RenderSuccess(c, true) return } - localMappingPath, err := builtin.DownloadFileByUrl(appInstallReq.MappingUrl) + localMappingPath, err := uixt.DownloadFileByUrl(appInstallReq.MappingUrl) if err != nil { server.RenderError(c, err) } @@ -45,7 +45,7 @@ func installAppHandler(c *gin.Context) { server.RenderError(c, err) return } - localResourceMappingPath, err := builtin.DownloadFileByUrl( + localResourceMappingPath, err := uixt.DownloadFileByUrl( appInstallReq.ResourceMappingUrl) if err != nil { server.RenderError(c, err) diff --git a/server/ext/context.go b/server/ext/context.go index 10e26ea4..c539687e 100644 --- a/server/ext/context.go +++ b/server/ext/context.go @@ -11,7 +11,7 @@ import ( "github.com/httprunner/httprunner/v5/server" ) -func GetDriver(c *gin.Context) (driverExt *driver_ext.XTDriver, err error) { +func (r *RouterExt) GetDriver(c *gin.Context) (driverExt uixt.IXTDriver, err error) { platform := c.Param("platform") deviceObj, exists := c.Get("device") var device uixt.IDevice diff --git a/server/ext/handler.go b/server/ext/handler.go index 09b932dd..51697cfa 100644 --- a/server/ext/handler.go +++ b/server/ext/handler.go @@ -8,18 +8,18 @@ import ( "github.com/httprunner/httprunner/v5/server" ) -func loginHandler(c *gin.Context) { +func (r *RouterExt) loginHandler(c *gin.Context) { var loginReq LoginRequest if err := c.ShouldBindJSON(&loginReq); err != nil { server.RenderErrorValidateRequest(c, err) return } - driver, err := GetDriver(c) + driver, err := r.GetDriver(c) if err != nil { return } - info, err := driver.IDriver.(driver_ext.IStubDriver). + info, err := driver.GetIDriver().(driver_ext.IStubDriver). LoginNoneUI(loginReq.PackageName, loginReq.PhoneNumber, loginReq.Captcha, loginReq.Password) if err != nil { @@ -29,18 +29,18 @@ func loginHandler(c *gin.Context) { server.RenderSuccess(c, info) } -func logoutHandler(c *gin.Context) { +func (r *RouterExt) logoutHandler(c *gin.Context) { var logoutReq LogoutRequest if err := c.ShouldBindJSON(&logoutReq); err != nil { server.RenderErrorValidateRequest(c, err) return } - driver, err := GetDriver(c) + driver, err := r.GetDriver(c) if err != nil { return } - err = driver.IDriver.(driver_ext.IStubDriver). + err = driver.GetIDriver().(driver_ext.IStubDriver). LogoutNoneUI(logoutReq.PackageName) if err != nil { server.RenderError(c, err) @@ -49,8 +49,8 @@ func logoutHandler(c *gin.Context) { server.RenderSuccess(c, true) } -func sourceHandler(c *gin.Context) { - driver, err := GetDriver(c) +func (r *RouterExt) sourceHandler(c *gin.Context) { + driver, err := r.GetDriver(c) if err != nil { return } diff --git a/server/ext/main.go b/server/ext/main.go index 11de3e8c..91b398c5 100644 --- a/server/ext/main.go +++ b/server/ext/main.go @@ -4,13 +4,24 @@ import ( "github.com/httprunner/httprunner/v5/server" ) -func NewExtRouter() *server.Router { - router := server.NewRouter() - apiV1PlatformSerial := router.Group("/api/v1").Group("/:platform").Group("/:serial") +type RouterExt struct { + *server.Router +} - apiV1PlatformSerial.GET("/stub/source", sourceHandler) - apiV1PlatformSerial.POST("/stub/login", loginHandler) - apiV1PlatformSerial.POST("/stub/logout", logoutHandler) - apiV1PlatformSerial.POST("/app/install", installAppHandler) +func NewExtRouter() *RouterExt { + router := &RouterExt{ + Router: server.NewRouter(), + } + router.Setup() return router } + +func (r *RouterExt) Setup() { + r.Router.Init() + apiV1PlatformSerial := r.Group("/api/v1").Group("/:platform").Group("/:serial") + + apiV1PlatformSerial.GET("/stub/source", r.sourceHandler) + apiV1PlatformSerial.POST("/stub/login", r.loginHandler) + apiV1PlatformSerial.POST("/stub/logout", r.logoutHandler) + apiV1PlatformSerial.POST("/app/install", r.installAppHandler) +} diff --git a/server/key.go b/server/key.go index e982c087..5f82ee9a 100644 --- a/server/key.go +++ b/server/key.go @@ -6,8 +6,8 @@ import ( "github.com/httprunner/httprunner/v5/pkg/uixt" ) -func unlockHandler(c *gin.Context) { - driver, err := GetDriver(c) +func (r *Router) unlockHandler(c *gin.Context) { + driver, err := r.GetDriver(c) if err != nil { return } @@ -19,8 +19,8 @@ func unlockHandler(c *gin.Context) { RenderSuccess(c, true) } -func homeHandler(c *gin.Context) { - driver, err := GetDriver(c) +func (r *Router) homeHandler(c *gin.Context) { + driver, err := r.GetDriver(c) if err != nil { return } @@ -32,7 +32,7 @@ func homeHandler(c *gin.Context) { RenderSuccess(c, true) } -func backspaceHandler(c *gin.Context) { +func (r *Router) backspaceHandler(c *gin.Context) { var deleteReq DeleteRequest if err := c.ShouldBindJSON(&deleteReq); err != nil { RenderErrorValidateRequest(c, err) @@ -41,7 +41,7 @@ func backspaceHandler(c *gin.Context) { if deleteReq.Count == 0 { deleteReq.Count = 20 } - driver, err := GetDriver(c) + driver, err := r.GetDriver(c) if err != nil { return } @@ -53,18 +53,18 @@ func backspaceHandler(c *gin.Context) { RenderSuccess(c, true) } -func keycodeHandler(c *gin.Context) { +func (r *Router) keycodeHandler(c *gin.Context) { var keycodeReq KeycodeRequest if err := c.ShouldBindJSON(&keycodeReq); err != nil { RenderErrorValidateRequest(c, err) return } - driver, err := GetDriver(c) + driver, err := r.GetDriver(c) if err != nil { return } // TODO FIXME - err = driver.IDriver.(*uixt.ADBDriver). + err = driver.GetIDriver().(*uixt.ADBDriver). PressKeyCode(uixt.KeyCode(keycodeReq.Keycode), uixt.KMEmpty) if err != nil { RenderError(c, err) diff --git a/server/main.go b/server/main.go index 3a125ce9..32a0605f 100644 --- a/server/main.go +++ b/server/main.go @@ -20,47 +20,51 @@ type Router struct { *gin.Engine } +type IRouter interface { + GetDriver(c *gin.Context) (driver uixt.IXTDriver, err error) +} + func (r *Router) Init() { r.Engine = gin.Default() r.Engine.Use(teardown()) - r.Engine.GET("/ping", pingHandler) - r.Engine.GET("/", pingHandler) - r.Engine.POST("/", pingHandler) - r.Engine.GET("/api/v1/devices", listDeviceHandler) + r.Engine.GET("/ping", r.pingHandler) + r.Engine.GET("/", r.pingHandler) + r.Engine.POST("/", r.pingHandler) + r.Engine.GET("/api/v1/devices", r.listDeviceHandler) apiV1PlatformSerial := r.Group("/api/v1").Group("/:platform").Group("/:serial") // UI operations - apiV1PlatformSerial.POST("/ui/tap", tapHandler) - apiV1PlatformSerial.POST("/ui/double_tap", doubleTapHandler) - apiV1PlatformSerial.POST("/ui/drag", dragHandler) - apiV1PlatformSerial.POST("/ui/input", inputHandler) - apiV1PlatformSerial.POST("/ui/home", homeHandler) + apiV1PlatformSerial.POST("/ui/tap", r.tapHandler) + apiV1PlatformSerial.POST("/ui/double_tap", r.doubleTapHandler) + apiV1PlatformSerial.POST("/ui/drag", r.dragHandler) + apiV1PlatformSerial.POST("/ui/input", r.inputHandler) + apiV1PlatformSerial.POST("/ui/home", r.homeHandler) // Key operations - apiV1PlatformSerial.POST("/key/unlock", unlockHandler) - apiV1PlatformSerial.POST("/key/home", homeHandler) - apiV1PlatformSerial.POST("/key/backspace", backspaceHandler) - apiV1PlatformSerial.POST("/key", keycodeHandler) + apiV1PlatformSerial.POST("/key/unlock", r.unlockHandler) + apiV1PlatformSerial.POST("/key/home", r.homeHandler) + apiV1PlatformSerial.POST("/key/backspace", r.backspaceHandler) + apiV1PlatformSerial.POST("/key", r.keycodeHandler) // APP operations - apiV1PlatformSerial.GET("/app/foreground", foregroundAppHandler) - apiV1PlatformSerial.GET("/app/appInfo", appInfoHandler) - apiV1PlatformSerial.POST("/app/clear", clearAppHandler) - apiV1PlatformSerial.POST("/app/launch", launchAppHandler) - apiV1PlatformSerial.POST("/app/terminal", terminalAppHandler) - apiV1PlatformSerial.POST("/app/uninstall", uninstallAppHandler) + apiV1PlatformSerial.GET("/app/foreground", r.foregroundAppHandler) + apiV1PlatformSerial.GET("/app/appInfo", r.appInfoHandler) + apiV1PlatformSerial.POST("/app/clear", r.clearAppHandler) + apiV1PlatformSerial.POST("/app/launch", r.launchAppHandler) + apiV1PlatformSerial.POST("/app/terminal", r.terminalAppHandler) + apiV1PlatformSerial.POST("/app/uninstall", r.uninstallAppHandler) // Device operations - apiV1PlatformSerial.GET("/screenshot", screenshotHandler) - apiV1PlatformSerial.GET("/video", videoHandler) - apiV1PlatformSerial.POST("/device/push_image", pushImageHandler) - apiV1PlatformSerial.POST("/device/clear_image", clearImageHandler) - apiV1PlatformSerial.GET("/adb/source", adbSourceHandler) + apiV1PlatformSerial.GET("/screenshot", r.screenshotHandler) + apiV1PlatformSerial.GET("/video", r.videoHandler) + apiV1PlatformSerial.POST("/device/push_image", r.pushImageHandler) + apiV1PlatformSerial.POST("/device/clear_image", r.clearImageHandler) + apiV1PlatformSerial.GET("/adb/source", r.adbSourceHandler) // uixt operations - apiV1PlatformSerial.POST("/uixt/action", uixtActionHandler) - apiV1PlatformSerial.POST("/uixt/actions", uixtActionsHandler) + apiV1PlatformSerial.POST("/uixt/action", r.uixtActionHandler) + apiV1PlatformSerial.POST("/uixt/actions", r.uixtActionsHandler) } func (r *Router) Run(port int) error { @@ -72,7 +76,7 @@ func (r *Router) Run(port int) error { return nil } -func pingHandler(c *gin.Context) { +func (r *Router) pingHandler(c *gin.Context) { RenderSuccess(c, true) } diff --git a/server/source.go b/server/source.go index fd184f12..d9903965 100644 --- a/server/source.go +++ b/server/source.go @@ -9,8 +9,8 @@ import ( "github.com/httprunner/httprunner/v5/pkg/uixt/option" ) -func screenshotHandler(c *gin.Context) { - driver, err := GetDriver(c) +func (r *Router) screenshotHandler(c *gin.Context) { + driver, err := r.GetDriver(c) if err != nil { return } @@ -23,8 +23,8 @@ func screenshotHandler(c *gin.Context) { RenderSuccess(c, base64.StdEncoding.EncodeToString(raw.Bytes())) } -func screenResultHandler(c *gin.Context) { - dExt, err := GetDriver(c) +func (r *Router) screenResultHandler(c *gin.Context) { + driver, err := r.GetDriver(c) if err != nil { return } @@ -40,7 +40,7 @@ func screenResultHandler(c *gin.Context) { actionOptions = screenReq.Options.Options() } - screenResult, err := dExt.GetScreenResult(actionOptions...) + screenResult, err := driver.GetScreenResult(actionOptions...) if err != nil { log.Err(err).Msg("get screen result failed") RenderError(c, err) @@ -49,8 +49,8 @@ func screenResultHandler(c *gin.Context) { RenderSuccess(c, screenResult) } -func adbSourceHandler(c *gin.Context) { - dExt, err := GetDriver(c) +func (r *Router) adbSourceHandler(c *gin.Context) { + dExt, err := r.GetDriver(c) if err != nil { return } diff --git a/server/ui.go b/server/ui.go index 7cb63855..b11a64c9 100644 --- a/server/ui.go +++ b/server/ui.go @@ -5,13 +5,13 @@ import ( "github.com/httprunner/httprunner/v5/pkg/uixt/option" ) -func tapHandler(c *gin.Context) { +func (r *Router) tapHandler(c *gin.Context) { var tapReq TapRequest if err := c.ShouldBindJSON(&tapReq); err != nil { RenderErrorValidateRequest(c, err) return } - driver, err := GetDriver(c) + driver, err := r.GetDriver(c) if err != nil { return } @@ -29,14 +29,14 @@ func tapHandler(c *gin.Context) { RenderSuccess(c, true) } -func doubleTapHandler(c *gin.Context) { +func (r *Router) doubleTapHandler(c *gin.Context) { var tapReq TapRequest if err := c.ShouldBindJSON(&tapReq); err != nil { RenderErrorValidateRequest(c, err) return } - driver, err := GetDriver(c) + driver, err := r.GetDriver(c) if err != nil { return } @@ -55,7 +55,7 @@ func doubleTapHandler(c *gin.Context) { RenderSuccess(c, true) } -func dragHandler(c *gin.Context) { +func (r *Router) dragHandler(c *gin.Context) { var dragReq DragRequest if err := c.ShouldBindJSON(&dragReq); err != nil { RenderErrorValidateRequest(c, err) @@ -64,7 +64,7 @@ func dragHandler(c *gin.Context) { if dragReq.Duration == 0 { dragReq.Duration = 1 } - driver, err := GetDriver(c) + driver, err := r.GetDriver(c) if err != nil { return } @@ -79,13 +79,13 @@ func dragHandler(c *gin.Context) { RenderSuccess(c, true) } -func inputHandler(c *gin.Context) { +func (r *Router) inputHandler(c *gin.Context) { var inputReq InputRequest if err := c.ShouldBindJSON(&inputReq); err != nil { RenderErrorValidateRequest(c, err) return } - driver, err := GetDriver(c) + driver, err := r.GetDriver(c) if err != nil { return } diff --git a/server/uixt.go b/server/uixt.go index c40d430e..865a1165 100644 --- a/server/uixt.go +++ b/server/uixt.go @@ -7,8 +7,8 @@ import ( ) // exec a single uixt action -func uixtActionHandler(c *gin.Context) { - dExt, err := GetDriver(c) +func (r *Router) uixtActionHandler(c *gin.Context) { + dExt, err := r.GetDriver(c) if err != nil { return } @@ -29,8 +29,8 @@ func uixtActionHandler(c *gin.Context) { } // exec multiple uixt actions -func uixtActionsHandler(c *gin.Context) { - dExt, err := GetDriver(c) +func (r *Router) uixtActionsHandler(c *gin.Context) { + dExt, err := r.GetDriver(c) if err != nil { return }