Skip to content
This repository was archived by the owner on Sep 3, 2024. It is now read-only.

Commit 3dd0694

Browse files
use different server for container
- uses sql-stream-store/browser container to get the compiled static assets - serve them as embedded content
1 parent b0ffd07 commit 3dd0694

13 files changed

Lines changed: 485 additions & 16 deletions

.dockerignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,5 @@
88
.vs/
99
.vscode/
1010
artifacts/
11+
build.sh
12+
build.cmd

Dockerfile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ RUN dotnet restore
3434

3535
COPY ./build .
3636

37+
COPY --from=sql-stream-store/browser:latest /var/www /app/src/SqlStreamStore.HAL.ApplicationServer/Browser/build
38+
3739
WORKDIR /app
3840

3941
RUN MYGET_API_KEY=$MYGET_API_KEY \
@@ -44,4 +46,4 @@ FROM microsoft/dotnet:2.1.6-runtime-deps-alpine3.7 AS runtime
4446
WORKDIR /app
4547
COPY --from=build /app/publish ./
4648

47-
ENTRYPOINT ["/app/SqlStreamStore.HAL.DevServer"]
49+
ENTRYPOINT ["/app/SqlStreamStore.HAL.ApplicationServer"]

build/Program.cs

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -70,17 +70,7 @@ public static void Main(string[] args)
7070
RunTargets(args.Concat(new[] {"--parallel"}));
7171
}
7272

73-
private static readonly Action Init = () =>
74-
{
75-
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
76-
{
77-
Run("cmd", "/c yarn", "docs");
78-
}
79-
else
80-
{
81-
Run("yarn", string.Empty, "docs");
82-
}
83-
};
73+
private static readonly Action Init = () => Yarn("./docs");
8474

8575
private static readonly Action Clean = () =>
8676
{
@@ -111,7 +101,7 @@ public static void Main(string[] args)
111101

112102
private static readonly Action Publish = () => Run(
113103
"dotnet",
114-
$"publish --configuration=Release --output=../../{PublishDir} --runtime=alpine.3.7-x64 /p:ShowLinkerSizeComparison=true src/SqlStreamStore.HAL.DevServer");
104+
$"publish --configuration=Release --output=../../{PublishDir} --runtime=alpine.3.7-x64 /p:ShowLinkerSizeComparison=true src/SqlStreamStore.HAL.ApplicationServer");
115105

116106
private static readonly Action Pack = () => Run(
117107
"dotnet",
@@ -136,6 +126,14 @@ public static void Main(string[] args)
136126
}
137127
};
138128

129+
private static void Yarn(string workingDirectory, string args = default)
130+
{
131+
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
132+
Run("cmd", "/c yarn", workingDirectory);
133+
else
134+
Run("yarn", args, workingDirectory);
135+
}
136+
139137
private static string[] SchemaDirectories(DirectoryInfo srcDirectory)
140138
=> srcDirectory.GetFiles("*.schema.json", SearchOption.AllDirectories)
141139
.Select(schemaFile => schemaFile.DirectoryName)

build/build.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
<PropertyGroup>
44
<OutputType>Exe</OutputType>
55
<TargetFramework>netcoreapp2.1</TargetFramework>
6+
<LangVersion>latest</LangVersion>
67
</PropertyGroup>
78

89
<ItemGroup>
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
namespace SqlStreamStore.HAL.ApplicationServer
2+
{
3+
using System;
4+
using System.Threading.Tasks;
5+
using Microsoft.AspNetCore.Builder;
6+
using Microsoft.AspNetCore.Hosting;
7+
using Microsoft.AspNetCore.Http;
8+
using Microsoft.Extensions.DependencyInjection;
9+
using Serilog;
10+
using SqlStreamStore.HAL.ApplicationServer.Browser;
11+
using MidFunc = System.Func<
12+
Microsoft.AspNetCore.Http.HttpContext,
13+
System.Func<System.Threading.Tasks.Task>,
14+
System.Threading.Tasks.Task
15+
>;
16+
17+
internal class ApplicationServerStartup : IStartup
18+
{
19+
private readonly IStreamStore _streamStore;
20+
private readonly SqlStreamStoreMiddlewareOptions _options;
21+
22+
public ApplicationServerStartup(
23+
IStreamStore streamStore,
24+
SqlStreamStoreMiddlewareOptions options)
25+
{
26+
_streamStore = streamStore;
27+
_options = options;
28+
}
29+
30+
public IServiceProvider ConfigureServices(IServiceCollection services) => services
31+
.AddResponseCompression(options => options.MimeTypes = new[] { "application/hal+json" })
32+
.BuildServiceProvider();
33+
34+
public void Configure(IApplicationBuilder app) => app
35+
.UseResponseCompression()
36+
.Use(VaryAccept)
37+
.Use(CatchAndDisplayErrors)
38+
.UseSqlStreamStoreBrowser()
39+
.UseSqlStreamStoreHal(_streamStore, _options);
40+
41+
private static MidFunc CatchAndDisplayErrors => async (context, next) =>
42+
{
43+
try
44+
{
45+
await next();
46+
}
47+
catch(Exception ex)
48+
{
49+
Log.Warning(ex, "Error during request.");
50+
}
51+
};
52+
53+
private static MidFunc VaryAccept => (context, next) =>
54+
{
55+
Task Vary()
56+
{
57+
context.Response.Headers.AppendCommaSeparatedValues("Vary", "Accept");
58+
59+
return Task.CompletedTask;
60+
}
61+
62+
context.Response.OnStarting(Vary);
63+
64+
return next();
65+
};
66+
}
67+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
namespace SqlStreamStore.HAL.ApplicationServer.Browser
2+
{
3+
using System;
4+
using System.Linq;
5+
using System.Net.Http.Headers;
6+
using System.Threading.Tasks;
7+
using Microsoft.AspNetCore.Builder;
8+
using Microsoft.AspNetCore.Http;
9+
using Microsoft.Extensions.FileProviders;
10+
using Serilog;
11+
using MidFunc = System.Func<
12+
Microsoft.AspNetCore.Http.HttpContext,
13+
System.Func<System.Threading.Tasks.Task>,
14+
System.Threading.Tasks.Task
15+
>;
16+
17+
internal static class SqlStreamStoreBrowserMiddleware
18+
{
19+
public static IApplicationBuilder UseSqlStreamStoreBrowser(
20+
this IApplicationBuilder builder)
21+
{
22+
var sqlStreamStoreBrowserFileProvider = new EmbeddedFileProvider(
23+
typeof(SqlStreamStoreBrowserMiddleware).Assembly,
24+
typeof(SqlStreamStoreBrowserMiddleware).Namespace);
25+
26+
var staticFiles = typeof(SqlStreamStoreBrowserMiddleware).Assembly.GetManifestResourceNames()
27+
.Where(name => name.StartsWith(typeof(SqlStreamStoreBrowserMiddleware).Namespace))
28+
.Select(name => name.Remove(0, typeof(SqlStreamStoreBrowserMiddleware).Namespace.Length + 1)
29+
.Replace('.', '/'));
30+
31+
Log.Information(
32+
$"The following files will be served as static content: {string.Join(", ", staticFiles)}");
33+
34+
return builder.Use(IndexPage).UseStaticFiles(new StaticFileOptions
35+
{
36+
FileProvider = sqlStreamStoreBrowserFileProvider
37+
});
38+
39+
Task IndexPage(HttpContext context, Func<Task> next)
40+
{
41+
if(GetAcceptHeaders(context.Request).Contains("text/html"))
42+
{
43+
context.Request.Path = new PathString("/index.html");
44+
}
45+
46+
return next();
47+
}
48+
}
49+
50+
private static string[] GetAcceptHeaders(HttpRequest contextRequest)
51+
=> Array.ConvertAll(
52+
contextRequest.Headers.GetCommaSeparatedValues("Accept"),
53+
value => MediaTypeWithQualityHeaderValue.TryParse(value, out var header)
54+
? header.MediaType
55+
: null);
56+
}
57+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
namespace SqlStreamStore.HAL.ApplicationServer
2+
{
3+
using System;
4+
using System.Threading;
5+
using System.Threading.Tasks;
6+
using Microsoft.AspNetCore.Hosting;
7+
using Serilog;
8+
9+
internal class Program : IDisposable
10+
{
11+
private readonly CancellationTokenSource _cts;
12+
private readonly SqlStreamStoreHalConfiguration _configuration;
13+
private readonly SqlStreamStoreFactory _factory;
14+
15+
public static async Task<int> Main(string[] args)
16+
{
17+
using(var program = new Program(args))
18+
{
19+
return await program.Run();
20+
}
21+
}
22+
23+
private Program(string[] args)
24+
{
25+
_configuration = new SqlStreamStoreHalConfiguration(Environment.GetEnvironmentVariables(), args);
26+
27+
Log.Logger = new LoggerConfiguration()
28+
.MinimumLevel.Is(_configuration.LogLevel)
29+
.Enrich.FromLogContext()
30+
.WriteTo.Console()
31+
.CreateLogger();
32+
33+
_cts = new CancellationTokenSource();
34+
_factory = new SqlStreamStoreFactory(_configuration);
35+
}
36+
37+
private async Task<int> Run()
38+
{
39+
try
40+
{
41+
using(var streamStore = await _factory.Create(_cts.Token))
42+
using(var host = new WebHostBuilder()
43+
.UseKestrel()
44+
.UseStartup(new ApplicationServerStartup(streamStore,
45+
new SqlStreamStoreMiddlewareOptions
46+
{
47+
UseCanonicalUrls = _configuration.UseCanonicalUris
48+
}))
49+
.UseSerilog()
50+
.Build())
51+
{
52+
await Task.WhenAll(
53+
host.RunAsync(_cts.Token),
54+
host.WaitForShutdownAsync(_cts.Token));
55+
56+
return 0;
57+
}
58+
}
59+
catch(Exception ex)
60+
{
61+
Log.Fatal(ex, "Host terminated unexpectedly.");
62+
return 1;
63+
}
64+
finally
65+
{
66+
Log.CloseAndFlush();
67+
}
68+
}
69+
70+
public void Dispose()
71+
{
72+
_cts?.Dispose();
73+
}
74+
}
75+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<OutputType>Exe</OutputType>
4+
<TargetFramework>netcoreapp2.1</TargetFramework>
5+
<RuntimeIdentifiers>alpine.3.7-x64</RuntimeIdentifiers>
6+
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
7+
<LangVersion>latest</LangVersion>
8+
<CrossGenDuringPublish>false</CrossGenDuringPublish>
9+
</PropertyGroup>
10+
<ItemGroup>
11+
<PackageReference Include="ILLink.Tasks" Version="0.1.5-preview-1841731" />
12+
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="2.1.3" />
13+
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.1.1" />
14+
<PackageReference Include="Microsoft.AspNetCore.ResponseCompression" Version="2.1.1" />
15+
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="2.1.1" />
16+
<PackageReference Include="Microsoft.Extensions.Configuration.CommandLine" Version="2.1.1" />
17+
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="2.1.1" />
18+
<PackageReference Include="Serilog.AspNetCore" Version="2.1.1" />
19+
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
20+
<PackageReference Include="SqlStreamStore.MsSql" Version="1.2.0-*" />
21+
<PackageReference Include="SqlStreamStore.Postgres" Version="1.2.0-*" />
22+
<PackageReference Include="System.IO.Pipelines" Version="4.5.1" />
23+
</ItemGroup>
24+
<ItemGroup>
25+
<ProjectReference Include="..\SqlStreamStore.HAL\SqlStreamStore.HAL.csproj" />
26+
</ItemGroup>
27+
<ItemGroup>
28+
<EmbeddedResource Include="Browser\build\**">
29+
<Link>Browser\%(RecursiveDir)%(Filename)%(Extension)</Link>
30+
</EmbeddedResource>
31+
</ItemGroup>
32+
</Project>

0 commit comments

Comments
 (0)