privatize IConnection and HttpConnection (#2105)

This commit is contained in:
Andrew Stanton-Nurse 2018-04-20 10:14:54 -07:00 committed by GitHub
parent 3b8243d203
commit dacea904cc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 65 additions and 45 deletions

View File

@ -1,10 +1,13 @@
// Copyright (c) .NET Foundation. All rights reserved. // Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
import { HttpConnection, HttpTransportType, IHttpConnectionOptions, LogLevel, TransferFormat } from "@aspnet/signalr"; import { HttpTransportType, IHttpConnectionOptions, LogLevel, TransferFormat } from "@aspnet/signalr";
import { eachTransport, ECHOENDPOINT_URL } from "./Common"; import { eachTransport, ECHOENDPOINT_URL } from "./Common";
import { TestLogger } from "./TestLogger"; import { TestLogger } from "./TestLogger";
// We want to continue testing HttpConnection, but we don't export it anymore. So just pull it in directly from the source file.
import { HttpConnection } from "../../signalr/src/HttpConnection";
const commonOptions: IHttpConnectionOptions = { const commonOptions: IHttpConnectionOptions = {
logMessageContent: true, logMessageContent: true,
logger: TestLogger.instance, logger: TestLogger.instance,

View File

@ -4,7 +4,6 @@
console.log("SignalR Functional Tests Loaded"); console.log("SignalR Functional Tests Loaded");
import "es6-promise/dist/es6-promise.auto.js"; import "es6-promise/dist/es6-promise.auto.js";
import "./ConnectionTests";
import "./HubConnectionTests"; import "./HubConnectionTests";
import "./WebDriverReporter"; import "./WebDriverReporter";
import "./WebSocketTests"; import "./WebSocketTests";

View File

@ -1,7 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved. // Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
import { HttpRequest } from "../src/index"; import { HttpRequest } from "../src/HttpClient";
import { TestHttpClient } from "./TestHttpClient"; import { TestHttpClient } from "./TestHttpClient";
import { asyncit as it } from "./Utils"; import { asyncit as it } from "./Utils";

View File

@ -1,9 +1,9 @@
// Copyright (c) .NET Foundation. All rights reserved. // Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
import { HttpResponse } from "../src/HttpClient";
import { HttpConnection } from "../src/HttpConnection"; import { HttpConnection } from "../src/HttpConnection";
import { IHttpConnectionOptions } from "../src/HttpConnection"; import { IHttpConnectionOptions } from "../src/IHttpConnectionOptions";
import { HttpResponse } from "../src/index";
import { HttpTransportType, ITransport, TransferFormat } from "../src/ITransport"; import { HttpTransportType, ITransport, TransferFormat } from "../src/ITransport";
import { eachEndpointUrl, eachTransport } from "./Common"; import { eachEndpointUrl, eachTransport } from "./Common";
import { TestHttpClient } from "./TestHttpClient"; import { TestHttpClient } from "./TestHttpClient";
@ -435,16 +435,26 @@ describe("HttpConnection", () => {
it("authorization header removed when token factory returns null and using LongPolling", async (done) => { it("authorization header removed when token factory returns null and using LongPolling", async (done) => {
const availableTransport = { transport: "LongPolling", transferFormats: ["Text"] }; const availableTransport = { transport: "LongPolling", transferFormats: ["Text"] };
var httpClientGetCount = 0; let httpClientGetCount = 0;
var accessTokenFactoryCount = 0; let accessTokenFactoryCount = 0;
const options: IHttpConnectionOptions = { const options: IHttpConnectionOptions = {
...commonOptions, ...commonOptions,
accessTokenFactory: () => {
accessTokenFactoryCount++;
if (accessTokenFactoryCount === 1) {
return "A token value";
} else {
// Return a null value after the first call to test the header being removed
return null;
}
},
httpClient: new TestHttpClient() httpClient: new TestHttpClient()
.on("POST", (r) => ({ connectionId: "42", availableTransports: [availableTransport] })) .on("POST", (r) => ({ connectionId: "42", availableTransports: [availableTransport] }))
.on("GET", (r) => { .on("GET", (r) => {
httpClientGetCount++; httpClientGetCount++;
// tslint:disable-next-line:no-string-literal
const authorizationValue = r.headers["Authorization"]; const authorizationValue = r.headers["Authorization"];
if (httpClientGetCount == 1) { if (httpClientGetCount === 1) {
if (authorizationValue) { if (authorizationValue) {
fail("First long poll request should have a authorization header."); fail("First long poll request should have a authorization header.");
} }
@ -458,15 +468,6 @@ describe("HttpConnection", () => {
throw new Error("fail"); throw new Error("fail");
} }
}), }),
accessTokenFactory: () => {
accessTokenFactoryCount++;
if (accessTokenFactoryCount == 1) {
return "A token value";
} else {
// Return a null value after the first call to test the header being removed
return null;
}
},
} as IHttpConnectionOptions; } as IHttpConnectionOptions;
const connection = new HttpConnection("http://tempuri.org", options); const connection = new HttpConnection("http://tempuri.org", options);
@ -485,14 +486,14 @@ describe("HttpConnection", () => {
it("sets inherentKeepAlive feature when using LongPolling", async (done) => { it("sets inherentKeepAlive feature when using LongPolling", async (done) => {
const availableTransport = { transport: "LongPolling", transferFormats: ["Text"] }; const availableTransport = { transport: "LongPolling", transferFormats: ["Text"] };
var httpClientGetCount = 0; let httpClientGetCount = 0;
const options: IHttpConnectionOptions = { const options: IHttpConnectionOptions = {
...commonOptions, ...commonOptions,
httpClient: new TestHttpClient() httpClient: new TestHttpClient()
.on("POST", (r) => ({ connectionId: "42", availableTransports: [availableTransport] })) .on("POST", (r) => ({ connectionId: "42", availableTransports: [availableTransport] }))
.on("GET", (r) => { .on("GET", (r) => {
httpClientGetCount++; httpClientGetCount++;
if (httpClientGetCount == 1) { if (httpClientGetCount === 1) {
// First long polling request must succeed so start completes // First long polling request must succeed so start completes
return ""; return "";
} else { } else {

View File

@ -1,11 +1,12 @@
// Copyright (c) .NET Foundation. All rights reserved. // Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
import { HubConnection, JsonHubProtocol } from "../src/HubConnection"; import { HubConnection } from "../src/HubConnection";
import { IConnection } from "../src/IConnection"; import { IConnection } from "../src/IConnection";
import { HubMessage, IHubProtocol, MessageType } from "../src/IHubProtocol"; import { HubMessage, IHubProtocol, MessageType } from "../src/IHubProtocol";
import { ILogger, LogLevel } from "../src/ILogger"; import { ILogger, LogLevel } from "../src/ILogger";
import { HttpTransportType, ITransport, TransferFormat } from "../src/ITransport"; import { HttpTransportType, ITransport, TransferFormat } from "../src/ITransport";
import { JsonHubProtocol } from "../src/JsonHubProtocol";
import { NullLogger } from "../src/Loggers"; import { NullLogger } from "../src/Loggers";
import { IStreamSubscriber } from "../src/Stream"; import { IStreamSubscriber } from "../src/Stream";
import { TextMessageFormat } from "../src/TextMessageFormat"; import { TextMessageFormat } from "../src/TextMessageFormat";
@ -13,7 +14,7 @@ import { TextMessageFormat } from "../src/TextMessageFormat";
import { asyncit as it, captureException, delay, PromiseSource } from "./Utils"; import { asyncit as it, captureException, delay, PromiseSource } from "./Utils";
function createHubConnection(connection: IConnection, logger?: ILogger, protocol?: IHubProtocol) { function createHubConnection(connection: IConnection, logger?: ILogger, protocol?: IHubProtocol) {
return new HubConnection(connection, logger || NullLogger.instance, protocol || new JsonHubProtocol()); return HubConnection.create(connection, logger || NullLogger.instance, protocol || new JsonHubProtocol());
} }
describe("HubConnection", () => { describe("HubConnection", () => {

View File

@ -3,13 +3,14 @@
import { HubConnectionBuilder } from "../src/HubConnectionBuilder"; import { HubConnectionBuilder } from "../src/HubConnectionBuilder";
import { HubConnection } from "../src";
import { HttpRequest, HttpResponse } from "../src/HttpClient"; import { HttpRequest, HttpResponse } from "../src/HttpClient";
import { IHttpConnectionOptions } from "../src/HttpConnection"; import { HubConnection } from "../src/HubConnection";
import { IHttpConnectionOptions } from "../src/IHttpConnectionOptions";
import { HubMessage, IHubProtocol } from "../src/IHubProtocol"; import { HubMessage, IHubProtocol } from "../src/IHubProtocol";
import { ILogger, LogLevel } from "../src/ILogger"; import { ILogger, LogLevel } from "../src/ILogger";
import { TransferFormat, HttpTransportType } from "../src/ITransport"; import { HttpTransportType, TransferFormat } from "../src/ITransport";
import { NullLogger } from "../src/Loggers"; import { NullLogger } from "../src/Loggers";
import { TestHttpClient } from "./TestHttpClient"; import { TestHttpClient } from "./TestHttpClient";
import { asyncit as it, PromiseSource } from "./Utils"; import { asyncit as it, PromiseSource } from "./Utils";
@ -123,14 +124,13 @@ describe("HubConnectionBuilder", () => {
await closed; await closed;
}); });
it("allows logger to be replaced", async () => { it("allows logger to be replaced", async () => {
let loggedMessages = 0; let loggedMessages = 0;
const logger = { const logger = {
log() { log() {
loggedMessages += 1; loggedMessages += 1;
} },
} };
const connection = createConnectionBuilder(logger) const connection = createConnectionBuilder(logger)
.withUrl("http://example.com") .withUrl("http://example.com")
.build(); .build();

View File

@ -3,6 +3,7 @@
import { DefaultHttpClient, HttpClient } from "./HttpClient"; import { DefaultHttpClient, HttpClient } from "./HttpClient";
import { IConnection } from "./IConnection"; import { IConnection } from "./IConnection";
import { IHttpConnectionOptions } from "./IHttpConnectionOptions";
import { ILogger, LogLevel } from "./ILogger"; import { ILogger, LogLevel } from "./ILogger";
import { HttpTransportType, ITransport, TransferFormat } from "./ITransport"; import { HttpTransportType, ITransport, TransferFormat } from "./ITransport";
import { LongPollingTransport } from "./LongPollingTransport"; import { LongPollingTransport } from "./LongPollingTransport";
@ -10,15 +11,6 @@ import { ServerSentEventsTransport } from "./ServerSentEventsTransport";
import { Arg, createLogger } from "./Utils"; import { Arg, createLogger } from "./Utils";
import { WebSocketTransport } from "./WebSocketTransport"; import { WebSocketTransport } from "./WebSocketTransport";
export interface IHttpConnectionOptions {
httpClient?: HttpClient;
transport?: HttpTransportType | ITransport;
logger?: ILogger | LogLevel;
accessTokenFactory?: () => string | Promise<string>;
logMessageContent?: boolean;
skipNegotiation?: boolean;
}
const enum ConnectionState { const enum ConnectionState {
Connecting, Connecting,
Connected, Connected,

View File

@ -2,7 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
import { HandshakeProtocol, HandshakeRequestMessage, HandshakeResponseMessage } from "./HandshakeProtocol"; import { HandshakeProtocol, HandshakeRequestMessage, HandshakeResponseMessage } from "./HandshakeProtocol";
import { HttpConnection, IHttpConnectionOptions } from "./HttpConnection"; import { HttpConnection } from "./HttpConnection";
import { IConnection } from "./IConnection"; import { IConnection } from "./IConnection";
import { CancelInvocationMessage, CompletionMessage, HubMessage, IHubProtocol, InvocationMessage, MessageType, StreamInvocationMessage, StreamItemMessage } from "./IHubProtocol"; import { CancelInvocationMessage, CompletionMessage, HubMessage, IHubProtocol, InvocationMessage, MessageType, StreamInvocationMessage, StreamItemMessage } from "./IHubProtocol";
import { ILogger, LogLevel } from "./ILogger"; import { ILogger, LogLevel } from "./ILogger";
@ -12,8 +12,6 @@ import { IStreamResult } from "./Stream";
import { TextMessageFormat } from "./TextMessageFormat"; import { TextMessageFormat } from "./TextMessageFormat";
import { Arg, createLogger, Subject } from "./Utils"; import { Arg, createLogger, Subject } from "./Utils";
export { JsonHubProtocol };
const DEFAULT_TIMEOUT_IN_MS: number = 30 * 1000; const DEFAULT_TIMEOUT_IN_MS: number = 30 * 1000;
export class HubConnection { export class HubConnection {
@ -30,7 +28,16 @@ export class HubConnection {
public serverTimeoutInMilliseconds: number; public serverTimeoutInMilliseconds: number;
constructor(connection: IConnection, logger: ILogger, protocol: IHubProtocol) { /** @internal */
// Using a public static factory method means we can have a private constructor and an _internal_
// create method that can be used by HubConnectionBuilder. An "internal" constructor would just
// be stripped away and the '.d.ts' file would have no constructor, which is interpreted as a
// public parameter-less constructor.
public static create(connection: IConnection, logger: ILogger, protocol: IHubProtocol): HubConnection {
return new HubConnection(connection, logger, protocol);
}
private constructor(connection: IConnection, logger: ILogger, protocol: IHubProtocol) {
Arg.isRequired(connection, "connection"); Arg.isRequired(connection, "connection");
Arg.isRequired(logger, "logger"); Arg.isRequired(logger, "logger");
Arg.isRequired(protocol, "protocol"); Arg.isRequired(protocol, "protocol");

View File

@ -1,11 +1,13 @@
// Copyright (c) .NET Foundation. All rights reserved. // Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
import { HttpConnection, IHttpConnectionOptions } from "./HttpConnection"; import { HttpConnection } from "./HttpConnection";
import { HubConnection, JsonHubProtocol } from "./HubConnection"; import { HubConnection } from "./HubConnection";
import { IHttpConnectionOptions } from "./IHttpConnectionOptions";
import { IHubProtocol } from "./IHubProtocol"; import { IHubProtocol } from "./IHubProtocol";
import { ILogger, LogLevel } from "./ILogger"; import { ILogger, LogLevel } from "./ILogger";
import { HttpTransportType } from "./ITransport"; import { HttpTransportType } from "./ITransport";
import { JsonHubProtocol } from "./JsonHubProtocol";
import { NullLogger } from "./Loggers"; import { NullLogger } from "./Loggers";
import { Arg, ConsoleLogger } from "./Utils"; import { Arg, ConsoleLogger } from "./Utils";
@ -76,7 +78,7 @@ export class HubConnectionBuilder {
} }
const connection = new HttpConnection(this.url, httpConnectionOptions); const connection = new HttpConnection(this.url, httpConnectionOptions);
return new HubConnection( return HubConnection.create(
connection, connection,
this.logger || NullLogger.instance, this.logger || NullLogger.instance,
this.protocol || new JsonHubProtocol()); this.protocol || new JsonHubProtocol());

View File

@ -0,0 +1,15 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
import { HttpClient } from "./HttpClient";
import { ILogger, LogLevel } from "./ILogger";
import { HttpTransportType, ITransport } from "./ITransport";
export interface IHttpConnectionOptions {
httpClient?: HttpClient;
transport?: HttpTransportType | ITransport;
logger?: ILogger | LogLevel;
accessTokenFactory?: () => string | Promise<string>;
logMessageContent?: boolean;
skipNegotiation?: boolean;
}

View File

@ -4,12 +4,12 @@
// Everything that users need to access must be exported here. Including interfaces. // Everything that users need to access must be exported here. Including interfaces.
export * from "./Errors"; export * from "./Errors";
export * from "./HttpClient"; export * from "./HttpClient";
export * from "./HttpConnection"; export * from "./IHttpConnectionOptions";
export * from "./HubConnection"; export * from "./HubConnection";
export * from "./HubConnectionBuilder"; export * from "./HubConnectionBuilder";
export * from "./IConnection";
export * from "./IHubProtocol"; export * from "./IHubProtocol";
export * from "./ILogger"; export * from "./ILogger";
export * from "./ITransport"; export * from "./ITransport";
export * from "./Stream"; export * from "./Stream";
export * from "./Loggers"; export * from "./Loggers";
export * from "./JsonHubProtocol";