当我使用firebase重写时,云运行API服务响应中断

xam8gpfp  于 2022-11-30  发布在  其他
关注(0)|答案(2)|浏览(117)

firebase的客户端应用程序和服务器API使用google的云运行托管容器。https://app...-4ysldefc4nq-uc.a.run.app/
但是当我使用firebase重写时,客户端可以正常工作:https://vc-ticker.web.app/...,但收到来自API服务的502和504响应。云运行日志未显示任何错误,收到客户端获取POST请求并返回Readablestream响应。

但使用重写时,此API服务响应流从不到达。

firebase.json

{
  "hosting": {
    "public": "public",   !! NOT used, cloud run hosts the app
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    "rewrites": [
      {
        "source": "**",
        "run": {
          "serviceId": "vc-ticker-app",
          "region": "us-central1"
        }
      }
    ]
  }
}
  • page.svelte客户端API请求:
const logging = true;
const controller = new AbortController();
let reader = null;
const signal = controller.signal;

async function streamer(params) {
  console.log("stream with logging:", logging, JSON.stringify(params));
  try {
    const response = await fetch("api/my-ticker", {
      method: "POST",
      body: JSON.stringify(params),
      headers: {
        "content-type": "application/json",
      },
      signal: signal,
    });

    const stream = response.body.pipeThrough(new TextDecoderStream("utf-8"));
    reader = stream.getReader();

    while (true) {
      const { value, done } = await reader.read();

      if (done || response.status !== 200) {
        console.log("done response", response.status, done, value);
        await reader.cancel(`reader done or invalid response: ${response.status}`);
        reader = null;
        break;
      }

      // response ok: parse multi json chunks => array => set store
      const quotes = {};
      JSON.parse(`[${value.replaceAll("}{", "},{")}]`).forEach((each, idx) => {
        quotes[each.id] = [each.price, each.changePercent];
        console.log(`quote-${idx}:`, quotes[each.id]);
      });
      positions.set(quotes);
    }
  } catch (err) {
    console.log("streamer exception", err.name, err);
    if (reader) {
      await reader.cancel(`client exception: ${err.name}`);
      reader = null;
    }
  }
}

$: if ($portfolio?.coins) {
  const params = {
    logging,
    symbols: Object.values($portfolio.symbols),
  };
  streamer(params);
}

onDestroy(async () => {
  if (reader) await reader.cancel("client destroyed");
  controller.abort();
  console.log("finished");
});

我使用Sveltekit适配器节点来构建应用程序。

igetnqfo

igetnqfo1#

使用重写规则,您可以将与特定模式匹配的请求定向到单个目标。

"hosting": {// ...
  // Add the "rewrites" attribute within "hosting"
  "rewrites": [ {
    "source": "/helloworld",
    "run": {
      "serviceId": "helloworld",  // "service name" (from when you [deployed the container image][3])
      "region": "us-central1"     // optional (if omitted, default is us-central1)
    }
  } ]
}

请务必注意,Firebase Hosting的请求超时时间为60秒。如果您的应用运行时间超过60秒,您将收到HTTPS状态代码504(请求超时)。要支持需要更长计算时间的动态内容,请考虑使用App Engine flexible environment
您还应该查看“托管配置”页以了解有关重写规则的详细信息。您还可以了解各种托管配置的响应优先级顺序。

cbjzeqam

cbjzeqam2#

我用一个到云运行API服务(cors)的外部链接使它工作,但我仍然不明白为什么没有cors,只使用firebase重写就不能完成。

  • + page.svelte客户端API请求更新:*

现在使用GET和auth令牌验证端点服务器上的api请求

const search = new URLSearchParams(params);
const apiHost = "https://fs-por....-app-4y...q-uc.a.run.app/api/yahoo-finance-streamer";
const response = await fetch(`${apiHost}?${search.toString()}`, {
  method: "GET",
  headers: {
    "auth-token": await getIdToken(),
  },
  signal: signal,
});
    • 和一个句柄挂接,用于验证验证令牌和句柄cors:**
const logging = true;
const reqUnauthorized = { status: 403, statusText: 'Unauthorized!' };

/** @type {import('@sveltejs/kit').Handle} */
export async function handle({ event, resolve }) {
  let response;
  if (event.request.method !== "OPTIONS") {
    if (event.url.pathname.startsWith('/api')) {
      const authToken = event.request.headers.get("auth-token")
      const obj = await decodeIdToken(logging, authToken)
      if ("message" in obj) return new Response(obj.message, reqUnauthorized);
      if (verifyUser(logging, obj.uid) === false) {
        return new Response(`user auth failed for: ${obj.email}`, reqUnauthorized);
      }
    }
    response = await resolve(event);
  } else { // handle cors preflight OPTIONS
    response = new Response("", { status: 200 });
  }
  response.headers.append('Access-Control-Allow-Headers', "*");
  response.headers.append('Access-Control-Allow-Origin', "*");
  return response;
}

相关问题