Astro JS中间件示例:请求记录
#javascript #网络开发人员 #astro

ðAstroJS中间件示例

Astro现在包括中间件,它具有与 sveltekit Hooks Deno Fresh Mifdware 或无服务器主机提供的中间件(例如 Cloud> Cloudflare Workers )。在这里,我们看到了一个Astro JS中间件示例,以及什么是中间件,以及何时将其从Astro Tool Tell带出。在我们的示例中,我们将使用Astro中间件添加请求记录,并使用 logtail serverless lodgging 服务。

在写作时,功能仍是实验性的,API可能会改变。因此,在生产项目中使用Astro中间件之前,请先检查当前状态。另外,请记住API可能会发展,因此,如果您遇到问题,请检查最新文档(在页面下方链接)。

什么是中间件?

中间件只是在服务器上运行以拦截请求的代码,并可能修改它们。将调用Astro路由文件,通常用于特定路由(例如/docs/getting-started)。在这方面,中间件有些不同,因为它的特定特定可以。您可以为所有路线或选定的子路径调用中间件功能。通过我们考虑的日志记录示例,无论请求是哪种路线,您都将要捕获一些请求详细信息。这里包括的可能是请求路径名,请求的时间,甚至可能是响应的时间。一个用于所有路由的中间件文件,而不是在每个路线的.astro文件中包含记录逻辑,在这里很有意义。

我们将在您的中间件功能中看到,您可以窥视响应的内容,然后发送该响应,AS-IS甚至更改某些零件,添加HTTP标头甚至更换响应主体的一部分,这很有意义。我们还可以看到Astro可以使用当地对象将数据传递到.astro文件,并提供另一种更新内容的方式。尽管 Astro中间件在SSR和静态路线上都可以使用,但您将在SSR网站上获得最大收益。

ð¶为什么使用中间件?

中间件的一些用途是:

  • 分析代码;
  • 记录;
  • 性能和可靠性测量;
  • 操纵HTML内容(例如重点搜索词在身体文本中);
  • 添加响应标头(例如 HTTP安全标头);和
  • 代理请求,例如keep a WordPress backend URL private

ð§±我们正在建造什么?

我们将查看代码的基本Astro JS中间件记录示例。在代码中,我们将看到如何在Astro中添加中间件功能以及最重要的方法,以拦截请求。我们还看到如何将响应完好无损但仍通过数据,以供您的前端代码中使用。

Astro JS Middleware Example: Screen capture shows an event logged in the Log tail console. Message reads astro-middleware-log. Timestamp and pathname are included, as, well as the event level, which is set to info.

如果这听起来像您要寻找的东西,那为什么我们不开始?我们不会从头开始构建一个应用程序,因此,您可能想在现有项目上创建一个功能分支。但是,如果这是您第一次在Astro工作,请参见 quick guide on how to spin up a new Astro project.

ð启用Astro中间件

因为中间件是一个实验功能,在写作时,您需要通过更新astro.config.mjs
来手动启用它

import { defineConfig } from 'astro/config';

import cloudflare from "@astrojs/cloudflare";

// https://astro.build/config
export default defineConfig({
  experimental: {
    middleware: true
  },
  output: "server",
  adapter: cloudflare()
});

中间件在静态和SSR站点上工作,但是您可以在SSR站点上获得最大的好处,因此我们将上面的outputadapter字段设置为outputadapter字段(1011)。如果您想保持静态,请放弃这些。而且,当然,如果您喜欢使用另一个主机,请切换Cloudflare适配器。

ðµð½Astro JS中间件:中间件代码

要将Astro中间件添加到所有路由中,只需创建一个导出onRequest处理程序的src/middleware.ts(或src/middleware.js)文件:

import type { MiddlewareHandler } from 'astro';

export const onRequest: MiddlewareHandler<Response> = async function onRequest(
    { locals, request },
    next,
) {
    const { url } = request;
    const { pathname } = new URL(url);
    const timestamp = new Date().toISOString();

    (locals as { timestamp: string }).timestamp = timestamp;

    const response = await next();

    return response;
};

这里有一些有趣的观点:

  • onRequest有两个参数:上下文对象和next
    • 上下文对象上的request是传入的HTTP请求,您可以从中破坏URL以及other fields, which you will be familiar with
    • locals(在上下文对象上)让我们从中间件传递数据
    • next是一个函数;调用该功能使您可以访问该路由通常生成的响应(无中间件)
  • onRequest返回响应对象;在这种情况中

我们还设置了上面的locals.timestamp。我们将看到该值稍后传递到前端代码。

Astro JS中间件示例:添加记录

在我们的示例中,我们希望将请求记录到我们的无服务器记录服务中。由于我们只是在报告,因此onRequest可以返回将要发送的响应(无需修改响应)。

这是使用logtail:
来记录一些响应细节的额外代码

import type { MiddlewareHandler } from 'astro';
import { pack } from 'msgpackr';

const logtailSourceToken = import.meta.env.LOGTAIL_SOURCE_TOKEN;

export const onRequest: MiddlewareHandler<Response> = async function onRequest(
    { locals, request },
    next,
) {
    const { url } = request;
    const { pathname } = new URL(url);
    const timestamp = new Date().toISOString();

    (locals as { timestamp: string }).timestamp = timestamp;

    const logData = {
        dt: timestamp,
        level: 'info',
        message: 'astro-middleware-log',
        item: {
            pathname,
        },
    };

    await fetch('https://in.logtail.com', {
        method: 'POST',
        headers: {
            Authorization: `Bearer ${logtailSourceToken}`,
            'Content-Type': 'application/msgpack',
        },
        body: pack(logData),
    });

    const response = await next();

    return response;
};

Logtail has a REST API,我们可以使用fetch发送日志数据;请注意,fetch仅在25行中可用;无需导入它。您可能会从Content-Type标头中注意到,消息主体处于 msgpack格式。这比JSON更有效。要以MSGPACK格式编码logData常规JavaScript对象,我们使用了2中导入的msgpackr软件包。要注意的最后一块是您需要将LOGTAIL_SOURCE_TOKEN添加到.env文件中,以便可以在line 4中导入它。

ð¥!Astro JS中间件示例:前端

您可以更新中间件中的响应,也许可以替换模板参数。我们可能会使用此技术来按区域或一天中的时间来改变内容,并且只需更改中间软件中的返回响应即可。在中间件中添加新数据的另一种方法是使用locals对象。在中间软件代码中,我们在其中添加了时间戳:

locals.timestamp = timestamp;

我们可以在单个.astro文件中访问该值。这是一个示例:

---
const { timestamp } = Astro.locals as { timestamp: string };
---

<html lang="en-GB">
    <head> <!-- TRUNCATED... -->
    </head>

    <body>
        <main class="container">
            <section class="content">{timestamp}</section>
        </main>
    </body>
</html>

2行中,我们将timestampAstro.locals上拉下来。请注意,这可能是我们决定在中间软件功能中包含的任何任意值,尽管应该可以将值序列化为JSON。最后,该值现在可以在标记中使用,如line 11

Astro JS Middleware Example: Screen capture shows a browser window with a timestamp in large text.

有趣的是,中间件在静态和SSR站点上工作。但是,对于静态站点,此处显示的值将是构建时间的时间戳,而不是在提出请求时。但是,这仍然很有用,例如,将构建时间包括在页面页脚中。

ðð½AstroJS中间件示例:总结

在这篇文章中,我们看到了使用Astro中间件API的示例。特别是,我们看到了:

  • 如何将中间件添加到Astro站点;
  • 您如何将Astro中间件用于请求记录;和
  • 使用 astro.locals 将中间件的数据传递到标记中。

您可以看到full code for this project in the Rodney Lab GitHub repo。另外,请参见Astro docs,以防自写作以来的实验API发生了一些变化。希望您发现这篇文章有用!我很想听听您将如何在下一个项目中中间件。另外,让我知道上述内容的任何可能改进。

ðð½AstroJS中间件示例:反馈

您发现该帖子有用吗?您想看另一个主题的帖子吗?与新帖子的想法联系。另外,如果您喜欢我的写作风格,请与您的公司网站撰写一些帖子,以联系您的公司网站。请继续阅读以找到与之联系的方法,以下更远。如果您想支持与此类似的帖子,并且可以节省几美元,欧元或磅,请consider supporting me through Buy me a Coffee

最后,请随时在社交媒体帐户上分享所有发现有用的关注者的帖子。除了在下面留下评论外,您还可以通过Twitter上的@askRodney,Mastodon上的@rodney@toot.community#rodney元素矩阵室取得联系。另外,请参见further ways to get in touch with Rodney Lab。我定期发布在Astro以及SEO上。另外,subscribe to the newsletter to keep up-to-date通过我们的最新项目。