BigQuery Storage gRP C -Web: ошибка 404 при создании сеанса чтения - PullRequest
6 голосов
/ 21 февраля 2020

Новые обновления в конце.

Мы создаем библиотеку BigQuery Storage в JavaScript для браузеров.

Проблема, с которой мы сталкиваемся, заключается в том, что мы получаем ошибка 404 из https://bigquerystorage.googleapis.com/:

404 camouflaged as 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>
...

Есть идеи, что происходит с запросом?

Вот все ресурсы, которые мы используем. Это базовая структура:

project structure

Исходные файлы .proto получены из:

Для компиляции .proto в .js мы используем protoc и плагин protoc-gen-grpc-web с:

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

И, наконец, это файл 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;

ОБНОВЛЕНИЕ 1:

Похоже, API хранилища больших запросов не поддерживает вызовы gRP C в текстовом режиме , В текстовом режиме заголовок 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:

Существует новое хранилище BigQuery библиотека для Node.js https://github.com/googleapis/nodejs-bigquery-storage, которая работает как шарм в 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
...