Skip to content

Commit

Permalink
feat: allow random port assignment
Browse files Browse the repository at this point in the history
  • Loading branch information
richardschneider committed Jun 19, 2019
1 parent 310301c commit af4b243
Show file tree
Hide file tree
Showing 8 changed files with 416 additions and 33 deletions.
6 changes: 6 additions & 0 deletions HttpGateway.sln
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
README.md = README.md
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HttpGatewayTests", "test\HttpGatewayTests.csproj", "{2618564F-254F-469F-A714-49182A5EF0E5}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -25,6 +27,10 @@ Global
{1CA35C8E-75B6-44DC-A7FA-6547297B3812}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1CA35C8E-75B6-44DC-A7FA-6547297B3812}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1CA35C8E-75B6-44DC-A7FA-6547297B3812}.Release|Any CPU.Build.0 = Release|Any CPU
{2618564F-254F-469F-A714-49182A5EF0E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2618564F-254F-469F-A714-49182A5EF0E5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2618564F-254F-469F-A714-49182A5EF0E5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2618564F-254F-469F-A714-49182A5EF0E5}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
3 changes: 1 addition & 2 deletions appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ pull_requests:
do_not_increment_build_number: true

before_build:
- nuget restore
- ps: gitversion /output buildserver /updateAssemblyInfo >gitversion.log

build_script:
Expand All @@ -54,7 +53,7 @@ after_build:
- cmd: appveyor PushArtifact "src\bin\%CONFIGURATION%\Ipfs.HttpGateway.%GitVersion_MajorMinorPatch%.nupkg"

test_script:
# - dotnet test --logger "console;verbosity=normal" -c %CONFIGURATION% --no-build --no-restore test
- dotnet test --logger "console;verbosity=normal" -c %CONFIGURATION% --no-build --no-restore test

after_test:
# Generate coverage report
Expand Down
54 changes: 23 additions & 31 deletions src/GatewayHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Hosting.Server.Features;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
Expand All @@ -20,11 +21,11 @@ namespace Ipfs.HttpGateway
/// </summary>
public class GatewayHost : IDisposable
{
ICoreApi ipfs;
string listeningUrl;
bool disposedValue;
readonly ICoreApi ipfs;
readonly string listeningUrl;
readonly string serverUrl;

IWebHost host;
CancellationTokenSource cancel = new CancellationTokenSource();

/// <summary>
/// Creates a web host that bridges IPFS and HTTP on "http://127.0.0.1:8080"
Expand All @@ -49,10 +50,10 @@ public GatewayHost(ICoreApi ipfs)
/// </param>
/// <param name="url">
/// The url to listen on, typically something like "http://127.0.0.1:8080".
/// A random port can assigned via "http:/127.0.0.1:0".
/// </param>
/// <remarks>
/// This starts the web host on a separate thread. Use the Dispose method to
/// stop the web host.
/// Use the Dispose method to stop the web host.
/// </remarks>
public GatewayHost(ICoreApi ipfs, string url)
{
Expand All @@ -78,12 +79,13 @@ public GatewayHost(ICoreApi ipfs, string url)
})
.Build();

var thread = new Thread(Runner)
{
IsBackground = true
};
host.Start();

thread.Start();
// Get an URL for the server.
serverUrl = host
.ServerFeatures.Get<IServerAddressesFeature>()
.Addresses
.First();
}

/// <summary>
Expand All @@ -104,34 +106,24 @@ public string IpfsUrl(string path)
path = path.Substring(1);
}

return $"{listeningUrl}/ipfs/{path}";
}

/// <summary>
/// The web host thread.
/// </summary>
void Runner()
{
try
{
host.RunAsync(cancel.Token).Wait();
}
catch (Exception e)
{
Console.Error.WriteLine(e.Message);
}
return $"{serverUrl}/ipfs/{path}";
}

/// <inheritdoc />
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
if (disposing)
{
if (disposing)
host?.StopAsync().ConfigureAwait(false).GetAwaiter().GetResult();
try
{
host?.Dispose();
}
catch (Exception)
{
cancel.Cancel();
// eat it.
}
disposedValue = true;
host = null;
}
}

Expand Down
135 changes: 135 additions & 0 deletions test/ConsoleOutLoggeFactoryAdapter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
#region License

/*
* Copyright � 2002-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#endregion

using System;
using Common.Logging.Configuration;

namespace Common.Logging.XSimple
{
/// <summary>
/// Factory for creating <see cref="ILog" /> instances that write data to <see cref="Console.Out" />.
/// </summary>
/// <remarks>
/// <example>
/// Below is an example how to configure this adapter:
/// <code>
/// &lt;configuration&gt;
///
/// &lt;configSections&gt;
/// &lt;sectionGroup name=&quot;common&quot;&gt;
/// &lt;section name=&quot;logging&quot;
/// type=&quot;Common.Logging.ConfigurationSectionHandler, Common.Logging&quot;
/// requirePermission=&quot;false&quot; /&gt;
/// &lt;/sectionGroup&gt;
/// &lt;/configSections&gt;
///
/// &lt;common&gt;
/// &lt;logging&gt;
/// &lt;factoryAdapter type=&quot;Common.Logging.Simple.ConsoleOutLoggerFactoryAdapter, Common.Logging&quot;&gt;
/// &lt;arg key=&quot;level&quot; value=&quot;ALL&quot; /&gt;
/// &lt;/factoryAdapter&gt;
/// &lt;/logging&gt;
/// &lt;/common&gt;
///
/// &lt;/configuration&gt;
/// </code>
/// </example>
/// </remarks>
/// <seealso cref="AbstractSimpleLoggerFactoryAdapter"/>
/// <seealso cref="LogManager.Adapter"/>
/// <seealso cref="ConfigurationSectionHandler"/>
/// <author>Gilles Bayon</author>
/// <author>Mark Pollack</author>
/// <author>Erich Eichinger</author>
public class ConsoleOutLoggerFactoryAdapter : Simple.AbstractSimpleLoggerFactoryAdapter
{
#if !SILVERLIGHT
private readonly bool useColor;

#endif
/// <summary>
/// Initializes a new instance of the <see cref="ConsoleOutLoggerFactoryAdapter"/> class using default
/// settings.
/// </summary>
public ConsoleOutLoggerFactoryAdapter()
: base(null)
{ }

/// <summary>
/// Initializes a new instance of the <see cref="ConsoleOutLoggerFactoryAdapter"/> class.
/// </summary>
/// <remarks>
/// Looks for level, showDateTime, showLogName, dateTimeFormat items from
/// <paramref name="properties" /> for use when the GetLogger methods are called.
/// <see cref="ConfigurationSectionHandler"/> for more information on how to use the
/// standard .NET application configuraiton file (App.config/Web.config)
/// to configure this adapter.
/// </remarks>
/// <param name="properties">The name value collection, typically specified by the user in
/// a configuration section named common/logging.</param>
public ConsoleOutLoggerFactoryAdapter(NameValueCollection properties)
: base(properties)
{ }

#if false
/// <summary>
/// Constructor for binary backwards compatibility with non-portableversions
/// </summary>
/// <param name="properties">The properties.</param>
[Obsolete("Use Constructor taking Common.Logging.Configuration.NameValueCollection instead")]
public ConsoleOutLoggerFactoryAdapter(System.Collections.Specialized.NameValueCollection properties)
: this(NameValueCollectionHelper.ToCommonLoggingCollection(properties))
{ }
#endif

/// <summary>
/// Initializes a new instance of the <see cref="AbstractSimpleLoggerFactoryAdapter"/> class with
/// default settings for the loggers created by this factory.
/// </summary>
public ConsoleOutLoggerFactoryAdapter(LogLevel level, bool showDateTime, bool showLogName, bool showLevel, string dateTimeFormat)
: base(level, showDateTime, showLogName, showLevel, dateTimeFormat)
{ }

#if !SILVERLIGHT
/// <summary>
/// Initializes a new instance of the <see cref="AbstractSimpleLoggerFactoryAdapter"/> class with
/// default settings for the loggers created by this factory.
/// </summary>
public ConsoleOutLoggerFactoryAdapter(LogLevel level, bool showDateTime, bool showLogName, bool showLevel, string dateTimeFormat, bool useColor)
: this(level, showDateTime, showLogName, showLevel, dateTimeFormat)
{
this.useColor = useColor;
}

#endif
/// <summary>
/// Creates a new <see cref="ConsoleOutLogger"/> instance.
/// </summary>
protected override ILog CreateLogger(string name, LogLevel level, bool showLevel, bool showDateTime, bool showLogName, string dateTimeFormat)
{
#if !SILVERLIGHT
ILog log = new ConsoleOutLogger(name, level, showLevel, showDateTime, showLogName, dateTimeFormat, this.useColor);
#else
ILog log = new ConsoleOutLogger(name, level, showLevel, showDateTime, showLogName, dateTimeFormat);
#endif
return log;
}
}
}
120 changes: 120 additions & 0 deletions test/ConsoleOutLogger.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
#region License

/*
* Copyright � 2002-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#endregion

using System;
#if !SILVERLIGHT
using System.Collections.Generic;
#endif
using System.Text;

namespace Common.Logging.XSimple
{
/// <summary>
/// Sends log messages to <see cref="Console.Out" />.
/// </summary>
/// <author>Gilles Bayon</author>
#if PORTABLE
#else
[Serializable]
#endif
public class ConsoleOutLogger : Simple.AbstractSimpleLogger
{
#if !SILVERLIGHT
private static readonly Dictionary<LogLevel, ConsoleColor> colors = new Dictionary<LogLevel, ConsoleColor>
{
{ LogLevel.Fatal, ConsoleColor.Red },
{ LogLevel.Error, ConsoleColor.Yellow },
{ LogLevel.Warn, ConsoleColor.Magenta },
{ LogLevel.Info, ConsoleColor.White },
{ LogLevel.Debug, ConsoleColor.Gray },
{ LogLevel.Trace, ConsoleColor.DarkGray },
};

private readonly bool useColor;

#endif
/// <summary>
/// Creates and initializes a logger that writes messages to <see cref="Console.Out" />.
/// </summary>
/// <param name="logName">The name, usually type name of the calling class, of the logger.</param>
/// <param name="logLevel">The current logging threshold. Messages recieved that are beneath this threshold will not be logged.</param>
/// <param name="showLevel">Include the current log level in the log message.</param>
/// <param name="showDateTime">Include the current time in the log message.</param>
/// <param name="showLogName">Include the instance name in the log message.</param>
/// <param name="dateTimeFormat">The date and time format to use in the log message.</param>
public ConsoleOutLogger(string logName, LogLevel logLevel, bool showLevel, bool showDateTime, bool showLogName, string dateTimeFormat)
: base(logName, logLevel, showLevel, showDateTime, showLogName, dateTimeFormat)
{
}

#if !SILVERLIGHT
/// <summary>
/// Creates and initializes a logger that writes messages to <see cref="Console.Out" />.
/// </summary>
/// <param name="logName">The name, usually type name of the calling class, of the logger.</param>
/// <param name="logLevel">The current logging threshold. Messages recieved that are beneath this threshold will not be logged.</param>
/// <param name="showLevel">Include the current log level in the log message.</param>
/// <param name="showDateTime">Include the current time in the log message.</param>
/// <param name="showLogName">Include the instance name in the log message.</param>
/// <param name="dateTimeFormat">The date and time format to use in the log message.</param>
/// <param name="useColor">Use color when writing the log message.</param>
public ConsoleOutLogger(string logName, LogLevel logLevel, bool showLevel, bool showDateTime, bool showLogName, string dateTimeFormat, bool useColor)
: this(logName, logLevel, showLevel, showDateTime, showLogName, dateTimeFormat)
{
this.useColor = useColor;
}

#endif
/// <summary>
/// Do the actual logging by constructing the log message using a <see cref="StringBuilder" /> then
/// sending the output to <see cref="Console.Out" />.
/// </summary>
/// <param name="level">The <see cref="LogLevel" /> of the message.</param>
/// <param name="message">The log message.</param>
/// <param name="e">An optional <see cref="Exception" /> associated with the message.</param>
protected override void WriteInternal(LogLevel level, object message, Exception e)
{
// Use a StringBuilder for better performance
StringBuilder sb = new StringBuilder();
FormatOutput(sb, level, message, e);

// Print to the appropriate destination
#if !SILVERLIGHT
ConsoleColor color;
if (this.useColor && colors.TryGetValue(level, out color))
{
var originalColor = Console.ForegroundColor;
try
{
Console.ForegroundColor = color;
Console.Out.WriteLine(sb.ToString());
return;
}
finally
{
Console.ForegroundColor = originalColor;
}
}

#endif
Console.Out.WriteLine(sb.ToString());
}
}
}
Loading

0 comments on commit af4b243

Please sign in to comment.