parent
fd7707e7d2
commit
e691e1cff8
|
|
@ -1,24 +1,25 @@
|
|||
export interface IHttpClient {
|
||||
get(url: string): Promise<string>;
|
||||
post(url: string, content: string): Promise<string>;
|
||||
get(url: string, headers?: Map<string, string>): Promise<string>;
|
||||
post(url: string, content: string, headers?: Map<string, string>): Promise<string>;
|
||||
}
|
||||
|
||||
export class HttpClient implements IHttpClient {
|
||||
get(url: string): Promise<string> {
|
||||
return this.xhr("GET", url);
|
||||
get(url: string, headers?: Map<string, string>): Promise<string> {
|
||||
return this.xhr("GET", url, headers);
|
||||
}
|
||||
|
||||
post(url: string, content: string): Promise<string> {
|
||||
return this.xhr("POST", url, content);
|
||||
post(url: string, content: string, headers?: Map<string, string>): Promise<string> {
|
||||
return this.xhr("POST", url, headers, content);
|
||||
}
|
||||
|
||||
private xhr(method: string, url: string, content?: string): Promise<string> {
|
||||
private xhr(method: string, url: string, headers?: Map<string, string>, content?: string): Promise<string> {
|
||||
return new Promise<string>((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);
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ export class ServerSentEventsTransport implements ITransport {
|
|||
}
|
||||
|
||||
async send(data: any): Promise<void> {
|
||||
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<void> {
|
||||
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<string, string>();
|
||||
headers.set("Content-Type", "application/vnd.microsoft.aspnetcore.endpoint-messages.v1+text");
|
||||
|
||||
async function send(httpClient: IHttpClient, url: string, data: any): Promise<void> {
|
||||
let message = `T${data.length.toString()}:T:${data};`;
|
||||
await httpClient.post(url, message, headers);
|
||||
}
|
||||
|
|
@ -338,31 +338,24 @@ namespace Microsoft.AspNetCore.Sockets
|
|||
buffer = stream.ToArray();
|
||||
}
|
||||
|
||||
IList<Message> 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<Message>()
|
||||
{
|
||||
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<Message> ParseSendBatch(ref BytesReader payload, MessageFormat messageFormat)
|
||||
private List<Message> ParseSendBatch(ref BytesReader payload, MessageFormat messageFormat)
|
||||
{
|
||||
var messages = new List<Message>();
|
||||
|
||||
|
|
|
|||
|
|
@ -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<TestEndPoint>();
|
||||
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<TestEndPoint>("", 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)]
|
||||
|
|
|
|||
Loading…
Reference in New Issue