public async Task DoesNotClose_UnderlyingStream_OnDisposingWriter() { // Arrange var stream = new TestMemoryStream(); var writer = new HttpResponseStreamWriter(stream, Encoding.UTF8); // Act await writer.WriteAsync("Hello"); writer.Close(); // Assert Assert.Equal(0, stream.CloseCallCount); }
public async Task DoesNotWriteBOM() { // Arrange var memoryStream = new MemoryStream(); var encodingWithBOM = new UTF8Encoding(encoderShouldEmitUTF8Identifier: true); var writer = new HttpResponseStreamWriter(memoryStream, encodingWithBOM); var expectedData = new byte[] { 97, 98, 99, 100 }; // without BOM // Act using (writer) { await writer.WriteAsync("abcd"); } // Assert Assert.Equal(expectedData, memoryStream.ToArray()); }
public async Task FlushesBuffer_ButNotStream_OnFlushAsync(int byteLength) { // Arrange var stream = new TestMemoryStream(); var writer = new HttpResponseStreamWriter(stream, Encoding.UTF8); await writer.WriteAsync(new string('a', byteLength)); var expectedWriteCount = Math.Ceiling((double)byteLength / HttpResponseStreamWriter.DefaultBufferSize); // Act await writer.FlushAsync(); // Assert Assert.Equal(0, stream.FlushAsyncCallCount); Assert.Equal(expectedWriteCount, stream.WriteAsyncCallCount); Assert.Equal(byteLength, stream.Length); }
public async Task WriteLineAsyncCharArray_OnlyWritesNewLineToStream_ForZeroCount(int newLineLength) { // Arrange var content = new char[1]; var stream = new TestMemoryStream(); var writer = new HttpResponseStreamWriter(stream, Encoding.UTF8); writer.NewLine = new string('\n', newLineLength); // Act using (writer) { await writer.WriteLineAsync(content, 0, 0); } // Assert Assert.Equal(newLineLength, stream.Length); }
public async Task WriteLineAsyncString_WritesToStream(int charCount, int newLineLength) { // Arrange var content = new string('a', charCount); var stream = new TestMemoryStream(); var writer = new HttpResponseStreamWriter(stream, Encoding.UTF8); writer.NewLine = new string('\n', newLineLength); // Act using (writer) { await writer.WriteLineAsync(content); } // Assert Assert.Equal(charCount + newLineLength, stream.Length); }
public async Task WriteLineAsyncString_OnlyWritesNewLineToStream_ForNullArgument(int newLineLength) { // Arrange string?content = null; var stream = new TestMemoryStream(); var writer = new HttpResponseStreamWriter(stream, Encoding.UTF8); writer.NewLine = new string('\n', newLineLength); // Act using (writer) { await writer.WriteLineAsync(content); } // Assert Assert.Equal(newLineLength, stream.Length); }
public Task ExecuteResultAsync(ActionContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } var response = context.HttpContext.Response; response.StatusCode = (int)_statusCode; response.ContentType = "application/json"; using (TextWriter writer = new HttpResponseStreamWriter(response.Body, Encoding.UTF8)) { writer.Write(_jsonString); } return(Task.CompletedTask); }
public Task WriteJsonToStreamAsync(Stream stream, object value, JsonSerializerSettings jsonSerializerSettings = null) { var jsonSerializer = jsonSerializerSettings != null ? JsonSerializer.Create(jsonSerializerSettings) : _jsonSerializer; using (var writer = new HttpResponseStreamWriter(stream, Encoding.UTF8)) { using (var jsonWriter = new JsonTextWriter(writer) { CloseOutput = false, AutoCompleteOnClose = false }) { jsonSerializer.Serialize(jsonWriter, value); } return(writer.FlushAsync()); } }
public void WriteLineReadOnlySpanChar_WritesToStream(int byteLength, string newLine) { // Arrange var stream = new TestMemoryStream(); var writer = new HttpResponseStreamWriter(stream, Encoding.UTF8); writer.NewLine = newLine; // Act using (writer) { var array = new string('a', byteLength).ToCharArray(); var span = new ReadOnlySpan <char>(array); writer.WriteLine(span); } // Assert Assert.Equal(byteLength + newLine.Length, stream.Length); }
public async Task WriteCharAsync_WritesToStream(int byteLength) { // Arrange var stream = new TestMemoryStream(); var writer = new HttpResponseStreamWriter(stream, Encoding.UTF8); // Act using (writer) { for (var i = 0; i < byteLength; i++) { await writer.WriteAsync('a'); } } // Assert Assert.Equal(byteLength, stream.Length); }
public static void WriteJson <T>(this HttpResponse response, T obj) { response.ContentType = "application/json"; var serializer = JsonSerializer.CreateDefault(); using (var writer = new HttpResponseStreamWriter(response.Body, Encoding.UTF8)) { using (var jsonWriter = new JsonTextWriter(writer)) { jsonWriter.ArrayPool = JsonArrayPool; jsonWriter.CloseOutput = false; jsonWriter.AutoCompleteOnClose = false; serializer.Serialize(jsonWriter, obj); } } }
internal static Task WriteJsonAsync <T>(this HttpResponse response, JsonSerializer serializer, T obj) { return(Task.Run(() => { response.ContentType = "application/json"; using (var writer = new HttpResponseStreamWriter(response.Body, Encoding.UTF8)) { using (var jsonWriter = new JsonTextWriter(writer)) { jsonWriter.CloseOutput = false; jsonWriter.AutoCompleteOnClose = false; serializer.Serialize(jsonWriter, obj); } } })); }
public Task OnCustomRedirectToLogin(CookieRedirectContext context) { var actionContext = context.HttpContext.RequestServices.GetRequiredService <IActionContextAccessor>(); if (actionContext.ActionContext == null) { return(_old(context)); } if (actionContext.ActionContext.ActionDescriptor.FilterDescriptors.Any(x => x.Filter is AjaxAttribute)) { // this is an ajax request, return custom JSON telling user that they must be authenticated. var serializerSettings = context .HttpContext .RequestServices .GetRequiredService <IOptions <MvcJsonOptions> >() .Value .SerializerSettings; context.Response.ContentType = "application/json"; using (var writer = new HttpResponseStreamWriter(context.Response.Body, Encoding.UTF8)) { using (var jsonWriter = new JsonTextWriter(writer)) { jsonWriter.CloseOutput = false; var jsonSerializer = JsonSerializer.Create(serializerSettings); jsonSerializer.Serialize(jsonWriter, new { success = false, error = "You must be signed in." }); } } return(Task.FromResult(0)); } else { // this is a normal request to an endpoint that is secured. // do what ASP.NET used to do. return(_old(context)); } }
/// <summary> /// Writes the content to the HTTP response. /// </summary> /// <param name="httpContext">The <see cref="HttpContext"/> for the current request.</param> /// <returns>A task that represents the asynchronous execute operation.</returns> async Task IResult.ExecuteAsync(HttpContext httpContext) { if (httpContext == null) { throw new ArgumentNullException(nameof(httpContext)); } var response = httpContext.Response; ResponseContentTypeHelper.ResolveContentTypeAndEncoding( ContentType, response.ContentType, DefaultContentType, out var resolvedContentType, out var resolvedContentTypeEncoding); response.ContentType = resolvedContentType; if (StatusCode != null) { response.StatusCode = StatusCode.Value; } var factory = httpContext.RequestServices.GetRequiredService <ILoggerFactory>(); var logger = factory.CreateLogger <ContentResult>(); logger.ContentResultExecuting(resolvedContentType); if (Content != null) { response.ContentLength = resolvedContentTypeEncoding.GetByteCount(Content); await using (var textWriter = new HttpResponseStreamWriter(response.Body, resolvedContentTypeEncoding)) { await textWriter.WriteAsync(Content); // Flushing the HttpResponseStreamWriter does not flush the underlying stream. This just flushes // the buffered text in the writer. // We do this rather than letting dispose handle it because dispose would call Write and we want // to call WriteAsync. await textWriter.FlushAsync(); } } }
public async Task CopyToAsync(Stream stream, CancellationToken cancellationToken = default) { using (var sb = new HttpResponseStreamWriter(stream, Encoding.ASCII)) { await sb.WriteAsync("Content-Type: application/http; msgtype=response").ConfigureAwait(false); await sb.WriteAsync(Crlf).ConfigureAwait(false); await sb.WriteAsync(Crlf).ConfigureAwait(false); await sb.WriteAsync(_httpVersion).ConfigureAwait(false); await sb.WriteAsync(' ').ConfigureAwait(false); // ReSharper disable once ImpureMethodCallOnReadonlyValueField await sb.WriteAsync(StatusCode.ToString()).ConfigureAwait(false); await sb.WriteAsync(' ').ConfigureAwait(false); await sb.WriteAsync(_reasonPhrase).ConfigureAwait(false); await sb.WriteAsync(Crlf).ConfigureAwait(false); foreach (var header in Headers) { await sb.WriteAsync(header.Key).ConfigureAwait(false); await sb.WriteAsync(": ").ConfigureAwait(false); await sb.WriteAsync(header.Value).ConfigureAwait(false); await sb.WriteAsync(Crlf).ConfigureAwait(false); } await sb.WriteAsync(Crlf).ConfigureAwait(false); await sb.FlushAsync().ConfigureAwait(false); } if (_content != null) { await _content.CopyToAsync(stream, cancellationToken).ConfigureAwait(false); } }
public async Task FlushesBuffer_OnClose(int byteLength) { // Arrange var stream = new TestMemoryStream(); var writer = new HttpResponseStreamWriter(stream, Encoding.UTF8); await writer.WriteAsync(new string('a', byteLength)); // Act #if NET451 writer.Close(); #else writer.Dispose(); #endif // Assert Assert.Equal(0, stream.FlushCallCount); Assert.Equal(0, stream.FlushAsyncCallCount); Assert.Equal(byteLength, stream.Length); }
public async Task WriteLineReadOnlyMemoryAsync_WritesToStream(int byteLength, int newLineLength) { // Arrange var stream = new TestMemoryStream(); var writer = new HttpResponseStreamWriter(stream, Encoding.UTF8); writer.NewLine = new string('\n', newLineLength); // Act using (writer) { var array = new string('a', byteLength).ToCharArray(); var memory = new ReadOnlyMemory <char>(array); await writer.WriteLineAsync(memory); } // Assert Assert.Equal(byteLength + newLineLength, stream.Length); }
public async Task HttpResponseStreamWriter_WritesDataCorrectly_ForCharactersHavingSurrogatePairs(int characterSize) { // Arrange // Here "𐐀" (called Deseret Long I) actually represents 2 characters. Try to make this character split across // the boundary var content = new string('a', characterSize - 1) + "𐐀"; var stream = new TestMemoryStream(); var writer = new HttpResponseStreamWriter(stream, Encoding.Unicode); // Act await writer.WriteAsync(content); await writer.FlushAsync(); // Assert stream.Seek(0, SeekOrigin.Begin); var streamReader = new StreamReader(stream, Encoding.Unicode); var actualContent = await streamReader.ReadToEndAsync(); Assert.Equal(content, actualContent); }
/// <summary> /// Writes a response in JSON format. /// This function creates a HttpResponseStreamWriter and invokes the callback function which actually does the job. /// </summary> /// <param name="context">The HTTP context.</param> /// <param name="result">The value of result property in the response object (either "ok" or any other string).</param> /// <param name="writeContentAction">The function that actually writes the content.</param> protected static async Task WriteJsonResponseAsync(HttpContext context, string result, Func <JsonWriter, Task> writeContentAction) { context.Response.ContentType = "application/json; charset=utf-8"; using (var responseWriter = new HttpResponseStreamWriter(context.Response.Body, _utf8NoBom)) { using (JsonWriter jsonWriter = new JsonTextWriter(responseWriter)){ await jsonWriter.WriteStartObjectAsync(); await jsonWriter.WritePropertyNameAsync("result"); await jsonWriter.WriteValueAsync(result); if (writeContentAction != null) { await writeContentAction(jsonWriter); } await jsonWriter.WriteEndObjectAsync(); await jsonWriter.FlushAsync(); } } }
public async Task WritesData_OfDifferentLength_InExpectedEncoding( char character, int charCount, string encodingName) { // Arrange var encoding = Encoding.GetEncoding(encodingName); string data = new string(character, charCount); var expectedBytes = encoding.GetBytes(data); var stream = new MemoryStream(); var writer = new HttpResponseStreamWriter(stream, encoding); // Act using (writer) { await writer.WriteAsync(data); } // Assert Assert.Equal(expectedBytes, stream.ToArray()); }
public void HttpResponseStreamWriter_UsingPooledBuffers() { // Arrange var encoding = Encoding.UTF8; var stream = new MemoryStream(); var expectedBytes = encoding.GetBytes("Hello, World!"); using (var writer = new HttpResponseStreamWriter( stream, encoding, 1024, ArrayPool <byte> .Shared, ArrayPool <char> .Shared)) { // Act writer.Write("Hello, World!"); } // Assert Assert.Equal(expectedBytes, stream.ToArray()); }
/// <summary> /// Set code 200, set content-type, add headers if not null, write json body if not null /// </summary> /// <returns></returns> public async Task Write(HandlingContext context, HeaderJsonRpcSerializer headerJsonRpcSerializer) { var sink = context.OriginalHttpContext.Response; if (Headers != null) { foreach (var header in Headers) { sink.Headers.Append(header.Key, header.Value); } } sink.StatusCode = 200; sink.ContentLength = null; var responseMediaType = new MediaTypeHeaderValue(JsonRpcConstants.ContentType) { Encoding = context.RequestEncoding }; sink.ContentType = responseMediaType.ToString(); if (!context.WriteResponse) { return; } await using (var writer = new HttpResponseStreamWriter(sink.Body, context.RequestEncoding)) { using var jsonWriter = new JsonTextWriter(writer) { CloseOutput = false, AutoCompleteOnClose = false, Formatting = headerJsonRpcSerializer.Settings.Formatting }; await Value.WriteToAsync(jsonWriter, context.OriginalHttpContext.RequestAborted); } SetResponseContextItem(context.OriginalHttpContext); }
public async Task FlushWriteThrows_DontFlushInDispose(int byteLength) { // Arrange var stream = new TestMemoryStream() { ThrowOnWrite = true }; var writer = new HttpResponseStreamWriter(stream, Encoding.UTF8); await writer.WriteAsync(new string('a', byteLength)); await Assert.ThrowsAsync <IOException>(() => writer.FlushAsync()); // Act writer.Dispose(); // Assert Assert.Equal(1, stream.WriteAsyncCallCount); Assert.Equal(0, stream.WriteCallCount); Assert.Equal(0, stream.FlushCallCount); Assert.Equal(0, stream.FlushAsyncCallCount); Assert.Equal(0, stream.Length); }
public async Task Invoke(HttpContext httpContext) { try { await next(httpContext); } catch (Exception) when(!httpContext.Response.HasStarted) { var severity = Severity.NawRelaxItsOk; var response = new { message = "An error occurred. Gee we're real sorry about that!", severity = severity.ToString(), }; using (var writer = new HttpResponseStreamWriter(httpContext.Response.Body, Encoding.UTF8)) { var serializer = new JsonSerializer(); serializer.Serialize(writer, response); } } }
public async Task WriteCharArrayAsync_WritesToStream(int byteLength) { // Arrange var stream = new TestMemoryStream(); var writer = new HttpResponseStreamWriter(stream, Encoding.UTF8); // Act using (writer) { await writer.WriteAsync((new string('a', byteLength)).ToCharArray()); } // Assert Assert.Equal(byteLength, stream.Length); }
public static void Main(string[] args) { var config = new Config(args); Logger.Init(config.DiscordLog); var masterData = new MasterData(config); var userBase = new UserBase(config, masterData); var serverBase = new ServerBase(config); Task.Run(async() => //Debug task { DateTime lastLog = DateTime.Now; while (true) { if ((DateTime.Now - lastLog).TotalSeconds > config.DebugTime) { lastLog = DateTime.Now; userBase.DebugUsers(); serverBase.DebugServers(); } await Task.Delay(10000); } }); Task.Run(async() => //Console task { while (true) { string[] cmd = Console.ReadLine().Split(' '); switch (cmd[0]) { case "set": var arg = cmd.Skip(1).ToArray(); if (arg.Length == 2) { config.AppendArgs(arg); } break; case "save": await userBase.Save(); break; case "debug": userBase.DebugUsers(); serverBase.DebugServers(); break; case "reload": await masterData.Reload(); break; default: Logger.Log("CONSOLE unknown command"); break; } await Task.Delay(1000); } }); var host = new WebHostBuilder() .UseKestrel((o) => o.Listen(IPAddress.Any, 8856)) //.UseContentRoot(Directory.GetCurrentDirectory()) .ConfigureAppConfiguration((hostingContext, sconfig) => { sconfig.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true).AddEnvironmentVariables(); }) .ConfigureLogging((hostingContext, l) => { l.AddConfiguration(hostingContext.Configuration.GetSection("Logging")); l.SetMinimumLevel(LogLevel.Warning); l.AddConsole(); l.AddProvider(new DiscordProvider()); }) .UseIISIntegration() .ConfigureServices(s => s.AddRouting()) .Configure(app => { // define all API endpoints app.UseRouter(r => { //Server //ReqConfig r.MapGet("config", async(request, response, routeData) => { response.WriteJson(masterData.GetParams()); }); //ReqClient r.MapPost("client", async(request, response, routeData) => { var req = request.HttpContext.ReadFromJson <ReqClient>(); response.WriteJson(await userBase.GetClinetData(req, masterData.GetSkins())); }); //ReqState r.MapPost("state", async(request, response, routeData) => { var ip = request.HttpContext.Connection.RemoteIpAddress; var req = request.HttpContext.ReadFromJson <ReqState>(); serverBase.UpdateServer(req, ip); }); //ReqSendStatus r.MapPost("sendstatus", async(request, response, routeData) => { var req = request.HttpContext.ReadFromJson <ReqSendStatus>(); var resp = await userBase.UpdateUserStatus(req); response.WriteJson(resp); }); //Client //ReqRegister r.MapPost("register", async(request, response, routeData) => { var req = request.HttpContext.ReadFromJson <ReqRegister>(); var resp = await userBase.RegisterUser(req); response.WriteJson(resp); }); //ReqUserStatus r.MapPost("userstatus", async(request, response, routeData) => { var req = request.HttpContext.ReadFromJson <ReqUserStatus>(); var resp = await userBase.GetUserStatus(req); if (resp == null) { using (var writer = new HttpResponseStreamWriter(response.Body, Encoding.UTF8)) { writer.WriteLine("empty"); } } else { response.WriteJson(resp); } }); //ReqLeaderboard r.MapPost("leaderboard", async(request, response, routeData) => { var req = request.HttpContext.ReadFromJson <ReqLeaderboard>(); var resp = await userBase.GetLeaderboard(req); response.WriteJson(resp); }); //ReqServer r.MapPost("server", async(request, response, routeData) => { var req = request.HttpContext.ReadFromJson <ReqServer>(); await userBase.SetDoubleUnits(req.UserId, req.DoubleUnits); var server = serverBase.FindServer(req.ServerVersion, req.GameMode); if (server != null) { response.WriteJson(new RespServer() { Address = server.Address.ToString(), Port = server.Port }); } else { response.WriteJson(new RespServer() { Address = "", Port = 0 }); } }); //ReqMessages r.MapPost("messages", async(request, response, routeData) => { var req = request.HttpContext.ReadFromJson <ReqMessages>(); var resp = masterData.GetMessages(req); response.WriteJson(resp); }); //ReqSkinInfo r.MapPost("skininfo", async(request, response, routeData) => { var req = request.HttpContext.ReadFromJson <ReqSkinInfo>(); var resp = await userBase.GetSkinInfo(req); response.WriteJson(resp); }); //ReqRestore r.MapPost("restore", async(request, response, routeData) => { var req = request.HttpContext.ReadFromJson <ReqRestore>(); var resp = await userBase.RestoreUser(req); response.WriteJson(resp); }); //Both //ReqUnits r.MapGet("units", async(request, response, routeData) => { var resp = masterData.GetUnits(); response.WriteJson(resp); }); }); }) .Build(); Logger.Log("SERVER starting server"); host.Run(); userBase.Dispose(); Logger.Stop(); }
public override Task WriteResponseBodyAsync(OutputFormatterContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } var response = context.HttpContext.Response; var selectedEncoding = context.SelectedEncoding; using (var writer = new HttpResponseStreamWriter(response.Body, selectedEncoding)) { WriteObject(writer, context.Object); } return Task.FromResult(true); }
public static void Run() { var host = new WebHostBuilder() .UseUrls("http://*:5000") .ConfigureServices(services => { // Use a custom server services.AddTransient <IServer, HttpServer>(); }) // .UseKestrel() .Configure(app => { app.Run(context => { if (context.Request.Path.StartsWithSegments("/plaintext")) { context.Response.StatusCode = 200; context.Response.ContentType = "text/plain"; // HACK: Setting the Content-Length header manually avoids the cost of serializing the int to a string. // This is instead of: httpContext.Response.ContentLength = _helloWorldPayload.Length; context.Response.Headers["Content-Length"] = "13"; return(context.Response.Body.WriteAsync(_helloWorldPayload, 0, _helloWorldPayload.Length)); } else if (context.Request.Path.StartsWithSegments("/json")) { context.Response.ContentType = "application/json"; context.Response.ContentLength = 3072; var model = BigModels.About100Fields; var outputWriter = new StreamWriter(context.Response.Body, _utf8Encoding); var jsonWriter = new JsonTextWriter(outputWriter); _json.Serialize(outputWriter, model); jsonWriter.Flush(); outputWriter.Flush(); } else if (context.Request.Path.StartsWithSegments("/jsonpool")) { context.Response.ContentType = "application/json"; context.Response.ContentLength = 3072; var model = BigModels.About100Fields; var outputWriter = new HttpResponseStreamWriter(context.Response.Body, _utf8Encoding); var jsonWriter = new JsonTextWriter(outputWriter); jsonWriter.ArrayPool = new JsonArrayPool <char>(ArrayPool <char> .Shared); _json.Serialize(outputWriter, model); jsonWriter.Flush(); outputWriter.Flush(); } else if (context.Request.Path.StartsWithSegments("/jsonbuffered")) { context.Response.ContentType = "application/json"; var model = BigModels.About100Fields; var ms = new MemoryStream(); var outputWriter = new StreamWriter(ms, _utf8Encoding); var jsonWriter = new JsonTextWriter(outputWriter); _json.Serialize(outputWriter, model); context.Response.ContentLength = ms.Length; ms.Position = 0; return(ms.CopyToAsync(context.Response.Body)); } else if (context.Request.Path.StartsWithSegments("/jsonbufferedpool")) { context.Response.ContentType = "application/json"; var model = BigModels.About100Fields; var ms = new MemoryStream(); var outputWriter = new HttpResponseStreamWriter(ms, _utf8Encoding); var jsonWriter = new JsonTextWriter(outputWriter); jsonWriter.ArrayPool = new JsonArrayPool <char>(ArrayPool <char> .Shared); _json.Serialize(outputWriter, model); context.Response.ContentLength = ms.Length; ms.Position = 0; return(ms.CopyToAsync(context.Response.Body)); } // REVIEW: Echo is broken for now because of handling of content length else if (context.Request.Path.StartsWithSegments("/jsonecho")) { var inputReader = new StreamReader(context.Request.Body, _utf8Encoding); var jsonReader = new JsonTextReader(inputReader); Pet value = _json.Deserialize <Pet>(jsonReader); var outputWriter = new StreamWriter(context.Response.Body, _utf8Encoding); var jsonWriter = new JsonTextWriter(outputWriter); _json.Serialize(outputWriter, value); jsonWriter.Flush(); } else if (context.Request.Path.StartsWithSegments("/jsonechopool")) { var inputReader = new StreamReader(context.Request.Body, _utf8Encoding); var jsonReader = new JsonTextReader(inputReader); jsonReader.ArrayPool = new JsonArrayPool <char>(ArrayPool <char> .Shared); Pet value = _json.Deserialize <Pet>(jsonReader); var outputWriter = new StreamWriter(context.Response.Body, _utf8Encoding); var jsonWriter = new JsonTextWriter(outputWriter); jsonWriter.ArrayPool = new JsonArrayPool <char>(ArrayPool <char> .Shared); _json.Serialize(outputWriter, value); jsonWriter.Flush(); } return(Task.CompletedTask); }); }) .Build(); host.Run(); }
private async Task ProcessBodyAsync(HttpContext httpContext, string charSet) { JsonElement json; if (string.Equals(charSet, Encoding.UTF8.WebName, StringComparison.OrdinalIgnoreCase)) { json = await JsonSerializer.DeserializeAsync <JsonElement>(httpContext.Request.Body); } else { using (var reader = new HttpRequestStreamReader(httpContext.Request.Body, Encoding.GetEncoding(charSet))) { var text = await reader.ReadToEndAsync(); json = JsonSerializer.Deserialize <JsonElement>(text); } } Stream originalBody; Stream body; string originalContentType; string contentType; // Check whether to use data or data_base64 as per https://github.com/cloudevents/spec/blob/v1.0.1/json-format.md#31-handling-of-data var isDataSet = json.TryGetProperty("data", out var data); var isBinaryDataSet = json.TryGetProperty("data_base64", out var binaryData); if (isDataSet && isBinaryDataSet) { httpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest; return; } else if (isDataSet) { contentType = this.GetDataContentType(json, out var isJson); // If the value is anything other than a JSON string, treat it as JSON. Cloud Events requires // non-JSON text to be enclosed in a JSON string. isJson |= data.ValueKind != JsonValueKind.String; body = new MemoryStream(); if (isJson || options.SuppressJsonDecodingOfTextPayloads) { // Rehydrate body from JSON payload await JsonSerializer.SerializeAsync <JsonElement>(body, data); } else { // Rehydrate body from contents of the string var text = data.GetString(); using var writer = new HttpResponseStreamWriter(body, Encoding.UTF8); writer.Write(text); } body.Seek(0L, SeekOrigin.Begin); } else if (isBinaryDataSet) { // As per the spec, if the implementation determines that the type of data is Binary, // the value MUST be represented as a JSON string expression containing the Base64 encoded // binary value, and use the member name data_base64 to store it inside the JSON object. var decodedBody = binaryData.GetBytesFromBase64(); body = new MemoryStream(decodedBody); body.Seek(0L, SeekOrigin.Begin); contentType = this.GetDataContentType(json, out _); } else { body = new MemoryStream(); contentType = null; } originalBody = httpContext.Request.Body; originalContentType = httpContext.Request.ContentType; try { httpContext.Request.Body = body; httpContext.Request.ContentType = contentType; await this.next(httpContext); } finally { httpContext.Request.ContentType = originalContentType; httpContext.Request.Body = originalBody; } }
public async Task FlushWriteThrows_DontFlushInDispose(int byteLength) { // Arrange var stream = new TestMemoryStream() { ThrowOnWrite = true }; var writer = new HttpResponseStreamWriter(stream, Encoding.UTF8); await writer.WriteAsync(new string('a', byteLength)); await Assert.ThrowsAsync<IOException>(() => writer.FlushAsync()); // Act writer.Dispose(); // Assert Assert.Equal(1, stream.WriteAsyncCallCount); Assert.Equal(0, stream.WriteCallCount); Assert.Equal(0, stream.FlushCallCount); Assert.Equal(0, stream.FlushAsyncCallCount); Assert.Equal(0, stream.Length); }
public async Task FlushesBuffer_OnDispose(int byteLength) { // Arrange var stream = new TestMemoryStream(); var writer = new HttpResponseStreamWriter(stream, Encoding.UTF8); await writer.WriteAsync(new string('a', byteLength)); // Act writer.Dispose(); // Assert Assert.Equal(0, stream.FlushCallCount); Assert.Equal(0, stream.FlushAsyncCallCount); Assert.Equal(byteLength, stream.Length); }
public async Task NoDataWritten_FlushAsync_DoesNotFlushUnderlyingStream() { // Arrange var stream = new TestMemoryStream(); var writer = new HttpResponseStreamWriter(stream, Encoding.UTF8); // Act await writer.FlushAsync(); // Assert Assert.Equal(0, stream.FlushAsyncCallCount); Assert.Equal(0, stream.Length); }
/// <inheritdoc /> public virtual async Task ExecuteAsync(ActionContext context, ViewComponentResult result) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (result == null) { throw new ArgumentNullException(nameof(result)); } var response = context.HttpContext.Response; var viewData = result.ViewData; if (viewData == null) { viewData = new ViewDataDictionary(_modelMetadataProvider, context.ModelState); } var tempData = result.TempData; if (tempData == null) { tempData = _tempDataDictionaryFactory.GetTempData(context.HttpContext); } ResponseContentTypeHelper.ResolveContentTypeAndEncoding( result.ContentType, response.ContentType, ViewExecutor.DefaultContentType, out var resolvedContentType, out var resolvedContentTypeEncoding); response.ContentType = resolvedContentType; if (result.StatusCode != null) { response.StatusCode = result.StatusCode.Value; } // Opt into sync IO support until we can work out an alternative https://github.com/aspnet/AspNetCore/issues/6397 var syncIOFeature = context.HttpContext.Features.Get <Http.Features.IHttpBodyControlFeature>(); if (syncIOFeature != null) { syncIOFeature.AllowSynchronousIO = true; } using (var writer = new HttpResponseStreamWriter(response.Body, resolvedContentTypeEncoding)) { var viewContext = new ViewContext( context, NullView.Instance, viewData, tempData, writer, _htmlHelperOptions); OnExecuting(viewContext); // IViewComponentHelper is stateful, we want to make sure to retrieve it every time we need it. var viewComponentHelper = context.HttpContext.RequestServices.GetRequiredService <IViewComponentHelper>(); (viewComponentHelper as IViewContextAware)?.Contextualize(viewContext); var viewComponentResult = await GetViewComponentResult(viewComponentHelper, _logger, result); viewComponentResult.WriteTo(writer, _htmlEncoder); } }
/// <summary> /// Asynchronously renders the specified <paramref name="view"/> to the response body. /// </summary> /// <param name="view">The <see cref="IView"/> to render.</param> /// <param name="actionContext">The <see cref="ActionContext"/> for the current executing action.</param> /// <param name="viewData">The <see cref="ViewDataDictionary"/> for the view being rendered.</param> /// <param name="tempData">The <see cref="ITempDataDictionary"/> for the view being rendered.</param> /// <returns>A <see cref="Task"/> that represents the asynchronous rendering.</returns> public static async Task ExecuteAsync( IView view, ActionContext actionContext, ViewDataDictionary viewData, ITempDataDictionary tempData, HtmlHelperOptions htmlHelperOptions, MediaTypeHeaderValue contentType) { if (view == null) { throw new ArgumentNullException(nameof(view)); } if (actionContext == null) { throw new ArgumentNullException(nameof(actionContext)); } if (viewData == null) { throw new ArgumentNullException(nameof(viewData)); } if (tempData == null) { throw new ArgumentNullException(nameof(tempData)); } if (htmlHelperOptions == null) { throw new ArgumentNullException(nameof(htmlHelperOptions)); } var response = actionContext.HttpContext.Response; if (contentType != null && contentType.Encoding == null) { // Do not modify the user supplied content type, so copy it instead contentType = contentType.Copy(); contentType.Encoding = Encoding.UTF8; } // Priority list for setting content-type: // 1. passed in contentType (likely set by the user on the result) // 2. response.ContentType (likely set by the user in controller code) // 3. ViewExecutor.DefaultContentType (sensible default) response.ContentType = contentType?.ToString() ?? response.ContentType ?? DefaultContentType.ToString(); using (var writer = new HttpResponseStreamWriter(response.Body, contentType?.Encoding ?? DefaultContentType.Encoding)) { var viewContext = new ViewContext( actionContext, view, viewData, tempData, writer, htmlHelperOptions); await view.RenderAsync(viewContext); // Invoke FlushAsync to ensure any buffered content is asynchronously written to the underlying // response. In the absence of this line, the buffer gets synchronously written to the response // as part of the Dispose which has a perf impact. await writer.FlushAsync(); } }
public async Task WritesData_InExpectedEncoding(string data, string encodingName) { // Arrange var encoding = Encoding.GetEncoding(encodingName); var expectedBytes = encoding.GetBytes(data); var stream = new MemoryStream(); var writer = new HttpResponseStreamWriter(stream, encoding); // Act using (writer) { await writer.WriteAsync(data); } // Assert Assert.Equal(expectedBytes, stream.ToArray()); }
/// <inheritdoc /> public virtual async Task ExecuteAsync(ActionContext context, ViewComponentResult result) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (result == null) { throw new ArgumentNullException(nameof(result)); } var response = context.HttpContext.Response; var viewData = result.ViewData; if (viewData == null) { viewData = new ViewDataDictionary(_modelMetadataProvider, context.ModelState); } var tempData = result.TempData; if (tempData == null) { tempData = _tempDataDictionaryFactory.GetTempData(context.HttpContext); } ResponseContentTypeHelper.ResolveContentTypeAndEncoding( result.ContentType, response.ContentType, ViewExecutor.DefaultContentType, out var resolvedContentType, out var resolvedContentTypeEncoding); response.ContentType = resolvedContentType; if (result.StatusCode != null) { response.StatusCode = result.StatusCode.Value; } using (var writer = new HttpResponseStreamWriter(response.Body, resolvedContentTypeEncoding)) { var viewContext = new ViewContext( context, NullView.Instance, viewData, tempData, writer, _htmlHelperOptions); // IViewComponentHelper is stateful, we want to make sure to retrieve it every time we need it. var viewComponentHelper = context.HttpContext.RequestServices.GetRequiredService <IViewComponentHelper>(); (viewComponentHelper as IViewContextAware)?.Contextualize(viewContext); var viewComponentResult = await GetViewComponentResult(viewComponentHelper, _logger, result); viewComponentResult.WriteTo(writer, _htmlEncoder); } }
public async Task Invoke(HttpContext context) { PathString subpath; if (!context.Request.Path.StartsWithSegments(_options.Path, out subpath)) { await _next(context); return; } var policyName = subpath.ToUriComponent().Trim('/'); if (policyName.Length == 0) { policyName = Constants.DefaultPolicy; } if (_options.AuthorizationPolicy != null) { var principal = await SecurityHelper.GetUserPrincipal(context, _options.AuthorizationPolicy); if (!await _authorizationService.AuthorizeAsync(principal, context, _options.AuthorizationPolicy)) { _logger.AuthorizationFailed(); await _next(context); return; } } HealthCheckPolicy policy = _policyProvider.GetPolicy(policyName); if (policy == null) { _logger.InvalidPolicy(policyName); await _next(context); return; } var response = context.Response; var healthCheckResponse = await _healthService.CheckHealthAsync(policy); if (healthCheckResponse.HasErrors) { _logger.HealthCheckFailed(healthCheckResponse.Errors); if (healthCheckResponse.HasCriticalErrors) { response.StatusCode = StatusCodes.Status503ServiceUnavailable; response.WriteRetryAfterHeader(healthCheckResponse.RetryAfter); } } else { _logger.HealthCheckSucceeded(); response.StatusCode = StatusCodes.Status200OK; } if (_options.SendResults && !HttpMethods.IsHead(context.Request.Method)) { response.ContentType = ApplicationJson; using (var writer = new HttpResponseStreamWriter(response.Body, Encoding.UTF8, 1024, _bytePool, _charPool)) { using (var jsonWriter = new JsonTextWriter(writer)) { jsonWriter.ArrayPool = _jsonCharPool; jsonWriter.CloseOutput = false; _jsonSerializer.Serialize(jsonWriter, healthCheckResponse.Results); } } } }
public void HttpResponseStreamWriter_UsingPooledBuffers() { // Arrange var encoding = Encoding.UTF8; var stream = new MemoryStream(); var expectedBytes = encoding.GetBytes("Hello, World!"); using (var writer = new HttpResponseStreamWriter( stream, encoding, 1024, ArrayPool<byte>.Shared, ArrayPool<char>.Shared)) { // Act writer.Write("Hello, World!"); } // Assert Assert.Equal(expectedBytes, stream.ToArray()); }