Merge pull request #528 from Tulpep/master

Support proxy attribute for download
pull/531/head
Oleg Nenashev 2020-05-07 06:16:30 +02:00 committed by GitHub
commit 70d83c045c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 81 additions and 2 deletions

View File

@ -186,6 +186,10 @@ For target servers using the HTTPS transfer protocol it is necessary, that the C
By default, the `download` command does not fail the service startup if the operation fails (e.g. `from` is not available).
In order to force the download failure in such case, it is possible to specify the `failOnError` boolean attribute.
To specify a custom proxy use the parameter `proxy` with the following formats:
- With credentials: `http://USERNAME:PASSWORD@HOST:PORT/`.
- Without credentials: `http://HOST:PORT/`.
Examples:
```xml
@ -193,12 +197,15 @@ Examples:
<download from="http://example.com/some.dat" to="%BASE%\some.dat" failOnError="true"/>
<download from="http://example.com/some.dat" to="%BASE%\some.dat" proxy="http://192.168.1.5:80/"/>
<download from="https://example.com/some.dat" to="%BASE%\some.dat" auth="sspi" />
<download from="https://example.com/some.dat" to="%BASE%\some.dat" failOnError="true"
auth="basic" user="aUser" password="aPassw0rd" />
<download from="http://example.com/some.dat" to="%BASE%\some.dat"
proxy="http://aUser:aPassw0rd@192.168.1.5:80/"
auth="basic" unsecureAuth="true"
user="aUser" password="aPassw0rd" />
```

View File

@ -36,6 +36,7 @@ namespace winsw
public readonly string? Password;
public readonly bool UnsecureAuth;
public readonly bool FailOnError;
public readonly string? Proxy;
public string ShortId => $"(download from {From})";
@ -75,11 +76,13 @@ namespace winsw
AuthType auth = AuthType.none,
string? username = null,
string? password = null,
bool unsecureAuth = false)
bool unsecureAuth = false,
string? proxy = null)
{
From = from;
To = to;
FailOnError = failOnError;
Proxy = proxy;
Auth = auth;
Username = username;
Password = password;
@ -98,6 +101,7 @@ namespace winsw
// All arguments below are optional
FailOnError = XmlHelper.SingleAttribute(n, "failOnError", false);
Proxy = XmlHelper.SingleAttribute<string>(n, "proxy", null);
Auth = XmlHelper.EnumAttribute(n, "auth", AuthType.none);
Username = XmlHelper.SingleAttribute<string>(n, "user", null);
@ -147,6 +151,18 @@ namespace winsw
#endif
{
WebRequest request = WebRequest.Create(From);
if (!string.IsNullOrEmpty(Proxy))
{
CustomProxyInformation proxyInformation = new CustomProxyInformation(Proxy);
if (proxyInformation.Credentials != null)
{
request.Proxy = new WebProxy(proxyInformation.ServerAddress, false, null, proxyInformation.Credentials);
}
else
{
request.Proxy = new WebProxy(proxyInformation.ServerAddress);
}
}
switch (Auth)
{
@ -220,8 +236,8 @@ namespace winsw
}
}
}
#if NET20
#if NET20
private static void CopyStream(Stream source, Stream destination)
{
byte[] buffer = new byte[8192];
@ -233,4 +249,31 @@ namespace winsw
}
#endif
}
public class CustomProxyInformation
{
public string ServerAddress { get; set; }
public NetworkCredential? Credentials { get; set; }
public CustomProxyInformation(string proxy)
{
if (proxy.Contains("@"))
{
// Extract proxy credentials
int credsFrom = proxy.IndexOf("://") + 3;
int credsTo = proxy.LastIndexOf("@");
string completeCredsStr = proxy.Substring(credsFrom, credsTo - credsFrom);
int credsSeparator = completeCredsStr.IndexOf(":");
string username = completeCredsStr.Substring(0, credsSeparator);
string password = completeCredsStr.Substring(credsSeparator + 1);
Credentials = new NetworkCredential(username, password);
ServerAddress = proxy.Replace(completeCredsStr + "@", "");
}
else
{
ServerAddress = proxy;
}
}
}
}

View File

@ -202,6 +202,35 @@ namespace winswTests
Assert.That(() => GetSingleEntry(sd), Throws.TypeOf<InvalidDataException>().With.Message.StartsWith("Cannot parse <auth> Enum value from string 'digest'"));
}
[TestCase("http://", "127.0.0.1:80", "egarcia", "Passw0rd")]
[TestCase("https://", "myurl.com.co:2298", "MyUsername", "P@ssw:rd")]
[TestCase("http://", "192.168.0.8:3030")]
public void Proxy_Credentials(string protocol, string address, string username = null, string password = null)
{
CustomProxyInformation cpi;
if (string.IsNullOrEmpty(username))
{
cpi = new CustomProxyInformation(protocol + address + "/");
}
else
{
cpi = new CustomProxyInformation(protocol + username + ":" + password + "@" + address + "/");
}
Assert.That(cpi.ServerAddress, Is.EqualTo(protocol + address + "/"));
if (string.IsNullOrEmpty(username))
{
Assert.IsNull(cpi.Credentials);
}
else
{
Assert.IsNotNull(cpi.Credentials);
Assert.That(cpi.Credentials.UserName, Is.EqualTo(username));
Assert.That(cpi.Credentials.Password, Is.EqualTo(password));
}
}
private Download GetSingleEntry(ServiceDescriptor sd)
{
var downloads = sd.Downloads.ToArray();