main
cs 130 lines 4.85 KB
Raw
1 // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3 namespace WixToolsetTest.BurnE2E
4 {
5 using System;
6 using System.Collections.Generic;
7 using System.IO;
8 using System.Threading.Tasks;
9 using Microsoft.AspNetCore.Builder;
10 using Microsoft.AspNetCore.Hosting;
11 using Microsoft.AspNetCore.Http;
12 using Microsoft.AspNetCore.StaticFiles;
13 using Microsoft.Extensions.FileProviders;
14 using Microsoft.Extensions.FileProviders.Physical;
15 using Microsoft.Extensions.Hosting;
16 using Microsoft.Extensions.Primitives;
17
18 public class CoreOwinWebServer : IWebServer, IFileProvider
19 {
20 const string StaticFileBasePath = "/e2e";
21
22 private Dictionary<string, string> PhysicalPathsByRelativeUrl { get; } = new Dictionary<string, string>();
23
24 private IHost WebHost { get; set; }
25
26 public bool DisableHeadResponses { get; set; }
27 public bool DisableRangeRequests { get; set; }
28
29 public void AddFiles(Dictionary<string, string> physicalPathsByRelativeUrl)
30 {
31 foreach (var kvp in physicalPathsByRelativeUrl)
32 {
33 this.PhysicalPathsByRelativeUrl.Add(kvp.Key, kvp.Value);
34 }
35 }
36
37 public void Start()
38 {
39 this.WebHost = Host.CreateDefaultBuilder()
40 .ConfigureWebHostDefaults(webBuilder =>
41 {
42 // Use localhost instead of * to avoid firewall issues.
43 webBuilder.UseUrls("http://localhost:9999");
44 webBuilder.Configure(appBuilder =>
45 {
46 appBuilder.Use(this.CustomStaticFileMiddleware);
47 appBuilder.UseStaticFiles(new StaticFileOptions
48 {
49 FileProvider = this,
50 RequestPath = StaticFileBasePath,
51 ServeUnknownFileTypes = true,
52 OnPrepareResponse = this.OnPrepareStaticFileResponse,
53 });
54 });
55 })
56 .Build();
57 this.WebHost.Start();
58 }
59
60 private async Task CustomStaticFileMiddleware(HttpContext context, Func<Task> next)
61 {
62 if (!this.DisableRangeRequests || (!HttpMethods.IsGet(context.Request.Method) && !HttpMethods.IsHead(context.Request.Method)))
63 {
64 await next();
65 return;
66 }
67
68 // Only send Content-Length header.
69 // Don't support range requests.
70 // https://github.com/dotnet/aspnetcore/blob/60abfafe32a4692f9dc4a172665524f163b10012/src/Middleware/StaticFiles/src/StaticFileMiddleware.cs
71 if (!context.Request.Path.StartsWithSegments(StaticFileBasePath, out var subpath))
72 {
73 context.Response.StatusCode = 404;
74 return;
75 }
76
77 var fileInfo = this.GetFileInfo(subpath);
78 if (!fileInfo.Exists)
79 {
80 context.Response.StatusCode = 404;
81 return;
82 }
83
84 var responseHeaders = context.Response.GetTypedHeaders();
85 var fileLength = fileInfo.Length;
86 responseHeaders.ContentLength = fileLength;
87
88 this.OnPrepareStaticFileResponse(new StaticFileResponseContext(context, fileInfo));
89
90 if (HttpMethods.IsGet(context.Request.Method))
91 {
92 await context.Response.SendFileAsync(fileInfo, 0, fileLength);
93 }
94 }
95
96 private void OnPrepareStaticFileResponse(StaticFileResponseContext obj)
97 {
98 if (this.DisableHeadResponses && obj.Context.Request.Method == "HEAD")
99 {
100 obj.Context.Response.StatusCode = 404;
101 }
102 }
103
104 public void Dispose()
105 {
106 var waitTime = TimeSpan.FromSeconds(5);
107 this.WebHost?.StopAsync(waitTime).Wait(waitTime);
108 }
109
110 public IDirectoryContents GetDirectoryContents(string subpath)
111 {
112 throw new NotImplementedException();
113 }
114
115 public IFileInfo GetFileInfo(string subpath)
116 {
117 if (this.PhysicalPathsByRelativeUrl.TryGetValue(subpath, out var filepath))
118 {
119 return new PhysicalFileInfo(new FileInfo(filepath));
120 }
121
122 return new NotFoundFileInfo(subpath);
123 }
124
125 public IChangeToken Watch(string filter)
126 {
127 throw new NotImplementedException();
128 }
129 }
130 }