312 lines
13 KiB
C#
312 lines
13 KiB
C#
// Copyright (c) .NET Foundation. All rights reserved.
|
|
// Licensed under the MIT License. See License.txt in the project root for license information.
|
|
|
|
using Microsoft.AspNetCore.Builder;
|
|
using Microsoft.AspNetCore.Http;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Microsoft.Extensions.Logging;
|
|
using Microsoft.Extensions.Primitives;
|
|
using Microsoft.Net.Http.Headers;
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.Net.WebSockets;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace AspnetCoreModule.TestSites.Standard
|
|
{
|
|
public class Startup
|
|
{
|
|
public static int SleeptimeWhileClosing = 0;
|
|
public static int SleeptimeWhileStarting = 0;
|
|
public static List<byte[]> MemoryLeakList = new List<byte[]>();
|
|
|
|
public void ConfigureServices(IServiceCollection services)
|
|
{
|
|
services.Configure<IISOptions>(options => {
|
|
// Considering the default value of ForwardWindowsAuthentication is true,
|
|
// the below line is not required at present, however keeping in case the default value is changed later.
|
|
options.ForwardWindowsAuthentication = true;
|
|
});
|
|
}
|
|
|
|
private async Task Echo(WebSocket webSocket)
|
|
{
|
|
var buffer = new byte[1024 * 4];
|
|
var result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
|
|
while (!result.CloseStatus.HasValue)
|
|
{
|
|
await webSocket.SendAsync(new ArraySegment<byte>(buffer, 0, result.Count), result.MessageType, result.EndOfMessage, CancellationToken.None);
|
|
result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
|
|
}
|
|
await webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None);
|
|
}
|
|
|
|
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
|
|
{
|
|
loggerFactory.AddConsole(minLevel: LogLevel.Warning);
|
|
|
|
app.Map("/websocketSubProtocol", subApp =>
|
|
{
|
|
app.UseWebSockets(new WebSocketOptions
|
|
{
|
|
ReplaceFeature = true
|
|
});
|
|
|
|
subApp.Use(async (context, next) =>
|
|
{
|
|
if (context.WebSockets.IsWebSocketRequest)
|
|
{
|
|
var webSocket = await context.WebSockets.AcceptWebSocketAsync("mywebsocketsubprotocol");
|
|
await Echo(webSocket);
|
|
}
|
|
else
|
|
{
|
|
var wsScheme = context.Request.IsHttps ? "wss" : "ws";
|
|
var wsUrl = $"{wsScheme}://{context.Request.Host.Host}:{context.Request.Host.Port}{context.Request.Path}";
|
|
await context.Response.WriteAsync($"Ready to accept a WebSocket request at: {wsUrl}");
|
|
}
|
|
});
|
|
});
|
|
|
|
app.Map("/websocket", subApp =>
|
|
{
|
|
app.UseWebSockets(new WebSocketOptions
|
|
{
|
|
ReplaceFeature = true
|
|
});
|
|
|
|
subApp.Use(async (context, next) =>
|
|
{
|
|
if (context.WebSockets.IsWebSocketRequest)
|
|
{
|
|
var webSocket = await context.WebSockets.AcceptWebSocketAsync("");
|
|
await Echo(webSocket);
|
|
}
|
|
else
|
|
{
|
|
var wsScheme = context.Request.IsHttps ? "wss" : "ws";
|
|
var wsUrl = $"{wsScheme}://{context.Request.Host.Host}:{context.Request.Host.Port}{context.Request.Path}";
|
|
await context.Response.WriteAsync($"Ready to accept a WebSocket request at: {wsUrl}");
|
|
}
|
|
});
|
|
});
|
|
|
|
app.Map("/GetProcessId", subApp =>
|
|
{
|
|
subApp.Run(context =>
|
|
{
|
|
var process = Process.GetCurrentProcess();
|
|
return context.Response.WriteAsync(process.Id.ToString());
|
|
});
|
|
});
|
|
|
|
app.Map("/EchoPostData", subApp =>
|
|
{
|
|
subApp.Run(context =>
|
|
{
|
|
string responseBody = string.Empty;
|
|
if (string.Equals(context.Request.Method, "POST", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
var form = context.Request.ReadFormAsync().GetAwaiter().GetResult();
|
|
int counter = 0;
|
|
foreach (var key in form.Keys)
|
|
{
|
|
StringValues output;
|
|
if (form.TryGetValue(key, out output))
|
|
{
|
|
responseBody += key + "=";
|
|
foreach (var line in output)
|
|
{
|
|
responseBody += line;
|
|
}
|
|
if (++counter < form.Count)
|
|
{
|
|
responseBody += "&";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
responseBody = "NoAction";
|
|
}
|
|
return context.Response.WriteAsync(responseBody);
|
|
});
|
|
});
|
|
|
|
app.Map("/contentlength", subApp =>
|
|
{
|
|
subApp.Run(context =>
|
|
{
|
|
context.Response.ContentLength = 14;
|
|
return context.Response.WriteAsync("Content Length");
|
|
});
|
|
});
|
|
|
|
app.Map("/connectionclose", subApp =>
|
|
{
|
|
subApp.Run(async context =>
|
|
{
|
|
context.Response.Headers[HeaderNames.Connection] = "close";
|
|
await context.Response.WriteAsync("Connnection Close");
|
|
await context.Response.Body.FlushAsync(); // Bypass IIS write-behind buffering
|
|
});
|
|
});
|
|
|
|
app.Map("/notchunked", subApp =>
|
|
{
|
|
subApp.Run(async context =>
|
|
{
|
|
var encoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false);
|
|
//context.Response.ContentLength = encoding.GetByteCount(document);
|
|
context.Response.ContentType = "text/html;charset=UTF-8";
|
|
await context.Response.WriteAsync("NotChunked", encoding, context.RequestAborted);
|
|
await context.Response.Body.FlushAsync(); // Bypass IIS write-behind buffering
|
|
});
|
|
});
|
|
|
|
app.Map("/chunked", subApp =>
|
|
{
|
|
subApp.Run(async context =>
|
|
{
|
|
await context.Response.WriteAsync("Chunked");
|
|
await context.Response.Body.FlushAsync(); // Bypass IIS write-behind buffering
|
|
});
|
|
});
|
|
|
|
app.Map("/manuallychunked", subApp =>
|
|
{
|
|
subApp.Run(context =>
|
|
{
|
|
context.Response.Headers[HeaderNames.TransferEncoding] = "chunked";
|
|
return context.Response.WriteAsync("10\r\nManually Chunked\r\n0\r\n\r\n");
|
|
});
|
|
});
|
|
|
|
app.Map("/manuallychunkedandclose", subApp =>
|
|
{
|
|
subApp.Run(context =>
|
|
{
|
|
context.Response.Headers[HeaderNames.Connection] = "close";
|
|
context.Response.Headers[HeaderNames.TransferEncoding] = "chunked";
|
|
return context.Response.WriteAsync("1A\r\nManually Chunked and Close\r\n0\r\n\r\n");
|
|
});
|
|
});
|
|
|
|
app.Map("/ImpersonateMiddleware", subApp =>
|
|
{
|
|
subApp.UseMiddleware<ImpersonateMiddleware>();
|
|
subApp.Run(context =>
|
|
{
|
|
return context.Response.WriteAsync("");
|
|
});
|
|
});
|
|
|
|
app.Run(context =>
|
|
{
|
|
string response = "Running";
|
|
string[] paths = context.Request.Path.Value.Split(new char[] { '/', '\\' }, StringSplitOptions.RemoveEmptyEntries);
|
|
foreach (string item in paths)
|
|
{
|
|
string action = string.Empty;
|
|
string parameter = string.Empty;
|
|
|
|
action = "DoSleep";
|
|
if (item.StartsWith(action))
|
|
{
|
|
/*
|
|
Process "DoSleep" command here.
|
|
For example, if path contains "DoSleep" such as /DoSleep1000, run Thread.Sleep(1000)
|
|
*/
|
|
int sleepTime = 1000;
|
|
if (item.Length > action.Length)
|
|
{
|
|
parameter = item.Substring(action.Length);
|
|
sleepTime = Convert.ToInt32(parameter);
|
|
}
|
|
Thread.Sleep(sleepTime);
|
|
}
|
|
|
|
action = "MemoryLeak";
|
|
if (item.StartsWith(action))
|
|
{
|
|
parameter = "1024";
|
|
if (item.Length > action.Length)
|
|
{
|
|
parameter = item.Substring(action.Length);
|
|
}
|
|
long size = Convert.ToInt32(parameter);
|
|
var rnd = new Random();
|
|
byte[] b = new byte[size*1024];
|
|
b[rnd.Next(0, b.Length)] = byte.MaxValue;
|
|
MemoryLeakList.Add(b);
|
|
response = "MemoryLeak, size:" + size.ToString() + " KB, total: " + MemoryLeakList.Count.ToString();
|
|
}
|
|
|
|
action = "ExpandEnvironmentVariables";
|
|
if (item.StartsWith(action))
|
|
{
|
|
if (item.Length > action.Length)
|
|
{
|
|
parameter = item.Substring(action.Length);
|
|
response = Environment.ExpandEnvironmentVariables("%" + parameter + "%");
|
|
}
|
|
}
|
|
|
|
action = "GetEnvironmentVariables";
|
|
if (item.StartsWith(action))
|
|
{
|
|
parameter = item.Substring(action.Length);
|
|
response = Environment.GetEnvironmentVariables().Count.ToString();
|
|
}
|
|
|
|
action = "DumpEnvironmentVariables";
|
|
if (item.StartsWith(action))
|
|
{
|
|
response = String.Empty;
|
|
|
|
foreach (DictionaryEntry de in Environment.GetEnvironmentVariables())
|
|
{
|
|
response += de.Key + ":" + de.Value + "<br/>";
|
|
}
|
|
}
|
|
|
|
action = "GetRequestHeaderValue";
|
|
if (item.StartsWith(action))
|
|
{
|
|
if (item.Length > action.Length)
|
|
{
|
|
parameter = item.Substring(action.Length);
|
|
|
|
if (context.Request.Headers.ContainsKey(parameter))
|
|
{
|
|
response = context.Request.Headers[parameter];
|
|
}
|
|
else
|
|
{
|
|
response = "";
|
|
}
|
|
}
|
|
}
|
|
|
|
action = "DumpRequestHeaders";
|
|
if (item.StartsWith(action))
|
|
{
|
|
response = String.Empty;
|
|
|
|
foreach (var de in context.Request.Headers)
|
|
{
|
|
response += de.Key + ":" + de.Value + "<br/>";
|
|
}
|
|
}
|
|
}
|
|
return context.Response.WriteAsync(response);
|
|
});
|
|
}
|
|
}
|
|
}
|