diff --git a/grpc-zpages/buildscripts/channelz_codgen.sh b/grpc-zpages/buildscripts/channelz_codgen.sh index 0b2ee0e..57aff34 100755 --- a/grpc-zpages/buildscripts/channelz_codgen.sh +++ b/grpc-zpages/buildscripts/channelz_codgen.sh @@ -29,4 +29,4 @@ docker build -t channelz_codegen codegen exec docker run --rm -v "$GRPC_ZPAGES_DIR"/docker/codegen/shared_dir:/shared_dir/ channelz_codegen bash -c "function fixFiles() { chown -R $(id -u):$(id -g) /shared_dir; }; trap fixFiles EXIT; /shared_dir/scripts/gen_channelz_pb.sh $GRPC_PROTO_SHA" -mv "$GRPC_ZPAGES_DIR"/docker/codegen/shared_dir/gen_out/channelz.js "$GRPC_ZPAGES_DIR"/web/channelzui/src/assets/channelz.js +mv "$GRPC_ZPAGES_DIR"/docker/codegen/shared_dir/gen_out/channelz.js "$GRPC_ZPAGES_DIR"/web/channelzui/src/generated/channelz.js diff --git a/grpc-zpages/web/channelzui/angular.json b/grpc-zpages/web/channelzui/angular.json index ec8e1db..9016af7 100644 --- a/grpc-zpages/web/channelzui/angular.json +++ b/grpc-zpages/web/channelzui/angular.json @@ -23,7 +23,7 @@ "styles": [ "src/styles.css" ], - "scripts": [] + "scripts": ["src/generated/channelz.js"] }, "configurations": { "production": { diff --git a/grpc-zpages/web/channelzui/src/app/app.module.ts b/grpc-zpages/web/channelzui/src/app/app.module.ts index 81998a9..5898ff8 100644 --- a/grpc-zpages/web/channelzui/src/app/app.module.ts +++ b/grpc-zpages/web/channelzui/src/app/app.module.ts @@ -20,7 +20,6 @@ import { AppRoutingModule } from './app-routing.module'; import { BrowserModule } from '@angular/platform-browser'; import { CommonModule } from '@angular/common'; import { FormsModule } from '@angular/forms'; -import { HttpClientModule } from '@angular/common/http'; import { NgModule } from '@angular/core'; import { ServersComponent } from './servers/servers.component'; import { SocketComponent } from './socket/socket.component'; @@ -52,7 +51,6 @@ import { TopChannelsComponent } from './top-channels/top-channels.component'; BrowserModule, CommonModule, FormsModule, - HttpClientModule, ], providers: [ChannelzService], bootstrap: [AppComponent] diff --git a/grpc-zpages/web/channelzui/src/app/channelz.service.ts b/grpc-zpages/web/channelzui/src/app/channelz.service.ts index 98f7801..784d874 100644 --- a/grpc-zpages/web/channelzui/src/app/channelz.service.ts +++ b/grpc-zpages/web/channelzui/src/app/channelz.service.ts @@ -15,15 +15,16 @@ * limitations under the License. */ -import { Injectable } from "@angular/core"; +import { Injectable, Optional } from "@angular/core"; import { Observable } from "rxjs"; -import { HttpClient } from "@angular/common/http"; import { environment } from "../environments/environment"; -// goog and proto are symbols provided by grpc generated code -// In OSS, the grpc generated code is imported from a standalone .js file +// When building with angular CLI in OSS: +// The standalone channelz.js file provides a proto symbol with the +// client and message types. goog.require() is effectively a noop. +// When building with closure compiler: +// goog.require() imports the client and message libraries declare var goog: any; -declare var proto: any; goog.require('proto.grpc.channelz.v1.ChannelzClient'); goog.require('proto.grpc.channelz.v1.GetChannelRequest'); goog.require('proto.grpc.channelz.v1.GetServerSocketsRequest'); @@ -31,29 +32,34 @@ goog.require('proto.grpc.channelz.v1.GetServersRequest'); goog.require('proto.grpc.channelz.v1.GetSocketRequest'); goog.require('proto.grpc.channelz.v1.GetSubchannelRequest'); goog.require('proto.grpc.channelz.v1.GetTopChannelsRequest'); - +declare var proto: any; @Injectable() export class ChannelzService { xsrfMeta: {}; + client: any; - constructor(private http: HttpClient) { + // Because this class is @Injectable, angular takes care of DI for parameters. + // This means we can not provide a default parameter value. + // The parameter is either injected or it is null. + constructor(@Optional() private grpcRemoteAddr:string) { + this.xsrfMeta = ChannelzService.genXsrfMeta(); + this.client = new proto.grpc.channelz.v1.ChannelzClient( + grpcRemoteAddr == null ? environment.grpcRemoteAddr : grpcRemoteAddr); + } + + private static genXsrfMeta(): any { const arr = new Int8Array(32); // 256 bits of entropy window.crypto.getRandomValues(arr); const xsrfVal = btoa(arr.toString()); document.cookie = `grpc-channelz-v1-channelz-token=${xsrfVal};path=/`; - this.xsrfMeta = {"grpc-channelz-v1-channelz-token": xsrfVal}; + return {"grpc-channelz-v1-channelz-token": xsrfVal}; } - // window.location.origin is the reverse proxy that both serves the - // app and performs grpc-web translation - private client = new proto.grpc.channelz.v1.ChannelzClient( - environment.grpcRemoteAddr); - private functionToObserver(rpcMethod: any, req: any): Observable { return new Observable(observer => { - // To pass a method around as a parameter, the method must be bound - // to an instance of the object. In this case it is the client. + // To use a method passed around as a parameter, the method must be bound + // to an instance of the object. rpcMethod.bind(this.client)(req, this.xsrfMeta, function(err, response) { observer.next(response); observer.complete(); diff --git a/grpc-zpages/web/channelzui/src/app/utils.ts b/grpc-zpages/web/channelzui/src/app/utils.ts index eb1edb7..2ee0010 100644 --- a/grpc-zpages/web/channelzui/src/app/utils.ts +++ b/grpc-zpages/web/channelzui/src/app/utils.ts @@ -17,14 +17,17 @@ import { Pipe, PipeTransform } from '@angular/core'; -// goog and proto are symbols provided by grpc generated code -// In OSS, the grpc generated code is imported from a standalone .js file +// When building with angular CLI in OSS: +// The standalone channelz.js file provides a proto symbol with the +// client and message types. goog.require() is effectively a noop. +// When building with closure compiler: +// goog.require() imports the client and message libraries declare var goog: any; -declare var proto: any; goog.require('proto.grpc.channelz.v1.SocketOptionLinger'); goog.require('proto.grpc.channelz.v1.SocketOptionTimeout'); goog.require('proto.grpc.channelz.v1.SocketOptionTcpInfo'); goog.require('proto.grpc.channelz.v1.ChannelConnectivityState.State'); +declare var proto: any; const protoAnyToStringHelpers = { 'type.googleapis.com/grpc.channelz.v1.SocketOptionLinger': (protoAny: any) => { diff --git a/grpc-zpages/web/channelzui/src/environments/environment.ts b/grpc-zpages/web/channelzui/src/environments/environment.ts index f6eac7e..dae36ba 100644 --- a/grpc-zpages/web/channelzui/src/environments/environment.ts +++ b/grpc-zpages/web/channelzui/src/environments/environment.ts @@ -5,5 +5,7 @@ export const environment = { production: false, + // window.location.origin is the reverse proxy that both serves the + // app and performs grpc-web translation grpcRemoteAddr: window.location.origin, }; diff --git a/grpc-zpages/web/channelzui/src/assets/channelz.js b/grpc-zpages/web/channelzui/src/generated/channelz.js similarity index 100% rename from grpc-zpages/web/channelzui/src/assets/channelz.js rename to grpc-zpages/web/channelzui/src/generated/channelz.js diff --git a/grpc-zpages/web/channelzui/src/index.html b/grpc-zpages/web/channelzui/src/index.html index 2da8a96..df6b9a4 100644 --- a/grpc-zpages/web/channelzui/src/index.html +++ b/grpc-zpages/web/channelzui/src/index.html @@ -7,7 +7,6 @@ -