Skip to content

Commit

Permalink
Reuse azure logger and move endpoint setting into options (#18359)
Browse files Browse the repository at this point in the history
  • Loading branch information
vicancy authored Oct 27, 2021
1 parent f2a1e38 commit 518dc80
Show file tree
Hide file tree
Showing 15 changed files with 140 additions and 117 deletions.
1 change: 1 addition & 0 deletions sdk/web-pubsub/web-pubsub-express/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
"sideEffects": false,
"dependencies": {
"tslib": "^2.2.0",
"@azure/logger": "^1.0.0",
"cloudevents": "^4.0.0"
},
"devDependencies": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export interface ConnectRequest {
claims?: Record<string, string[]>;
clientCertificates?: Certificate[];
context: ConnectionContext;
headers?: Record<string, string[]>;
queries?: Record<string, string[]>;
subprotocols?: string[];
}
Expand Down Expand Up @@ -77,22 +78,21 @@ export interface UserEventResponseHandler {

// @public
export class WebPubSubEventHandler {
constructor(hub: string, allowedEndpoints: string[], options?: WebPubSubEventHandlerOptions);
constructor(hub: string, options?: WebPubSubEventHandlerOptions);
getMiddleware(): express.RequestHandler;
readonly path: string;
}

// @public
export interface WebPubSubEventHandlerOptions {
dumpRequest?: boolean;
allowedEndpoints?: string[];
handleConnect?: (connectRequest: ConnectRequest, connectResponse: ConnectResponseHandler) => void;
handleUserEvent?: (userEventRequest: UserEventRequest, userEventResponse: UserEventResponseHandler) => void;
onConnected?: (connectedRequest: ConnectedRequest) => void;
onDisconnected?: (disconnectedRequest: DisconnectedRequest) => void;
path?: string;
}


// (No @packageDocumentation comment for this package)

```
6 changes: 3 additions & 3 deletions sdk/web-pubsub/web-pubsub-express/samples-dev/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@
import { WebPubSubEventHandler } from "@azure/web-pubsub-express";
import express from "express";

const handler = new WebPubSubEventHandler("chat", ["https://xxx.webpubsub.azure.com"], {
dumpRequest: false,
const handler = new WebPubSubEventHandler("chat", {
handleConnect(req, res) {
console.log(req);
// You can set the state for the connection, it lasts throughout the lifetime of the connection
Expand All @@ -27,7 +26,8 @@ const handler = new WebPubSubEventHandler("chat", ["https://xxx.webpubsub.azure.
// You can also set the state here
res.setState("calledTime", calledTime);
res.success("Hello", "text");
}
},
allowedEndpoints: ["https://xxx.webpubsub.azure.com"]
});

const app = express();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"homepage": "https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/web-pubsub/web-pubsub-express",
"dependencies": {
"@azure/web-pubsub-express": "next",
"dotenv": "latest"
"dotenv": "latest",
"express": "^4.17.1"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
const { WebPubSubEventHandler } = require("@azure/web-pubsub-express");
const express = require("express");

const handler = new WebPubSubEventHandler("chat", ["https://xxx.webpubsub.azure.com"], {
dumpRequest: false,
const handler = new WebPubSubEventHandler("chat", {
path: "/api/webpubsub",
handleConnect(req, res) {
console.log(req);
res.success();
Expand Down
50 changes: 26 additions & 24 deletions sdk/web-pubsub/web-pubsub-express/src/cloudEventsDispatcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import { HTTP, CloudEvent } from "cloudevents";
import { IncomingMessage, ServerResponse } from "http";
import { URL } from "url";

import { logger } from "./logger";
import * as utils from "./utils";

import {
Expand All @@ -14,9 +14,9 @@ import {
DisconnectedRequest,
ConnectedRequest,
ConnectionContext,
WebPubSubEventHandlerOptions,
ConnectResponseHandler,
UserEventResponseHandler
UserEventResponseHandler,
WebPubSubEventHandlerOptions
} from "./cloudEventsProtocols";

enum EventType {
Expand Down Expand Up @@ -137,24 +137,27 @@ function tryGetWebPubSubEvent(req: IncomingMessage): EventType | undefined {
}
}

function isWebPubSubRequest(req: IncomingMessage): boolean {
return utils.getHttpHeader(req, "ce-awpsversion") !== undefined;
}

/**
* @internal
*/
export class CloudEventsDispatcher {
private readonly _dumpRequest: boolean;
private readonly _allowedOrigins: string[];
constructor(
private hub: string,
allowedEndpoints: string[],
private eventHandler?: WebPubSubEventHandlerOptions
) {
this._dumpRequest = eventHandler?.dumpRequest ?? false;
this._allowedOrigins = allowedEndpoints.map((endpoint) =>
endpoint === "*" ? "*" : new URL(endpoint).host
);
private readonly _allowedOrigins = ["*"];
constructor(private hub: string, private eventHandler?: WebPubSubEventHandlerOptions) {
if (eventHandler?.allowedEndpoints !== undefined) {
this._allowedOrigins = eventHandler.allowedEndpoints.map((endpoint) =>
endpoint === "*" ? "*" : new URL(endpoint).host
);
}
}

public processValidateRequest(req: IncomingMessage, res: ServerResponse): boolean {
public handlePreflight(req: IncomingMessage, res: ServerResponse): boolean {
if (!isWebPubSubRequest(req)) {
return false;
}
if (req.headers["webhook-request-origin"]) {
res.setHeader("WebHook-Allowed-Origin", this._allowedOrigins);
res.end();
Expand All @@ -164,10 +167,11 @@ export class CloudEventsDispatcher {
}
}

public async processRequest(
request: IncomingMessage,
response: ServerResponse
): Promise<boolean> {
public async handleRequest(request: IncomingMessage, response: ServerResponse): Promise<boolean> {
if (!isWebPubSubRequest(request)) {
return false;
}

// check if it is a valid WebPubSub cloud events
const origin = utils.getHttpHeader(request, "webhook-request-origin");
if (origin === undefined) {
Expand Down Expand Up @@ -213,16 +217,14 @@ export class CloudEventsDispatcher {
}
break;
default:
console.warn(`Unknown EventType ${eventType}`);
logger.warning(`Unknown EventType ${eventType}`);
return false;
}

const eventRequest = await utils.convertHttpToEvent(request);
const receivedEvent = HTTP.toEvent(eventRequest);

if (this._dumpRequest) {
console.log(receivedEvent);
}
logger.verbose(receivedEvent);

switch (eventType) {
case EventType.Connect: {
Expand Down Expand Up @@ -277,7 +279,7 @@ export class CloudEventsDispatcher {
return true;
}
default:
console.warn(`Unknown EventType ${eventType}`);
logger.warning(`Unknown EventType ${eventType}`);
return false;
}
}
Expand Down
14 changes: 9 additions & 5 deletions sdk/web-pubsub/web-pubsub-express/src/cloudEventsProtocols.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ export interface ConnectRequest {
* The queries that the client WebSocket connection has when it connects.
*/
queries?: Record<string, string[]>;
/**
* The headers that the client WebSocket connection has when it connects.
*/
headers?: Record<string, string[]>;
/**
* The subprotocols that the client WebSocket connection uses to do handshake.
*/
Expand Down Expand Up @@ -208,11 +212,6 @@ export interface WebPubSubEventHandlerOptions {
*/
path?: string;

/**
* Configures if you'd like to dump the incoming HTTP request.
*/
dumpRequest?: boolean;

/**
* Handle 'connect' event, the service waits for the response to proceed.
*/
Expand All @@ -236,4 +235,9 @@ export interface WebPubSubEventHandlerOptions {
* Event triggers for "disconnected" unblocking event. This is an unblocking event and the service does not wait for the response.
*/
onDisconnected?: (disconnectedRequest: DisconnectedRequest) => void;

/**
* If not specified, by default allow all the endpoints, otherwise only allow specified endpoints
*/
allowedEndpoints?: string[];
}
11 changes: 11 additions & 0 deletions sdk/web-pubsub/web-pubsub-express/src/logger.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import { createClientLogger } from "@azure/logger";

/**
* The \@azure/logger configuration for this package.
*
* @internal
*/
export const logger = createClientLogger("web-pubsub-express");
16 changes: 6 additions & 10 deletions sdk/web-pubsub/web-pubsub-express/src/webPubSubEventHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export class WebPubSubEventHandler {
* import express from "express";
* import { WebPubSubEventHandler } from "@azure/web-pubsub-express";
* const endpoint = "https://xxxx.webpubsubdev.azure.com"
* const handler = new WebPubSubEventHandler('chat', [ endpoint ] {
* const handler = new WebPubSubEventHandler('chat', {
* handleConnect: (req, res) => {
* console.log(JSON.stringify(req));
* return {};
Expand All @@ -37,22 +37,18 @@ export class WebPubSubEventHandler {
* console.log(JSON.stringify(req));
* res.success("Hey " + req.data, req.dataType);
* };
* allowedEndpoints: [ endpoint ]
* },
* });
* ```
*
* @param hub - The name of the hub to listen to
* @param allowedEndpoints - The allowed endpoints for the incoming CloudEvents request
* @param options - Options to configure the event handler
*/
constructor(
private hub: string,
allowedEndpoints: string[],
options?: WebPubSubEventHandlerOptions
) {
constructor(private hub: string, options?: WebPubSubEventHandlerOptions) {
const path = (options?.path ?? `/api/webpubsub/hubs/${hub}/`).toLowerCase();
this.path = path.endsWith("/") ? path : path + "/";
this._cloudEventsHandler = new CloudEventsDispatcher(this.hub, allowedEndpoints, options);
this._cloudEventsHandler = new CloudEventsDispatcher(this.hub, options);
}

/**
Expand All @@ -71,12 +67,12 @@ export class WebPubSubEventHandler {
requestUrl = requestUrl.endsWith("/") ? requestUrl : requestUrl + "/";
if (requestUrl.startsWith(this.path)) {
if (req.method === "OPTIONS") {
if (this._cloudEventsHandler.processValidateRequest(req, res)) {
if (this._cloudEventsHandler.handlePreflight(req, res)) {
return;
}
} else if (req.method === "POST") {
try {
if (await this._cloudEventsHandler.processRequest(req, res)) {
if (await this._cloudEventsHandler.handleRequest(req, res)) {
return;
}
} catch (err) {
Expand Down
Loading

0 comments on commit 518dc80

Please sign in to comment.