Skip to content

Commit

Permalink
feat(middleware-sdk-rekognitionstreaming): create port middleware (#4622
Browse files Browse the repository at this point in the history
)

* feat(middleware-sdk-rekognitionstreaming): create port middleware

* fix(client-rekognitionstreaming): apply explicit 443 wss port
  • Loading branch information
kuhe authored Apr 6, 2023
1 parent c64cf47 commit adf3353
Show file tree
Hide file tree
Showing 17 changed files with 289 additions and 0 deletions.
1 change: 1 addition & 0 deletions clients/client-rekognitionstreaming/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"@aws-sdk/middleware-logger": "*",
"@aws-sdk/middleware-recursion-detection": "*",
"@aws-sdk/middleware-retry": "*",
"@aws-sdk/middleware-sdk-rekognitionstreaming": "*",
"@aws-sdk/middleware-serde": "*",
"@aws-sdk/middleware-signing": "*",
"@aws-sdk/middleware-stack": "*",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
import { getLoggerPlugin } from "@aws-sdk/middleware-logger";
import { getRecursionDetectionPlugin } from "@aws-sdk/middleware-recursion-detection";
import { getRetryPlugin, resolveRetryConfig, RetryInputConfig, RetryResolvedConfig } from "@aws-sdk/middleware-retry";
import { getRekognitionStreamingPlugin } from "@aws-sdk/middleware-sdk-rekognitionstreaming";
import {
AwsAuthInputConfig,
AwsAuthResolvedConfig,
Expand Down Expand Up @@ -319,6 +320,7 @@ export class RekognitionStreamingClient extends __Client<
this.middlewareStack.use(getLoggerPlugin(this.config));
this.middlewareStack.use(getRecursionDetectionPlugin(this.config));
this.middlewareStack.use(getAwsAuthPlugin(this.config));
this.middlewareStack.use(getRekognitionStreamingPlugin(this.config));
this.middlewareStack.use(getUserAgentPlugin(this.config));
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

package software.amazon.smithy.aws.typescript.codegen;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import software.amazon.smithy.aws.traits.ServiceTrait;
import software.amazon.smithy.codegen.core.SymbolProvider;
import software.amazon.smithy.model.Model;
import software.amazon.smithy.model.shapes.ServiceShape;
import software.amazon.smithy.typescript.codegen.LanguageTarget;
import software.amazon.smithy.typescript.codegen.TypeScriptSettings;
import software.amazon.smithy.typescript.codegen.TypeScriptWriter;
import software.amazon.smithy.typescript.codegen.integration.RuntimeClientPlugin;
import software.amazon.smithy.typescript.codegen.integration.TypeScriptIntegration;
import software.amazon.smithy.utils.ListUtils;
import software.amazon.smithy.utils.SmithyInternalApi;

/**
* Add client plugins and configs to support WebSocket streaming for Rekognition
* Streaming service.
**/
@SmithyInternalApi
public class AddRekognitionStreamingDependency implements TypeScriptIntegration {
@Override
public List<RuntimeClientPlugin> getClientPlugins() {
return ListUtils.of(
RuntimeClientPlugin.builder()
.withConventions(AwsDependency.REKOGNITION_STREAMING_MIDDLEWARE.dependency,
"RekognitionStreaming", RuntimeClientPlugin.Convention.HAS_MIDDLEWARE)
.servicePredicate((m, s) -> isRekognitionStreaming(s))
.build()
);
}

@Override
public Map<String, Consumer<TypeScriptWriter>> getRuntimeConfigWriters(
TypeScriptSettings settings,
Model model,
SymbolProvider symbolProvider,
LanguageTarget target
) {
ServiceShape service = settings.getService(model);
if (!isRekognitionStreaming(service)) {
return Collections.emptyMap();
}

switch (target) {
case REACT_NATIVE:
case BROWSER:
default:
return Collections.emptyMap();
}
}

private static boolean isRekognitionStreaming(ServiceShape service) {
String serviceId = service.getTrait(ServiceTrait.class).map(ServiceTrait::getSdkId).orElse("");
return serviceId.equals("RekognitionStreaming");
}
}


Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ public enum AwsDependency implements SymbolDependencyContainer {
MIDDLEWARE_EVENTSTREAM(NORMAL_DEPENDENCY, "@aws-sdk/middleware-eventstream"),
AWS_SDK_EVENTSTREAM_HANDLER_NODE(NORMAL_DEPENDENCY, "@aws-sdk/eventstream-handler-node"),
TRANSCRIBE_STREAMING_MIDDLEWARE(NORMAL_DEPENDENCY, "@aws-sdk/middleware-sdk-transcribe-streaming"),
REKOGNITION_STREAMING_MIDDLEWARE(NORMAL_DEPENDENCY, "@aws-sdk/middleware-sdk-rekognitionstreaming"),
STS_MIDDLEWARE(NORMAL_DEPENDENCY, "@aws-sdk/middleware-sdk-sts"),
STS_CLIENT(NORMAL_DEPENDENCY, "@aws-sdk/client-sts"),
MIDDLEWARE_LOGGER(NORMAL_DEPENDENCY, "@aws-sdk/middleware-logger"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ software.amazon.smithy.aws.typescript.codegen.AddEventStreamHandlingDependency
software.amazon.smithy.aws.typescript.codegen.AddHttp2Dependency
software.amazon.smithy.aws.typescript.codegen.AddWebsocketPlugin
software.amazon.smithy.aws.typescript.codegen.AddTranscribeStreamingDependency
software.amazon.smithy.aws.typescript.codegen.AddRekognitionStreamingDependency
software.amazon.smithy.aws.typescript.codegen.AddUserAgentDependency
software.amazon.smithy.aws.typescript.codegen.AddOmitRetryHeadersDependency
software.amazon.smithy.aws.typescript.codegen.StripNewEnumNames
Expand Down
9 changes: 9 additions & 0 deletions packages/middleware-sdk-rekognitionstreaming/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/node_modules/
/build/
/dist/
/coverage/
/docs/
*.tsbuildinfo
*.tgz
*.log
package-lock.json
Empty file.
4 changes: 4 additions & 0 deletions packages/middleware-sdk-rekognitionstreaming/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# @aws-sdk/middleware-sdk-rekognitionstreaming

[![NPM version](https://img.shields.io/npm/v/@aws-sdk/middleware-sdk-rekognitionstreaming/latest.svg)](https://www.npmjs.com/package/@aws-sdk/middleware-sdk-rekognitionstreaming)
[![NPM downloads](https://img.shields.io/npm/dm/@aws-sdk/middleware-sdk-rekognitionstreaming.svg)](https://www.npmjs.com/package/@aws-sdk/middleware-sdk-rekognitionstreaming)
7 changes: 7 additions & 0 deletions packages/middleware-sdk-rekognitionstreaming/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const base = require("../../jest.config.base.js");

module.exports = {
...base,
//only test cjs dist, avoid testing the package twice
testPathIgnorePatterns: ["/node_modules/", "/es/"],
};
60 changes: 60 additions & 0 deletions packages/middleware-sdk-rekognitionstreaming/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
{
"name": "@aws-sdk/middleware-sdk-rekognitionstreaming",
"version": "3.0.0",
"main": "./dist-cjs/index.js",
"module": "./dist-es/index.js",
"types": "./dist-types/index.d.ts",
"scripts": {
"build": "concurrently 'yarn:build:cjs' 'yarn:build:es' 'yarn:build:types'",
"build:cjs": "tsc -p tsconfig.cjs.json",
"build:es": "tsc -p tsconfig.es.json",
"build:include:deps": "lerna run --scope $npm_package_name --include-dependencies build",
"build:types": "tsc -p tsconfig.types.json",
"build:types:downlevel": "downlevel-dts dist-types dist-types/ts3.4",
"clean": "rimraf ./dist-* && rimraf *.tsbuildinfo",
"test": "jest --passWithNoTests"
},
"author": {
"name": "AWS SDK for JavaScript Team",
"url": "https://aws.amazon.com/javascript/"
},
"license": "Apache-2.0",
"dependencies": {
"@aws-sdk/protocol-http": "*",
"@aws-sdk/types": "*",
"tslib": "^2.5.0"
},
"devDependencies": {
"@tsconfig/recommended": "1.0.1",
"@types/uuid": "^8.3.0",
"concurrently": "7.0.0",
"downlevel-dts": "0.10.1",
"jest-websocket-mock": "^2.0.2",
"mock-socket": "9.1.5",
"rimraf": "3.0.2",
"typedoc": "0.23.23",
"typescript": "~4.9.5"
},
"engines": {
"node": ">=14.0.0"
},
"typesVersions": {
"<4.0": {
"dist-types/*": [
"dist-types/ts3.4/*"
]
}
},
"files": [
"dist-*"
],
"homepage": "https://github.com/aws/aws-sdk-js-v3/tree/main/packages/middleware-sdk-rekognitionstreaming",
"repository": {
"type": "git",
"url": "https://github.com/aws/aws-sdk-js-v3.git",
"directory": "packages/middleware-sdk-rekognitionstreaming"
},
"typedoc": {
"entryPoint": "src/index.ts"
}
}
2 changes: 2 additions & 0 deletions packages/middleware-sdk-rekognitionstreaming/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from "./middleware-port";
export * from "./plugin";
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { HttpRequest } from "@aws-sdk/protocol-http";
import { BuildHandlerArguments, RequestHandler } from "@aws-sdk/types";

import { websocketPortMiddleware } from "./middleware-port";

describe("websocketPortMiddleware", () => {
const mockHandler: RequestHandler<any, any> = {
metadata: { handlerProtocol: "websocket" },
handle: () => ({} as any),
};
it("should skip non-http request", (done) => {
const nonHttpRequest = {
foo: "bar",
};
const next = (args: BuildHandlerArguments<any>) => {
expect(args.request).toEqual(nonHttpRequest);
done();
};
const mw = websocketPortMiddleware({ requestHandler: mockHandler });
mw(next as any, {} as any)({ request: nonHttpRequest, input: {} });
});

it("should skip non WebSocket requests", (done) => {
const mockHandler: RequestHandler<any, any> = {
metadata: { handlerProtocol: "some_protocol" },
handle: () => ({} as any),
};
const request = new HttpRequest({});
const next = (args: BuildHandlerArguments<any>) => {
expect(args.request).toEqual(request);
done();
};
const mw = websocketPortMiddleware({ requestHandler: mockHandler });
mw(next as any, {} as any)({ request, input: {} });
});

it("should update endpoint to websocket url", (done) => {
const request = new HttpRequest({
hostname: "streaming-rekognition.us-east-1.amazonaws.com",
});
const next = (args: BuildHandlerArguments<any>) => {
expect(HttpRequest.isInstance(args.request)).toBeTruthy();
const processed = args.request as HttpRequest;
expect(processed.hostname).toEqual("streaming-rekognition.us-east-1.amazonaws.com:443");
expect(processed.headers.host).toEqual("streaming-rekognition.us-east-1.amazonaws.com:443");
done();
};
const mw = websocketPortMiddleware({ requestHandler: mockHandler });
mw(next as any, {} as any)({ request, input: {} });
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { HttpRequest } from "@aws-sdk/protocol-http";
import {
BuildHandler,
BuildHandlerArguments,
BuildMiddleware,
RelativeMiddlewareOptions,
RequestHandler,
} from "@aws-sdk/types";

/**
* @internal
*
* Middleware that generates WebSocket URL to RekognitionStreaming service
* Reference: https://docs.aws.amazon.com/transcribe/latest/dg/websocket.html
*/
export const websocketPortMiddleware =
(options: { requestHandler: RequestHandler<any, any> }): BuildMiddleware<any, any> =>
(next: BuildHandler<any, any>) =>
(args: BuildHandlerArguments<any>) => {
const { request } = args;
if (HttpRequest.isInstance(request) && options.requestHandler.metadata?.handlerProtocol?.includes("websocket")) {
// Append port to hostname because it needs to be signed together
request.hostname = `${request.hostname}:443`;
request.headers.host = request.hostname;
}
return next(args);
};

/**
* @internal
*/
export const websocketPortMiddlewareOptions: RelativeMiddlewareOptions = {
name: "websocketPortMiddleware",
tags: ["WEBSOCKET", "EVENT_STREAM", "PORT"],
relation: "after",
toMiddleware: "eventStreamHeaderMiddleware",
override: true,
};
16 changes: 16 additions & 0 deletions packages/middleware-sdk-rekognitionstreaming/src/plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Pluggable, RequestHandler } from "@aws-sdk/types";

import { websocketPortMiddleware, websocketPortMiddlewareOptions } from "./middleware-port";

interface PreviouslyResolved {
requestHandler: RequestHandler<any, any>;
}

/**
* @internal
*/
export const getRekognitionStreamingPlugin = (config: PreviouslyResolved): Pluggable<any, any> => ({
applyToStack: (clientStack) => {
clientStack.addRelativeTo(websocketPortMiddleware(config), websocketPortMiddlewareOptions);
},
});
10 changes: 10 additions & 0 deletions packages/middleware-sdk-rekognitionstreaming/tsconfig.cjs.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"compilerOptions": {
"baseUrl": ".",
"outDir": "dist-cjs",
"rootDir": "src",
"stripInternal": true
},
"extends": "../../tsconfig.cjs.json",
"include": ["src/"]
}
11 changes: 11 additions & 0 deletions packages/middleware-sdk-rekognitionstreaming/tsconfig.es.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"compilerOptions": {
"baseUrl": ".",
"lib": ["DOM"],
"outDir": "dist-es",
"rootDir": "src",
"stripInternal": true
},
"extends": "../../tsconfig.es.json",
"include": ["src/"]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"compilerOptions": {
"baseUrl": ".",
"declarationDir": "dist-types",
"rootDir": "src"
},
"extends": "../../tsconfig.types.json",
"include": ["src/"]
}

0 comments on commit adf3353

Please sign in to comment.