【问题标题】:webpack dev-server: Avoid proxy errors on HTTP errors returned from proxy targetwebpack dev-server:避免代理目标返回的 HTTP 错误的代理错误
【发布时间】:2019-07-07 15:51:30
【问题描述】:

我有一个 Vue.js 项目,我在其中配置了一个 webpack 开发服务器,将所有对 UI 的请求代理到我的后端服务器。这是 vue.config.js 的相关部分:

devServer: {
    contentBase: PATHS.build,
    port: 9000,
    https: false,
    hot: true,
    progress: true,
    inline: true,
    watchContentBase: true,
    proxy: {
        '^/': {
            target: 'http://127.0.0.1:8089',
            secure: false
        },
    }
},

我注意到,如果来自 http://127.0.0.1:8089 的 HTTP 响应代码不是 2xx,那么代理将失败并出现以下错误:

代理错误:无法将请求 /api/test 从 localhost:9000 代理到 http://127.0.0.1:8089。 有关详细信息,请参阅 https://nodejs.org/api/errors.html#errors_common_system_errors (HPE_INVALID_CHUNK_SIZE)。

这还会导致从请求到 localhost:9000 的 HTTP 响应代码对于任何错误都为 500,并且有关服务器端出现问题的所有信息都丢失了。这是有问题的,因为我希望能够从错误响应中提取信息以显示给用户。

我知道这是可能的,因为我让它在一个较旧的 Angular 项目上工作,我认为该项目使用的是 Webpack 3(我现在使用的是 Webpack 4)。我尝试从该项目复制所有开发服务器配置,但它似乎在这里不起作用!

编辑:我错了。代理错误不会发生在每个错误响应上,而只会发生在多部分文件上传请求中。尽管很难查明原因,但仍然无法在一个较小的示例中重现此问题以放在 github 上。

【问题讨论】:

  • 在 github 上创建一个 repo 以重现您的问题,人们可以检查它以查看问题所在。
  • 您应该指定更多信息。你使用的是什么版本的 Webpack/Vue.js?在 dev-server 之前是否有一些 webserver 处理请求,例如 apache 或 nginx?带有代码的仓库也会有所帮助。
  • @Legends 今天我花了一些时间试图整理一个失败的最小示例。不幸的是,无法分享原始项目。令人愤怒的是,我无法重现这个问题,所以我将不得不找出我所做的不同之处!

标签: vue.js webpack webpack-dev-server http-proxy


【解决方案1】:

我终于找到了问题所在,对此我深表歉意,这比我最初写问题时所想的要具体得多。

问题与使用 Spring RestTemplate 代理到另一台服务器的请求有关:

例如

@PostMapping("/upload")
    public ResponseEntity upload(@RequestParam("file") MultipartFile file)
        throws Exception {
        String baseUrl = serviceProperties.getAddress();
        HttpEntity<MultiValueMap<String, Object>> request = createMultipartRequest(file.getBytes());
        return restTemplate.postForEntity(baseUrl + "/api/upload", filterRequest, String.class);
    }

当响应不是 200 时,从其余模板代理返回的 ResponseEntity 包含标头“连接:关闭”,这会导致连接关闭并导致此请求无法返回任何随后生成开发服务器代理的内容在 UI 上失败。

通过不将响应标头从其余模板代理传递到响应来解决此问题:

@PostMapping("/upload")
    public ResponseEntity upload(@RequestParam("file") MultipartFile file)
        throws Exception {
        String baseUrl = serviceProperties.getAddress();
        HttpEntity<MultiValueMap<String, Object>> request = createMultipartRequest(file.getBytes());
        ResponseEntity response = restTemplate.postForEntity(baseUrl + "/api/upload", filterRequest, String.class);
        return new ResponseEntity<>(response.getBody(), response.getStatusCode());
    }

【讨论】:

    【解决方案2】:

    这个错误信息来自node_modules/@vue/cli-service/lib/util/prepareProxy.js,它为node-http-proxy定义了一个onError回调;

    所以我做了一些实验,让后端 api 生成 400 404 500 响应,但我没有收到这个错误。

    碰巧关闭后端api后,出现错误:

    Proxy error: Could not proxy request /hello from localhost:8080 to http://localhost:8081 (ECONNREFUSED).

    我在the doc 中搜索并找到这些:

    如果对目标的请求失败,则会发出错误事件。我们不对client和proxy之间传递的消息,proxy和target之间传递的消息做任何错误处理,所以建议您监听错误并处理它们

    所以onError不处理错误代码,只有在请求失败时才调用500 response仍然被视为一个完整的请求,connection refuse不是)


    返回您的错误消息,[HPE_INVALID_CHUNK_SIZE] 表示对后端 api 的错误请求。在this issue中,给出了解决方案:add a keep-alive header

    devServer: {
        publicPath: 'http://localhost:9090/front/static-dev/build/',
        port: 9090,
        proxy: {
            '/**': {
                target: 'http://localhost:8080',
                secure: false,
                changeOrigin: true,
                headers: {
                       Connection: 'keep-alive'
                }
        },
        open: true
    }
    

    【讨论】:

    • 不幸的是,这并不能解决我的问题。我做了一些进一步的调查,但我错了,并不是每个错误的请求都会导致这个代理错误,而只是在一个特定的请求上,即多部分文件上传。尽管如此,仍然无法在较小的示例中重新创建它。
    • @Plog 当然,现在的问题是为什么这个多部分请求失败并显示 INVALID_CHUNK_SIZE,我不熟悉块编码。如果您在没有代理的情况下立即请求,chrome 是否会显示此错误?
    • 我终于解决了这个问题。事实证明,它根本与代理配置无关。我的后端有问题。为混乱道歉。我会奖励你的努力。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-28
    • 1970-01-01
    • 1970-01-01
    • 2015-08-02
    • 2011-05-14
    相关资源
    最近更新 更多