From e691e1cff83cce9ab1fd294ee787aba822ff0e7b Mon Sep 17 00:00:00 2001 From: moozzyk Date: Mon, 17 Apr 2017 13:15:06 -0700 Subject: [PATCH] Removing legacy raw format for `send` Fixes issues #383 and #127 --- .../HttpClient.ts | 19 +++++++------ .../Transports.ts | 12 ++++++-- .../HttpConnectionDispatcher.cs | 25 ++++++----------- .../HttpConnectionDispatcherTests.cs | 28 +++++++++++++++++-- 4 files changed, 55 insertions(+), 29 deletions(-) diff --git a/client-ts/Microsoft.AspNetCore.SignalR.Client.TS/HttpClient.ts b/client-ts/Microsoft.AspNetCore.SignalR.Client.TS/HttpClient.ts index f94d719ffe..ab4dba966f 100644 --- a/client-ts/Microsoft.AspNetCore.SignalR.Client.TS/HttpClient.ts +++ b/client-ts/Microsoft.AspNetCore.SignalR.Client.TS/HttpClient.ts @@ -1,24 +1,25 @@ export interface IHttpClient { - get(url: string): Promise; - post(url: string, content: string): Promise; + get(url: string, headers?: Map): Promise; + post(url: string, content: string, headers?: Map): Promise; } export class HttpClient implements IHttpClient { - get(url: string): Promise { - return this.xhr("GET", url); + get(url: string, headers?: Map): Promise { + return this.xhr("GET", url, headers); } - post(url: string, content: string): Promise { - return this.xhr("POST", url, content); + post(url: string, content: string, headers?: Map): Promise { + return this.xhr("POST", url, headers, content); } - private xhr(method: string, url: string, content?: string): Promise { + private xhr(method: string, url: string, headers?: Map, content?: string): Promise { return new Promise((resolve, reject) => { let xhr = new XMLHttpRequest(); + xhr.open(method, url, true); - if (method === "POST" && content != null) { - xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); + if (headers) { + headers.forEach((value, header) => xhr.setRequestHeader(header, value)); } xhr.send(content); diff --git a/client-ts/Microsoft.AspNetCore.SignalR.Client.TS/Transports.ts b/client-ts/Microsoft.AspNetCore.SignalR.Client.TS/Transports.ts index a0809063fe..ba361298a1 100644 --- a/client-ts/Microsoft.AspNetCore.SignalR.Client.TS/Transports.ts +++ b/client-ts/Microsoft.AspNetCore.SignalR.Client.TS/Transports.ts @@ -139,7 +139,7 @@ export class ServerSentEventsTransport implements ITransport { } async send(data: any): Promise { - await this.httpClient.post(this.url + "/send?" + this.queryString, data); + return send(this.httpClient, `${this.url}/send?${this.queryString}`, data); } stop(): void { @@ -231,7 +231,7 @@ export class LongPollingTransport implements ITransport { } async send(data: any): Promise { - await this.httpClient.post(this.url + "/send?" + this.queryString, data); + return send(this.httpClient, `${this.url}/send?${this.queryString}`, data); } stop(): void { @@ -245,3 +245,11 @@ export class LongPollingTransport implements ITransport { onDataReceived: DataReceived; onClosed: TransportClosed; } + +const headers = new Map(); +headers.set("Content-Type", "application/vnd.microsoft.aspnetcore.endpoint-messages.v1+text"); + +async function send(httpClient: IHttpClient, url: string, data: any): Promise { + let message = `T${data.length.toString()}:T:${data};`; + await httpClient.post(url, message, headers); +} \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Sockets/HttpConnectionDispatcher.cs b/src/Microsoft.AspNetCore.Sockets/HttpConnectionDispatcher.cs index f3dc37afa2..e3a5f4c14e 100644 --- a/src/Microsoft.AspNetCore.Sockets/HttpConnectionDispatcher.cs +++ b/src/Microsoft.AspNetCore.Sockets/HttpConnectionDispatcher.cs @@ -338,31 +338,24 @@ namespace Microsoft.AspNetCore.Sockets buffer = stream.ToArray(); } - IList messages; + MessageFormat messageFormat; if (string.Equals(context.Request.ContentType, MessageFormatter.TextContentType, StringComparison.OrdinalIgnoreCase)) { - var reader = new BytesReader(buffer); - messages = ParseSendBatch(ref reader, MessageFormat.Text); + messageFormat = MessageFormat.Text; } else if (string.Equals(context.Request.ContentType, MessageFormatter.BinaryContentType, StringComparison.OrdinalIgnoreCase)) { - var reader = new BytesReader(buffer); - messages = ParseSendBatch(ref reader, MessageFormat.Binary); + messageFormat = MessageFormat.Binary; } else { - // Legacy, single message raw format - - var format = - string.Equals(context.Request.Query["format"], "binary", StringComparison.OrdinalIgnoreCase) - ? MessageType.Binary - : MessageType.Text; - messages = new List() - { - new Message(buffer, format, endOfMessage: true) - }; + context.Response.StatusCode = StatusCodes.Status400BadRequest; + await context.Response.WriteAsync($"'{context.Request.ContentType}' is not a valid Content-Type for send requests."); + return; } + var reader = new BytesReader(buffer); + var messages = ParseSendBatch(ref reader, messageFormat); // REVIEW: Do we want to return a specific status code here if the connection has ended? _logger.LogDebug("Received batch of {0} message(s) in '/send'", messages.Count); @@ -449,7 +442,7 @@ namespace Microsoft.AspNetCore.Sockets return connectionState; } - private IList ParseSendBatch(ref BytesReader payload, MessageFormat messageFormat) + private List ParseSendBatch(ref BytesReader payload, MessageFormat messageFormat) { var messages = new List(); diff --git a/test/Microsoft.AspNetCore.Sockets.Tests/HttpConnectionDispatcherTests.cs b/test/Microsoft.AspNetCore.Sockets.Tests/HttpConnectionDispatcherTests.cs index 5250162055..bc45397869 100644 --- a/test/Microsoft.AspNetCore.Sockets.Tests/HttpConnectionDispatcherTests.cs +++ b/test/Microsoft.AspNetCore.Sockets.Tests/HttpConnectionDispatcherTests.cs @@ -109,6 +109,32 @@ namespace Microsoft.AspNetCore.Sockets.Tests } } + [Fact] + public async Task SendRequestsWithInvalidContentTypeAreRejected() + { + var manager = CreateConnectionManager(); + var connectionState = manager.CreateConnection(); + var dispatcher = new HttpConnectionDispatcher(manager, new LoggerFactory()); + using (var strm = new MemoryStream()) + { + var context = new DefaultHttpContext(); + var services = new ServiceCollection(); + services.AddOptions(); + services.AddEndPoint(); + context.RequestServices = services.BuildServiceProvider(); + context.Request.Path = "/send"; + context.Request.QueryString = new QueryString($"?id={connectionState.Connection.ConnectionId}"); + context.Request.ContentType = "text/plain"; + context.Response.Body = strm; + + await dispatcher.ExecuteAsync("", context); + + Assert.Equal(StatusCodes.Status400BadRequest, context.Response.StatusCode); + await strm.FlushAsync(); + Assert.Equal("'text/plain' is not a valid Content-Type for send requests.", Encoding.UTF8.GetString(strm.ToArray())); + } + } + [Theory] [InlineData(TransportType.LongPolling, 204)] [InlineData(TransportType.WebSockets, 404)] @@ -417,8 +443,6 @@ namespace Microsoft.AspNetCore.Sockets.Tests } [Theory] - [InlineData("", "text", "Hello, World", "Hello, World", MessageType.Text)] // Legacy format - [InlineData("", "binary", "Hello, World", "Hello, World", MessageType.Binary)] // Legacy format [InlineData(TextContentType, null, "T12:T:Hello, World;", "Hello, World", MessageType.Text)] [InlineData(TextContentType, null, "T16:B:SGVsbG8sIFdvcmxk;", "Hello, World", MessageType.Binary)] [InlineData(TextContentType, null, "T12:E:Hello, World;", "Hello, World", MessageType.Error)]