0

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

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 发送响应的底层包)在这里通过不发送输出而是发送 headers 来处理它。

但是 fastify 似乎在这里错误地将其标记为错误

4

2 回答 2

0

这是一个工作示例:

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,因为标准说:

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

所以你的身体会是空的:

HTTP/1.1 200 正常

内容类型:文本/html

内容长度:41

日期:星期三,---

连接:保持活动

于 2020-01-29T09:36:06.190 回答
0

解决了。关键是返回文件的二进制流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;
    }
  });
})();

于 2020-01-29T17:05:36.433 回答