Skip to content

Commit f058c2f

Browse files
committed
simple ssl support
1 parent 613d541 commit f058c2f

7 files changed

Lines changed: 96 additions & 14 deletions

File tree

README.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,9 @@ to return http://www.google.com content when only GET and the path and query do
148148

149149
---- To specify a port number to use, put this in your server.csv `app port,8080` . The port must not be in use.
150150

151+
---- To specify https port to use `app sslport,44300` . It will make things easier if you have visual studio installed which will setup ports 44300 to 44399 ports for use with https, otherwise, you have to setup ssl yourself, e.g see https://www.pluralsight.com/blog/software-development/selfcert-create-a-self-signed-certificate-interactively-gui-or-programmatically-in-net for a convinent self cert tool to use.
152+
153+
151154
---- To open your default browser automatically when you start ServeMe.exe , put this in your server.csv `app openDefaultBrowserOnStartUp`
152155

153156
---- Ok, how about this, imagine you'd like to call a method from an assembly from a dll file. Here is how to do it in server.csv `getSome,assembly file:///D:/ServeMe.Tests/bin/Debug/ServeMe.Tests.DLL ServeMe.Tests.when_serve_me_runs DoSomething w,get` Inside unit tests you can use this helper method to compose the execution instruction `string instruction = ServeMe.GetMethodExecutionInstruction(this.GetType(), methodName, arg);`
@@ -156,10 +159,13 @@ to return http://www.google.com content when only GET and the path and query do
156159
The script can be something like this
157160
`return DateTime.UtcNow;` inside a file called, say, code.txt
158161
The server entry will be (note that script has access to global variables context and args[] )
159-
`getSome,sourcecode csharp code.txt,get`
162+
`getSome,sourcecode csharp code.cs,get`
163+
164+
---- doing `app classes,helper1.cs,helper2.cs,helper3.cs` will load helper 1 2 and 3 along with any script specified in `sourcecode csharp code.cs` config , and they must be c# classes
165+
166+
160167

161-
The class will be auto loaded from
162-
`code.txt.classes`
168+
---- when executing scripts in `getSome,sourcecode csharp code.cs,get` , you have access to the `_` variable as a global variable which contains helper methods
163169

164170
so a get to /getsome will return the value of DateTime.UtcNow;
165171

ServeMeLib/Program.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -641,7 +641,7 @@ others to try
641641
OnlineProcess.StartInfo.FileName = @"cmd.exe";
642642
string ngrokPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"npm\node_modules\ngrok\bin\ngrok.exe");
643643
//var p = $@"{Path.GetPathRoot(Environment.SystemDirectory)}Users\{Environment.UserName}\AppData\Roaming\npm\node_modules\ngrok\bin\ngrok.exe";
644-
OnlineProcess.StartInfo.Arguments = $@"/c {ngrokPath} http {server.CurrentPortUsed}";
644+
OnlineProcess.StartInfo.Arguments = $@"/c {ngrokPath} http {server.CurrentHttpsPortUsed}";
645645
OnlineProcess.Start();
646646
ConsoleWriteLine("IMPORTANT: Remember to run 'go offline' to take your server offline!");
647647
//todo in future , remove dependency on ngrok

ServeMeLib/ServeMe.cs

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ namespace ServeMeLib
1414

1515
public class ServeMe : IDisposable
1616
{
17-
public static string Version = "0.37.0";
17+
public static string Version = "0.38.0";
1818

1919
internal static Action<Exception, string> _onError = null;
2020
public static void OnError(Action<Exception, string> handler)
@@ -81,6 +81,7 @@ internal static bool IsPathRooted(string fn)
8181
public string InMemoryConfigurationPrepend { get; private set; }
8282

8383
public int CurrentPortUsed { get; set; }
84+
public int CurrentHttpsPortUsed { get; set; }
8485

8586
public void Dispose()
8687
{
@@ -393,7 +394,7 @@ internal string CanOpenDefaultBrowserOnStart(string root)
393394
}
394395

395396
//https://stackoverflow.com/questions/570098/in-c-how-to-check-if-a-tcp-port-is-available
396-
private bool PortInUse(int port)
397+
internal bool PortInUse(int port)
397398
{
398399
bool isAvailable = true;
399400
IPGlobalProperties ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties();
@@ -426,6 +427,19 @@ internal List<List<string>> GetVariablesFromSettings()
426427
return null;
427428
}
428429

430+
internal int? GetHttpsPortNumberFromSettings()
431+
{
432+
string[] data;
433+
if (this.ExtractFromSettings("app sslport", out data) == 2)
434+
{
435+
int port = int.Parse(data[1]);
436+
if (this.PortInUse(port))
437+
throw new Exception($"Ssl Port {port} in setting is in use");
438+
return port;
439+
}
440+
441+
return null;
442+
}
429443
internal int? GetPortNumberFromSettings()
430444
{
431445
string[] data;
@@ -454,7 +468,7 @@ internal string GetWorkingPathFromSettings()
454468
return null;
455469
}
456470

457-
public List<string> Start(string serverCsv = null, int? port = null, Func<string, bool> fileExists = null, Func<string, string> readAllTextFromFile = null, Action<string, string> writeAllTextToFile = null)
471+
public List<string> Start(string serverCsv = null, int? port = null, int? portHttps = null, Func<string, bool> fileExists = null, Func<string, string> readAllTextFromFile = null, Action<string, string> writeAllTextToFile = null)
458472
{
459473
this.FileExists = fileExists ?? this.FileExists;
460474
this.ReadAllTextFromFile = readAllTextFromFile ?? this.ReadAllTextFromFile;
@@ -465,8 +479,9 @@ public List<string> Start(string serverCsv = null, int? port = null, Func<string
465479
try
466480
{
467481
this.SetWorkingDirectory(this.GetWorkingPathFromSettings());
468-
this.MyServer = new SimpleHttpServer(this, port ?? this.GetPortNumberFromSettings());
482+
this.MyServer = new SimpleHttpServer(this, port ?? this.GetPortNumberFromSettings(), portHttps?? this.GetHttpsPortNumberFromSettings());
469483
this.CurrentPortUsed = this.MyServer.Port;
484+
this.CurrentHttpsPortUsed = this.MyServer.PortHttps;
470485
Console.WriteLine("Serving!");
471486
Console.WriteLine("");
472487
Console.WriteLine("If you are using server.csv then note that the csv format is :");
@@ -517,16 +532,32 @@ public List<string> Start(string serverCsv = null, int? port = null, Func<string
517532
Console.WriteLine("");
518533
Console.BackgroundColor = ConsoleColor.Black;
519534
Console.ForegroundColor = ConsoleColor.Green;
535+
536+
537+
endpoints.Add("https://localhost:" + this.MyServer.PortHttps);
538+
endpoints.Add("https://127.0.0.1:" + this.MyServer.PortHttps);
539+
Console.WriteLine("- Local: " + "https://localhost:" + this.MyServer.PortHttps);
540+
Console.WriteLine("- Local: " + "https://127.0.0.1:" + this.MyServer.PortHttps);
541+
542+
543+
520544
endpoints.Add("http://localhost:" + this.MyServer.Port);
521545
endpoints.Add("http://127.0.0.1:" + this.MyServer.Port);
522546
Console.WriteLine("- Local: " + "http://localhost:" + this.MyServer.Port);
523547
Console.WriteLine("- Local: " + "http://127.0.0.1:" + this.MyServer.Port);
548+
549+
524550
IPAddress[] localIPs = Dns.GetHostAddresses(Dns.GetHostName());
525551
foreach (IPAddress addr in localIPs)
526552
if (addr.AddressFamily == AddressFamily.InterNetwork)
527553
{
528554
endpoints.Add($"http://{addr}:" + this.MyServer.Port);
529555
Console.WriteLine($"- On your network: http://{addr}:" + this.MyServer.Port);
556+
557+
endpoints.Add($"https://{addr}:" + this.MyServer.PortHttps);
558+
Console.WriteLine($"- On your network: https://{addr}:" + this.MyServer.PortHttps);
559+
560+
530561
}
531562

532563
Console.WriteLine("");

ServeMeLib/SimpleHttpServer.cs

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Runtime.Serialization.Json;
2+
using System.Security.Cryptography.X509Certificates;
23

34
namespace ServeMeLib
45
{
@@ -106,6 +107,7 @@ internal class SimpleHttpServer
106107

107108
private HttpListener _listener;
108109
private int _port;
110+
private int _portHttps;
109111
//private string _rootDirectory;
110112

111113
private Thread _serverThread;
@@ -116,7 +118,7 @@ internal class SimpleHttpServer
116118
/// Construct server with suitable port.
117119
/// </summary>
118120
/// <param name="path">Directory path to serve.</param>
119-
public SimpleHttpServer(ServeMe serveMe, int? port = null)
121+
public SimpleHttpServer(ServeMe serveMe, int? port = null, int? portHttps = null)
120122
{
121123
ServicePointManager.DefaultConnectionLimit = 100;
122124
var handler = new HttpClientHandler
@@ -141,13 +143,39 @@ public SimpleHttpServer(ServeMe serveMe, int? port = null)
141143
port = ((IPEndPoint)l.LocalEndpoint).Port;
142144
l.Stop();
143145
}
146+
if (portHttps == null)
147+
{
148+
var allowableHttpsPortsByVisualStudio = Enumerable.Range(44300, 33399).ToList();
149+
150+
for (int i = 0; i < allowableHttpsPortsByVisualStudio.Count; i++)
151+
{
152+
if (!serveMe.PortInUse(allowableHttpsPortsByVisualStudio[i]))
153+
{
154+
portHttps = allowableHttpsPortsByVisualStudio[i];
155+
serveMe.Log($"Yay! Found https port {portHttps} to use ....");
156+
break;
157+
}
158+
159+
if (i == allowableHttpsPortsByVisualStudio.Count - 1)
160+
{
161+
serveMe.Log(
162+
"Unable to find any siutable https port to use from list between 44300 and 44399. It's unlikely that I will be able to respond to https endpoint");
163+
}
164+
}
165+
}
144166

145167
this.ServeMe.Log($"Using port {port}");
146-
this.Initialize(port.Value);
168+
this.ServeMe.Log($"Using https port {portHttps}");
169+
this.Initialize(port.Value,portHttps.Value);
147170
}
148171

149172
private ServeMe ServeMe { get; }
150173

174+
public int PortHttps
175+
{
176+
get => this._portHttps;
177+
private set { }
178+
}
151179
public int Port
152180
{
153181
get => this._port;
@@ -167,11 +195,13 @@ public void Stop()
167195
client.Dispose();
168196
this._serverThread.Abort();
169197
}
170-
198+
171199
private void Listen()
172200
{
173201
//https://github.com/arshad115/HttpListenerServer
174202
/*
203+
powershell -Command "New-SelfSignedCertificate -DnsName localhost -CertStoreLocation cert:\LocalMachine\My -NotAfter (Get-Date).AddYears(10)"
204+
175205
A URI prefix string is composed of a scheme (http or https), a host, an optional port,
176206
and an optional path. An example of a complete prefix string is "http://www.contoso.com:8080/customerData/".
177207
Prefixes must end in a forward slash ("/"). The HttpListener object with the prefix that most closely matches
@@ -183,13 +213,27 @@ Prefixes must end in a forward slash ("/"). The HttpListener object with the pre
183213
all requests sent to a port, replace the host element with the "+" character, "https://+:8080".
184214
The "*" and "+" characters can be present in prefixes that include paths.
185215
*/
216+
186217
this._listener = new HttpListener();
187218
this._listener.Prefixes.Add("http://*:" + this._port.ToString() + "/");
219+
this._listener.Prefixes.Add("https://*:" + this._portHttps.ToString() + "/");
188220
//this._listener.AuthenticationSchemes = AuthenticationSchemes.Anonymous;
189221
//this._listener.Prefixes.Add("http://+:80/");
190-
this.ServeMe.Log($"About to start listening on port {this._port}");
222+
223+
224+
225+
//X509Certificate2 cert = new X509Certificate2( X509Certificate.CreateFromCertFile("ServeMeCert.cer"));
226+
//X509Store store = new X509Store(StoreName.Root, StoreLocation.LocalMachine);
227+
//store.Open(OpenFlags.ReadWrite);
228+
//if (!store.Certificates.Contains(cert))
229+
//{
230+
// store.Add(cert);
231+
//}
232+
//store.Close();
233+
234+
this.ServeMe.Log($"About to start listening on port {this._port} and https {this._portHttps}");
191235
this._listener.Start();
192-
this.ServeMe.Log($"Now listening on port {this._port}");
236+
this.ServeMe.Log($"Now listening on port {this._port} and https {this._portHttps}");
193237
while (true)
194238
{
195239
HttpListenerContext context = null;
@@ -968,9 +1012,10 @@ private static List<string> extractTokens(HttpListenerContext context)
9681012
return tokensPasts;
9691013
}
9701014

971-
private void Initialize(int port)
1015+
private void Initialize(int port, int https)
9721016
{
9731017
this._port = port;
1018+
this._portHttps = https;
9741019
this._serverThread = new Thread(this.Listen);
9751020
this._serverThread.Start();
9761021
}

tools/Pluralsight.Crypto.dll

39.5 KB
Binary file not shown.

tools/SelfCert.exe

7.5 KB
Binary file not shown.

tools/SelfCert.zip

95.6 KB
Binary file not shown.

0 commit comments

Comments
 (0)