diff --git a/src/Appium.Net/Appium/Service/AppiumLocalService.cs b/src/Appium.Net/Appium/Service/AppiumLocalService.cs index 5461fbefa..b66ef2cff 100644 --- a/src/Appium.Net/Appium/Service/AppiumLocalService.cs +++ b/src/Appium.Net/Appium/Service/AppiumLocalService.cs @@ -18,6 +18,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; +using System.Linq; using System.Net; using System.Runtime.CompilerServices; @@ -32,6 +33,7 @@ public class AppiumLocalService : ICommandServer private readonly TimeSpan InitializationTimeout; private readonly IDictionary EnvironmentForProcess; private Process Service; + private List ArgsList; /// /// Creates an instance of AppiumLocalService without special settings @@ -40,11 +42,11 @@ public class AppiumLocalService : ICommandServer public static AppiumLocalService BuildDefaultService() => new AppiumServiceBuilder().Build(); internal AppiumLocalService( - FileInfo nodeJS, - string arguments, - IPAddress ip, + FileInfo nodeJS, + string arguments, + IPAddress ip, int port, - TimeSpan initializationTimeout, + TimeSpan initializationTimeout, IDictionary environmentForProcess) { NodeJS = nodeJS; @@ -58,7 +60,7 @@ internal AppiumLocalService( /// /// The base URL for the managed appium server. /// - public Uri ServiceUrl => new Uri($"http://{IP.ToString()}:{Convert.ToString(Port)}/wd/hub"); + public Uri ServiceUrl => new Uri($"http://{IP}:{Convert.ToString(Port)}"); /// /// Event that can be used to capture the output of the service @@ -131,7 +133,7 @@ private void DestroyProcess() { Service.Kill(); } - catch (Exception ignored) + catch { } finally @@ -175,26 +177,80 @@ public bool IsRunning } } - private bool Ping(TimeSpan span) + private string GetArgsValue(string argStr) { - bool pinged = false; + int idx; + idx= ArgsList.IndexOf(argStr); + return ArgsList[idx + 1]; + } - Uri status; + private string ParseBasePath() + { + if (ArgsList.Contains("--base-path")) + { + return GetArgsValue("--base-path"); + } + else if (ArgsList.Contains("-pa")) + { + return GetArgsValue("-pa"); + } + return AppiumServiceConstants.DefaultBasePath; + } + private void GenerateArgsList() + { + ArgsList = Arguments.Split(' ').ToList(); + } + private Uri CreateStatusUrl() + { + Uri status; Uri service = ServiceUrl; + + if (ArgsList == null) + { + GenerateArgsList(); + } + string basePath = ParseBasePath(); + bool defBasePath = basePath.Equals(AppiumServiceConstants.DefaultBasePath); + if (service.IsLoopback || IP.ToString().Equals(AppiumServiceConstants.DefaultLocalIPAddress)) { - status = new Uri("http://localhost:" + Convert.ToString(Port) + "/wd/hub/status"); + var tmpStatus = "http://localhost:" + Convert.ToString(Port); + if (defBasePath) + { + status = new Uri(tmpStatus + AppiumServiceConstants.StatusUrl); + } + else + { + status = new Uri(tmpStatus + basePath + AppiumServiceConstants.StatusUrl); + } } else { - status = new Uri(service.ToString() + "/status"); + if (defBasePath) + { + status = new Uri(service, AppiumServiceConstants.StatusUrl); + } + else + { + status = new Uri(service, basePath + AppiumServiceConstants.StatusUrl); + } } + return status; + } + + private bool Ping(TimeSpan span) + { + bool pinged = false; + + Uri status; + + status = CreateStatusUrl(); - DateTime endTime = DateTime.Now.Add(this.InitializationTimeout); + DateTime endTime = DateTime.Now.Add(span); while (!pinged & DateTime.Now < endTime) { - HttpWebRequest request = (HttpWebRequest) HttpWebRequest.Create(status); + HttpWebRequest request = (HttpWebRequest)WebRequest.Create(status); HttpWebResponse response = null; try { @@ -203,7 +259,7 @@ private bool Ping(TimeSpan span) pinged = true; } } - catch (Exception e) + catch { pinged = false; } diff --git a/src/Appium.Net/Appium/Service/AppiumServiceConstants.cs b/src/Appium.Net/Appium/Service/AppiumServiceConstants.cs index 02a20d144..c64ab7d57 100644 --- a/src/Appium.Net/Appium/Service/AppiumServiceConstants.cs +++ b/src/Appium.Net/Appium/Service/AppiumServiceConstants.cs @@ -37,9 +37,11 @@ public sealed class AppiumServiceConstants internal readonly static string Bash = "/bin/bash"; internal readonly static string CmdExe = "cmd.exe"; internal readonly static string Node = "node"; - + internal static readonly string DefaultLocalIPAddress = "127.0.0.1"; internal static readonly int DefaultAppiumPort = 4723; + internal static readonly string StatusUrl = "/status"; + internal static readonly string DefaultBasePath = "/"; internal static readonly string AppiumFolder = "appium"; internal static readonly string BinFolder = "bin"; diff --git a/src/Appium.Net/Appium/Service/Options/GeneralOptionList.cs b/src/Appium.Net/Appium/Service/Options/GeneralOptionList.cs index 853ddab30..55502cb46 100644 --- a/src/Appium.Net/Appium/Service/Options/GeneralOptionList.cs +++ b/src/Appium.Net/Appium/Service/Options/GeneralOptionList.cs @@ -20,7 +20,7 @@ namespace OpenQA.Selenium.Appium.Service.Options /// /// Here is the list of common Appium server arguments. /// All flags are optional, but some are required in conjunction with certain others. - /// The full list is available here: http://appium.io/slate/en/master/?ruby#appium-server-arguments + /// The full list is available here: https://appium.io/docs/en/writing-running-appium/server-args/ /// public sealed class GeneralOptionList : BaseOptionList { @@ -30,6 +30,16 @@ public sealed class GeneralOptionList : BaseOptionList public static KeyValuePair Shell(string value) => GetKeyValuePair("--shell", value); + /// + /// Initial path segment where the Appium/WebDriver API will be hosted. Every endpoint will be behind this segment.
+ /// Default: for Appium 2.0: / ; for Appium 1: /wd/hub
+ /// Example: --base-path /my/path/prefix + ///
+ /// + /// + public static KeyValuePair BasePath(string value) => + GetKeyValuePair("--base-path", value); + /// /// callback IP Address (default: same as address)
/// Sample
diff --git a/test/integration/Properties/Resources.Designer.cs b/test/integration/Properties/Resources.Designer.cs index d3397d2da..400c7e3eb 100644 --- a/test/integration/Properties/Resources.Designer.cs +++ b/test/integration/Properties/Resources.Designer.cs @@ -8,10 +8,10 @@ // //------------------------------------------------------------------------------ -namespace Appium.Net.Integration.Tests.Properties { - using System; - - +namespace Appium.Net.Integration.Tests.Properties +{ + + /// /// A strongly-typed resource class, for looking up localized strings, etc. /// diff --git a/test/integration/ServerTests/AppiumLocalServerLaunchingTest.cs b/test/integration/ServerTests/AppiumLocalServerLaunchingTest.cs index 2b23ec1d1..8662eef3a 100644 --- a/test/integration/ServerTests/AppiumLocalServerLaunchingTest.cs +++ b/test/integration/ServerTests/AppiumLocalServerLaunchingTest.cs @@ -184,6 +184,24 @@ public void CheckAbilityToStartServiceUsingFlags() } } + [Test] + public void CheckAbilityToStartServiceUsingBasePathFlag() + { + AppiumLocalService service = null; + var args = new OptionCollector().AddArguments(GeneralOptionList.BasePath("/wd/hub")); + try + { + service = new AppiumServiceBuilder().WithArguments(args).Build(); + service.Start(); + Assert.IsTrue(service.IsRunning); + } + finally + { + service?.Dispose(); + } + } + + [Test] public void CheckAbilityToStartServiceUsingCapabilities() {