【问题标题】:Astro: How to proxy service callsAstro:如何代理服务调用
【发布时间】:2023-01-16 02:59:58
【问题描述】:

我正在设置一个 Astro 站点,该站点将显示从在同一主机但不同端口上运行的简单服务获取的数据。

该服务是一个简单的 Express 应用程序。 server.js:

const express = require('express')
const app = express()
const port = 3010

const response = {
  message: "hello"
}
app.get('/api/all', (_req, res) => {
  res.send(JSON.stringify(response))
})

app.listen(port, () => {
  console.log(`listening on port ${port}`)
})

由于该服务运行在与Astro站点不同的3010端口,因此我在Vite级别配置了一个server proxyastro.config.mjs:

import { defineConfig } from 'astro/config';
import react from '@astrojs/react';

export default defineConfig({
  integrations: [react()],
  vite: {
    optimizeDeps: {
      esbuildOptions: {
        define: {
          global: 'globalThis'
        }
      }
    },
    server: {
      proxy: {
        '/api/all': 'http://localhost:3010'
      }
    }
  },
});

这是我尝试调用该服务的地方。 index.astro:

---
const response = await fetch('/api/all');
const data = await response.json();
console.log(data);
---

当我运行 yarn dev 时,我得到这个控制台输出:

Response {
  size: 0,
  [Symbol(Body internals)]: {
    body: Readable {
      _readableState: [ReadableState],
      _events: [Object: null prototype],
      _eventsCount: 1,
      _maxListeners: undefined,
      _read: [Function (anonymous)],
      [Symbol(kCapture)]: false
    },
    stream: Readable {
      _readableState: [ReadableState],
      _events: [Object: null prototype],
      _eventsCount: 1,
      _maxListeners: undefined,
      _read: [Function (anonymous)],
      [Symbol(kCapture)]: false
    },
    boundary: null,
    disturbed: false,
    error: null
  },
  [Symbol(Response internals)]: {
    type: 'default',
    url: undefined,
    status: 404,
    statusText: '',
    headers: { date: 'Tue, 02 Aug 2022 19:41:02 GMT' },
    counter: undefined,
    highWaterMark: undefined
  }
}

看起来网络请求正在返回 404。

我没有在 doc 中看到更多关于服务器配置的信息。 我这样做是对的吗?

我可以使用 vanilla Vite 应用程序和相同的配置/设置正常工作。

我如何代理 Astro 应用程序的本地服务调用?

【问题讨论】:

    标签: node.js http-status-code-404 vite astrojs


    【解决方案1】:

    简答

    您不能使用 Astro 代理服务调用,但您也不必这样做

    细节

    • Astro 没有将 server.proxy 配置转发给 Vite,可以看到 Astro Vite 服务器配置为空
    proxy: {
            // add proxies here
         },
    

    参考https://github.com/withastro/astro/blob/8c100a6fe6cc652c3799d1622e12c2c969f30510/packages/astro/src/core/create-vite.ts#L125

    • Astro 服务器与 Astro vite.server 配置合并,但它不采用代理参数。
    let result = commonConfig;
        result = vite.mergeConfig(result, settings.config.vite || {});
        result = vite.mergeConfig(result, commandConfig);
    

    参考https://github.com/withastro/astro/blob/8c100a6fe6cc652c3799d1622e12c2c969f30510/packages/astro/src/core/create-vite.ts#L167

    测试

    配置测试

    我尝试了如何将配置输入到 Astro 的所有可能组合,并在每个位置使用不同的端口号来显示哪个端口号被覆盖

    • 根目录下的 vite.config.js 文件
    export default {
        server: {
          port:6000,
            proxy: {
              '/api': 'http://localhost:4000'
            }
          }
    }
    
    • 在根文件 astro.config.mjs 的两个位置
      • 服务器
      • vite.server
    export default defineConfig({
      server:{
        port: 3000,
        proxy: {
          '/api': 'http://localhost:4000'
        }
    },
      integrations: [int_test()],
      vite: {
        optimizeDeps: {
          esbuildOptions: {
            define: {
              global: 'globalThis'
            }
          }
        },
        server: {
          port:5000,
          proxy: {
            '/api': 'http://localhost:4000'
          }
        }
      }
    });
    
    • 在 Astro 集成中 Astro 有一个所谓的集成,可以帮助更新配置(Astro 插件的种类)集成有助于识别最终保留在配置中的内容,并提供最后一次机会附加配置

    集成测试.js

    async function config_setup({ updateConfig, config, addPageExtension, command }) {
        green_log(`astro:config:setup> running (${command})`)
        config.server.proxy = {'/api': 'http://localhost:4000'}
        console.log(config.server)
        console.log(config.vite)
        green_log(`astro:config:setup> end`)
    }
    

    这是输出日志

     astro:config:setup> running (dev) 
    {
      host: false,
      port: 3000,
      streaming: true,
      proxy: { '/api': 'http://localhost:4000' }
    }
    {
      optimizeDeps: { esbuildOptions: { define: [Object] } },
      server: { port: 5000, proxy: { '/api': 'http://localhost:4000' } }
    }
     astro:config:setup> end 
    

    没有在 config.server.proxy = {'/api': 'http://localhost:4000'} 行的集成中添加代理,没有代理参数,这意味着 Astro 剥离了代理参数

    试验结果

    • 开发服务器在来自 Astro 配置@987654331 的端口 3000 上运行@所有其他配置被覆盖
    • 获取 api 失败并出现错误
     error   fetch failed
      File:
        D:devstrostro-examples_api-proxyD:devstrostro-examples_api-proxysrcpagesindex.astro:15:20
      Stacktrace:
    TypeError: fetch failed
        at Object.fetch (node:internal/deps/undici/undici:11118:11)
        at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
        at async eval (D:devstrostro-examples_api-proxysrcpagesindex.astro:15:20)
        at async renderPage (file:///D:/dev/astro/astro-examples/24_api-proxy/node_modules/.pnpm/astro@2.0.0-beta.2/node_modules/astro/dist/runtime/server/rendge.js:89:30)
    

    无代理的功能测试

    鉴于 Astro 前端在服务器端运行,在构建期间以 SSG 模式运行,在服务器上加载页面时以 SSR 模式运行,然后服务器发送结果 html,Astro 可以访问所有主机端口并可以像这样直接使用服务端口

    const response = await fetch('http://localhost:4000/api');
    const data = await response.json();
    console.log(data);
    

    参考范例

    上面提到的所有测试和文件都可以在参考示例 github repo 上找到:https://github.com/MicroWebStacks/astro-examples/tree/main/24_api-proxy

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-03-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-16
      • 1970-01-01
      • 2020-02-03
      相关资源
      最近更新 更多