BigQuery Storage gRPC-Web:创建读取会话时出现 404 错误

jos*_*azo 6 javascript google-bigquery grpc

新的更新在最后。

我们正在用 JavaScript 为浏览器创建 BigQuery 存储库。

我们面临的问题是我们从https://bigquerystorage.googleapis.com/以下位置获得 404 错误:

404伪装成CORS

看起来像是 CORS 问题,但实际上是 404 问题:

$> curl 'https://bigquerystorage.googleapis.com/google.cloud.bigquery.storage.v1beta1.BigQueryStorage/CreateReadSession' \
       -H 'x-goog-request-params: table_reference.project_id=project&table_reference.dataset_id=dataset' \
       -H 'X-User-Agent: grpc-web-javascript/0.1' -H 'DNT: 1' -H 'Content-Type: application/grpc-web-text' \
       -H 'Accept: application/grpc-web-text' -H 'X-Grpc-Web: 1' -H 'Sec-Fetch-Dest: empty' \
       --data-binary 'ydG9k_binary_data_oATgB' --compressed

<!DOCTYPE html>
<html lang=en>
  <meta charset=utf-8>
  <meta name=viewport content="initial-scale=1, minimum-scale=1, width=device-width">
  <title>Error 404 (Not Found)!!1</title>
...
Run Code Online (Sandbox Code Playgroud)

知道请求发生了什么吗?

这是我们正在使用的所有资源。这是基本结构:

项目结构

原始.proto文件来自:

为了编译.proto.js我们使用的protocprotoc-gen-grpc-web插件:

cd src/proto/
protoc -I=. $(find . -iname "*.proto") --js_out=import_style=commonjs:. --grpc-web_out=import_style=commonjs,mode=grpcwebtext:.
Run Code Online (Sandbox Code Playgroud)

最后,这是big_query_storage.js我们捆绑的文件rollup.js

import BigQueryStorage from './proto/storage_grpc_web_pb.js';
import BigQueryStorageEnums from './proto/storage_pb.js';
import TableComponents from './proto/google/cloud/bigquery/storage/v1beta1/table_reference_pb.js';
import Timestamp from 'google-protobuf/google/protobuf/timestamp_pb.js';

const bigQueryStorageHostname = 'https://bigquerystorage.googleapis.com'

const projectId = 'project';
const datasetId = 'dataset';
const tableId = 'table';

const fields = ['column'];
const rowRestriction = 'where';

function BigQueryStorageTest() {
  let client = new BigQueryStorage.BigQueryStorageClient(bigQueryStorageHostname);

  let tableReference = new TableComponents.TableReference();
  tableReference.setProjectId(projectId);
  tableReference.setDatasetId(datasetId);
  tableReference.setTableId(tableId);

  let readOptions = new TableComponents.TableReadOptions();
  readOptions.setSelectedFieldsList(fields);
  readOptions.setRowRestriction(rowRestriction);

  const parent = `projects/${projectId}`;

  let readSessionRequest = new BigQueryStorage.CreateReadSessionRequest();
  readSessionRequest.setTableReference(tableReference);
  readSessionRequest.setParent(parent);
  readSessionRequest.setReadOptions(readOptions);
  readSessionRequest.setFormat(BigQueryStorageEnums.DataFormat.AVRO);
  readSessionRequest.setShardingStrategy(BigQueryStorageEnums.ShardingStrategy.LIQUID);

  let metadata = {};

  let routingHeader = new URLSearchParams({
    'table_reference.project_id': encodeURI(tableReference.getProjectId()),
    'table_reference.dataset_id': encodeURI(tableReference.getDatasetId())
  }).toString();

  let routingMetadata = {
    'x-goog-request-params': routingHeader
  };

  metadata = {...metadata, ...routingMetadata}

  let session = client.createReadSession(readSessionRequest, metadata);
}

export default BigQueryStorageTest;
Run Code Online (Sandbox Code Playgroud)

更新1:

看起来 Big Query Storage API 不支持文本模式下的 gRPC 调用。文本模式将Content-Type标题设置为application/grpc-web-text为以 base64 编码的二进制文件和正文。

因此,因此,API 无法在编码正文中找到表,返回 404 错误。

修改编译.js文件(来自.proto)以使用二进制作为格式,正文作为二进制发送并且Content-Type标头设置为application/x-protobuf. 这是因为 API 不会返回 404 错误,但会收到 400,Invalid resource field value in the request

更新 2:

Node.js https://github.com/googleapis/nodejs-bigquery-storage有一个新的 BigQuery 存储库,它在 Node.js 中的作用很明显,但在移植到浏览器时存在一些问题。

看起来它无法执行流操作,并在访问为readRows服务生成的存根时出现此错误:

TypeError: undefined is not a function
    at Service.newServiceStub.<computed> [as readRows] (fallback.js:190)
    at big_query_storage_client.js:147
    at streamingApiCaller.js:37
    at timeout.js:43
    at Object.request (streaming.js:102)
    at makeRequest (index.js:128)
    at retryRequest (index.js:96)
    at StreamProxy.setStream (streaming.js:93)
    at StreamingApiCaller.call (streamingApiCaller.js:53)
    at createApiCall.js:72
Run Code Online (Sandbox Code Playgroud)