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);
        }
Пример #2
0
        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 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());
        }
Пример #4
0
        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);
    }
Пример #8
0
        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);
        }
Пример #9
0
        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);
    }
Пример #12
0
        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);
                }
            }
        }
Пример #13
0
        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);
                    }
                }
            }));
        }
Пример #14
0
        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));
            }
        }
Пример #15
0
        /// <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();
                }
            }
        }
Пример #16
0
        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);
            }
        }
Пример #17
0
        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);
    }
Пример #20
0
        /// <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());
    }
Пример #23
0
        /// <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);
    }
Пример #25
0
        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);
        }
Пример #27
0
        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();
        }
Пример #28
0
        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);
        }
Пример #29
0
        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();
        }
        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);
        }
        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 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 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);
        }
Пример #36
0
        /// <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);
            }
        }
Пример #37
0
        /// <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());
        }
Пример #39
0
        /// <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 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);
        }
Пример #42
0
        /// <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 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());
        }