【问题标题】:How do I send a HEAD request for a static sendFile in fastify?如何在 fastify 中发送静态 sendFile 的 HEAD 请求?
【发布时间】:2020-01-28 22:42:04
【问题描述】:

当我尝试向sendFile 发送HEAD 请求时,我收到以下错误:

app.head(filePath, { logLevel: LOG_LEVEL }, async (request, reply) => {
    console.log('head');
    try {
      const { '*': uriPath } = request.params;
      const isFile = !!uriPath.match(/\.[a-zA-Z0-9]{1,5}(\?.*)?/);
      if (isFile) {
        setCacheControl(reply, FILE_CACHE_CONTROL_MAX_AGE);
        reply.sendFile(uriPath);
      } else {
        const indexPath = 'index.html';
        const indexStr = await fs.readFile(path.join(serveRoot, indexPath), {
          encoding: 'utf-8',
        });
        const indexPayload = await injectEnv(indexStr);
        setCacheControl(reply, INDEX_CACHE_CONTROL_MAX_AGE);
        reply.type('text/html');
        reply.send(indexPayload);
      }
    } catch (e) {
      console.error(e);
    }
  });
web_1  | {"level":50,"time":1580244056047,"pid":1,"hostname":"3ee631923a16","reqId":5,"err":{"type":"FastifyError","message":"FST_ERR_PROMISE_NOT_FULLFILLED: Promise may not be fulfilled with 'undefined' when statusCode is not 204","stack":"FastifyError [FST_ERR_PROMISE_NOT_FULLFILLED]: FST_ERR_PROMISE_NOT_FULLFILLED: Promise may not be fulfilled with 'undefined' when statusCode is not 204\n    at /usr/src/server/node_modules/fastify/lib/wrapThenable.js:34:30\n    at processTicksAndRejections (internal/process/task_queues.js:85:5)","name":"FastifyError [FST_ERR_PROMISE_NOT_FULLFILLED]","code":"FST_ERR_PROMISE_NOT_FULLFILLED","statusCode":500},"msg":"Promise may not be fulfilled with 'undefined' when statusCode is not 204","v":1}

express 处理这个问题的方式是简单地将 HEAD 请求传递给 GET 方法,然后让 send(为 fastify 和 express 发送响应的底层包)通过 here 处理它不发送输出而是发送标头。

但 fastify 似乎错误地将其标记为错误here

【问题讨论】:

    标签: fastify


    【解决方案1】:

    这是一个工作示例:

    const fs = require('fs').promises
    const path = require('path')
    const app = require('fastify')({ logger: true })
    
    app.head('/', async (request, reply) => {
      request.log.debug('head')
      try {
        const indexStr = await fs.readFile(path.join(__dirname, 'index.html'), { encoding: 'utf-8' })
        reply.type('text/html')
        return indexStr
      } catch (e) {
        request.log.error(e)
        return e
      }
    })
    
    app.listen(3000)
    
    // curl --location --head 'http://localhost:3000/'
    

    当一个错误被抛出并被捕获时,undefined 实现了承诺,这导致了您在源代码中链接的错误。

    此外,当您使用async 函数作为处理程序时,您应该在正文中返回您想要发送的内容或使用return reply.send(content)

    无论如何,考虑不要使用HEADmethot,因为the standard 说:

    对 HEAD 方法的响应不应该有正文。如果是这样,它必须被忽略。即便如此,描述正文内容的实体标头(如 Content-Length)也可能包含在响应中。它们与应该为空的 HEAD 响应的主体无关,而是与使用 GET 方法的类似请求将作为响应返回的主体相关。

    所以你的身体会是空的:

    HTTP/1.1 200 正常

    内容类型:文本/html

    内容长度:41

    日期:星期三,---

    连接:保持活动

    【讨论】:

    • 这适用于index.html 或我返回的某些字符串,但是当我传回return reply.sendFile() 时,它会给我undefined 错误。当我执行reply.sendFile(uriPath); return reply.send(''); 时,它会回复内容长度为 0 且没有 etags
    • sendFile 来自fastify-static 的 API 不返回任何内容,因此这可能是插件的问题
    【解决方案2】:

    解决了。关键是返回文件return fs.readFile(uriPath);的二进制流和字符串响应return indexPayload;的字符串

    
    import path from 'path';
    import fastify from 'fastify';
    import staticServe from 'fastify-static';
    
    import { promises as fs } from 'fs';
    
    
    (async () => {
      const app = fastify({
        logger: !!LOG_LEVEL,
      });
    
      const filePath = `${ROOT_PATH}*`;
      const serveRoot = path.resolve(SERVE_PATH);
    
    
      app.register(staticServe, {
        root: serveRoot,
        serve: false,
      });
    
      // @ts-ignore
      const getHandler = async (request, reply) => {
        try {
          const { '*': uriPath } = request.params;
    
          const isFile = !!uriPath.match(/\.[a-zA-Z0-9]{1,5}(\?.*)?/);
          if (isFile) {
            setCacheControl(reply, FILE_CACHE_CONTROL_MAX_AGE);
            reply.sendFile(uriPath);
            return fs.readFile(uriPath);
          } else {
            const indexPath = 'index.html';
            const indexStr = await fs.readFile(path.join(serveRoot, indexPath), {
              encoding: 'utf-8',
            });
            const indexPayload = await injectEnv(indexStr);
            setCacheControl(reply, INDEX_CACHE_CONTROL_MAX_AGE);
            reply.type('text/html');
            return indexPayload;
          }
        } catch (e) {
          request.log.error(e);
          return e;
        }
      };
    
      app.get(filePath, { logLevel: LOG_LEVEL }, getHandler);
    
      // More info here on how it works
      // https://github.com/fastify/fastify/issues/2061
      app.head(filePath, { logLevel: LOG_LEVEL }, getHandler);
    
      app.listen(Number.parseInt(PORT, 10), '0.0.0.0', (err: Error) => {
        if (err) {
          throw err;
        }
      });
    })();
    
    

    【讨论】:

      猜你喜欢
      • 2017-09-06
      • 2010-09-11
      • 1970-01-01
      • 1970-01-01
      • 2021-11-30
      • 2010-12-30
      • 2018-09-06
      相关资源
      最近更新 更多