From 240a88f7af601b8748c523585be676e4c71987e7 Mon Sep 17 00:00:00 2001 From: David Fowler Date: Fri, 19 May 2017 23:37:17 -0700 Subject: [PATCH] Make the http end points more resty (#470) - Use HTTP verbs to describe functionality for endpoints - Updated TransportProtocols.md --- .../Connection.spec.ts | 30 +- .../Connection.ts | 3 +- .../HttpClient.ts | 5 + .../Transports.ts | 15 +- samples/ClientSample/ClientSample.csproj | 3 +- samples/SocketsSample/SocketsSample.csproj | 4 + samples/SocketsSample/Startup.cs | 12 + samples/SocketsSample/wwwroot/ws.html | 2 +- specs/TransportProtocols.md | 32 ++- .../Connection.cs | 10 +- .../LongPollingTransport.cs | 6 +- .../ServerSentEventsTransport.cs | 6 +- .../WebSocketsTransport.cs | 2 - .../HttpConnectionDispatcher.cs | 52 +++- .../Transports/LongPollingTransport.cs | 8 +- .../Transports/WebSocketsTransport.cs | 7 +- .../ConnectionTests.cs | 13 +- .../LongPollingTransportTests.cs | 6 +- .../EndToEndTests.cs | 2 +- .../HttpConnectionDispatcherTests.cs | 267 +++++++++++------- .../LongPollingTests.cs | 3 +- 21 files changed, 308 insertions(+), 180 deletions(-) diff --git a/client-ts/Microsoft.AspNetCore.SignalR.Client.TS.Tests/Connection.spec.ts b/client-ts/Microsoft.AspNetCore.SignalR.Client.TS.Tests/Connection.spec.ts index 1327b81432..8185c65356 100644 --- a/client-ts/Microsoft.AspNetCore.SignalR.Client.TS.Tests/Connection.spec.ts +++ b/client-ts/Microsoft.AspNetCore.SignalR.Client.TS.Tests/Connection.spec.ts @@ -9,10 +9,10 @@ describe("Connection", () => { it("starting connection fails if getting id fails", async (done) => { let options: ISignalROptions = { httpClient: { + options(url: string): Promise { + return Promise.reject("error"); + }, get(url: string): Promise { - if (url.indexOf("/negotiate") >= 0) { - return Promise.reject("error"); - } return Promise.resolve(""); } } @@ -34,9 +34,8 @@ describe("Connection", () => { it("cannot start a running connection", async (done) => { let options: ISignalROptions = { httpClient: { - get(url: string): Promise { - if (url.indexOf("/negotiate") >= 0) { - connection.start() + options(url: string): Promise { + connection.start() .then(() => { fail(); done(); @@ -47,7 +46,8 @@ describe("Connection", () => { }); return Promise.reject("error"); - } + }, + get(url: string): Promise { return Promise.resolve(""); } } @@ -67,10 +67,10 @@ describe("Connection", () => { it("cannot start a stopped connection", async (done) => { let options: ISignalROptions = { httpClient: { + options(url: string): Promise { + return Promise.reject("error"); + }, get(url: string): Promise { - if (url.indexOf("/negotiate") >= 0) { - return Promise.reject("error"); - } return Promise.resolve(""); } } @@ -100,6 +100,10 @@ describe("Connection", () => { it("can stop a starting connection", async (done) => { let options: ISignalROptions = { httpClient: { + options(url: string): Promise { + connection.stop(); + return Promise.resolve(""); + }, get(url: string): Promise { connection.stop(); return Promise.resolve(""); @@ -128,10 +132,10 @@ describe("Connection", () => { it("preserves users connection string", async done => { let options: ISignalROptions = { httpClient: { + options(url: string): Promise { + return Promise.resolve("42"); + }, get(url: string): Promise { - if (url.includes("negotiate")) { - return Promise.resolve("42"); - } return Promise.resolve(""); } } diff --git a/client-ts/Microsoft.AspNetCore.SignalR.Client.TS/Connection.ts b/client-ts/Microsoft.AspNetCore.SignalR.Client.TS/Connection.ts index bc6668d256..bb7a2f81a8 100644 --- a/client-ts/Microsoft.AspNetCore.SignalR.Client.TS/Connection.ts +++ b/client-ts/Microsoft.AspNetCore.SignalR.Client.TS/Connection.ts @@ -40,7 +40,8 @@ export class Connection implements IConnection { private async startInternal(transportType: TransportType | ITransport): Promise { try { - this.connectionId = await this.httpClient.get(`${this.url}/negotiate?${this.queryString}`); + var negotiateUrl = this.url + (this.queryString ? "?" + this.queryString : ""); + this.connectionId = await this.httpClient.options(negotiateUrl); // the user tries to stop the the connection when it is being started if (this.connectionState == ConnectionState.Disconnected) { diff --git a/client-ts/Microsoft.AspNetCore.SignalR.Client.TS/HttpClient.ts b/client-ts/Microsoft.AspNetCore.SignalR.Client.TS/HttpClient.ts index ab4dba966f..34621586ed 100644 --- a/client-ts/Microsoft.AspNetCore.SignalR.Client.TS/HttpClient.ts +++ b/client-ts/Microsoft.AspNetCore.SignalR.Client.TS/HttpClient.ts @@ -1,5 +1,6 @@ export interface IHttpClient { get(url: string, headers?: Map): Promise; + options(url: string, headers?: Map): Promise; post(url: string, content: string, headers?: Map): Promise; } @@ -8,6 +9,10 @@ export class HttpClient implements IHttpClient { return this.xhr("GET", url, headers); } + options(url: string, headers?: Map): Promise { + return this.xhr("OPTIONS", url, headers); + } + post(url: string, content: string, headers?: Map): Promise { return this.xhr("POST", url, headers, content); } diff --git a/client-ts/Microsoft.AspNetCore.SignalR.Client.TS/Transports.ts b/client-ts/Microsoft.AspNetCore.SignalR.Client.TS/Transports.ts index ba361298a1..9de3fb8176 100644 --- a/client-ts/Microsoft.AspNetCore.SignalR.Client.TS/Transports.ts +++ b/client-ts/Microsoft.AspNetCore.SignalR.Client.TS/Transports.ts @@ -22,7 +22,7 @@ export class WebSocketTransport implements ITransport { connect(url: string, queryString: string = ""): Promise { return new Promise((resolve, reject) => { url = url.replace(/^http/, "ws"); - let connectUrl = url + "/ws?" + queryString; + let connectUrl = url + (queryString ? "?" + queryString : ""); let webSocket = new WebSocket(connectUrl); @@ -81,6 +81,7 @@ export class ServerSentEventsTransport implements ITransport { private eventSource: EventSource; private url: string; private queryString: string; + private fullUrl: string; private httpClient: IHttpClient; constructor(httpClient: IHttpClient) { @@ -94,10 +95,10 @@ export class ServerSentEventsTransport implements ITransport { this.queryString = queryString; this.url = url; - let tmp = `${this.url}/sse?${this.queryString}`; + this.fullUrl = url + (queryString ? "?" + queryString : ""); return new Promise((resolve, reject) => { - let eventSource = new EventSource(`${this.url}/sse?${this.queryString}`); + let eventSource = new EventSource(this.fullUrl); try { eventSource.onmessage = (e: MessageEvent) => { @@ -139,7 +140,7 @@ export class ServerSentEventsTransport implements ITransport { } async send(data: any): Promise { - return send(this.httpClient, `${this.url}/send?${this.queryString}`, data); + return send(this.httpClient, this.fullUrl, data); } stop(): void { @@ -156,6 +157,7 @@ export class ServerSentEventsTransport implements ITransport { export class LongPollingTransport implements ITransport { private url: string; private queryString: string; + private fullUrl: string; private httpClient: IHttpClient; private pollXhr: XMLHttpRequest; private shouldPoll: boolean; @@ -168,7 +170,8 @@ export class LongPollingTransport implements ITransport { this.url = url; this.queryString = queryString; this.shouldPoll = true; - this.poll(url + "/poll?" + this.queryString) + this.fullUrl = url + (queryString ? "?" + queryString : ""); + this.poll(this.fullUrl); return Promise.resolve(); } @@ -231,7 +234,7 @@ export class LongPollingTransport implements ITransport { } async send(data: any): Promise { - return send(this.httpClient, `${this.url}/send?${this.queryString}`, data); + return send(this.httpClient, this.fullUrl, data); } stop(): void { diff --git a/samples/ClientSample/ClientSample.csproj b/samples/ClientSample/ClientSample.csproj index 0ce2d3466e..f8f21956ca 100644 --- a/samples/ClientSample/ClientSample.csproj +++ b/samples/ClientSample/ClientSample.csproj @@ -1,4 +1,4 @@ - + @@ -6,6 +6,7 @@ netcoreapp2.0 false + Exe diff --git a/samples/SocketsSample/SocketsSample.csproj b/samples/SocketsSample/SocketsSample.csproj index 33e881598a..7949e296d7 100644 --- a/samples/SocketsSample/SocketsSample.csproj +++ b/samples/SocketsSample/SocketsSample.csproj @@ -8,6 +8,9 @@ false + + + @@ -18,6 +21,7 @@ + diff --git a/samples/SocketsSample/Startup.cs b/samples/SocketsSample/Startup.cs index 93b0232efc..ed635cfc6b 100644 --- a/samples/SocketsSample/Startup.cs +++ b/samples/SocketsSample/Startup.cs @@ -21,6 +21,16 @@ namespace SocketsSample services.AddSignalR(); // .AddRedis(); + services.AddCors(o => + { + o.AddPolicy("Everything", p => + { + p.AllowAnyHeader() + .AllowAnyMethod() + .AllowAnyOrigin(); + }); + }); + services.AddEndPoint(); } @@ -34,6 +44,8 @@ namespace SocketsSample app.UseDeveloperExceptionPage(); } + app.UseCors("Everything"); + app.UseSignalR(routes => { routes.MapHub("/hubs"); diff --git a/samples/SocketsSample/wwwroot/ws.html b/samples/SocketsSample/wwwroot/ws.html index 8990fa27d3..e56f3233ed 100644 --- a/samples/SocketsSample/wwwroot/ws.html +++ b/samples/SocketsSample/wwwroot/ws.html @@ -5,7 +5,7 @@