在典型的请求-响应循环中,请求和响应头包含很多附加信息。本文讨论如何检索它们并将它们存储在数据库中。在本文中,我们将使用 PostgreSQL 作为数据库,并使用dotConnect for PostgreSQL连接到它。
先决条件
为了能够使用本文中演示的代码示例,您应该在系统中安装以下内容:
- Visual Studio 2019 Community Edition
- PostgreSQL
- dotConnect for PostgreSQL
您可以从这里下载 .NET Core 。
你可以从这里下载 Visual Studio 2019 。
您可以从这里下载 PostgreSQL 。
您可以从这里下载 dotConnect for PostgreSQL 的试用版。
在 Visual Studio 2019 中创建一个新的 ASP.NET Core 5.0 项目
假设您的计算机上已安装必要的软件,请按照下面列出的步骤创建一个新的 ASP.NET Core Web API 项目。
- 首先,打开 Visual Studio 2019 IDE
- 接下来,在 IDE 加载后单击“创建新项目”
- 在“创建新项目”屏幕中,选择“ASP.NET Core Web API”作为项目模板。
- 单击“下一步”按钮
- 指定项目名称和位置 – 应将其存储在系统中的位置
- 或者,单击“将解决方案和项目放在同一目录中”复选框。
- 接下来,单击“创建”按钮
- 在接下来显示的“创建新的 ASP.NET Core Web 应用程序”对话框窗口中,选择“API”作为项目模板。
- 在“附加信息”屏幕中,.NET 5.0 是框架版本。
- 您应该通过禁用相应的复选框来禁用“为 HTTPS 配置”和“启用 Docker 支持”选项。
- 由于在本示例中我们不会使用身份验证,因此将身份验证指定为“无身份验证”。
- 最后,单击“创建”按钮完成该过程。
这将在 Visual Studio 中创建一个新的 ASP.NET Core Web API 项目。
安装 NuGet 包
要在 ASP.NET Core 5 中使用 dotConnect for PostgreSQL,您应该将以下包安装到您的项目中:
Devart.Data.PostgreSQL
您有两种安装此包的选项:通过 NuGet 包管理器或通过运行以下命令的包管理器控制台窗口。
PM> Install-Package Devart.Data.PostgreSQL
ASP.NET Core 中的请求和响应标头
请求标头提供有关请求的资源或请求它的客户端的更多信息。您可以利用请求标头向 HTTP 请求添加额外信息。
响应头包含有关响应的附加信息,例如其位置和服务器。它是一个只能在 HTTP 响应中使用的 HTTP 标头,不必对消息的内容做任何事情。要为响应提供更多上下文,您可以使用响应标头,例如 Age、Server 和 Location。
请求头和响应头都表示为键值对的集合,可以在客户端和服务器之间来回传递。
在 ASP.NET Core 中读取请求和响应标头
您可以使用 HttpContext 类的 Request 和 Response 属性读取请求和响应标头。这些属性分别是 HttpRequest 和 HttpResponse 类型。
您可以使用以下代码在 ASP.NET Cre 中检索请求标头:
List < string > AllRequestHeaders = new List < string > ();
var requestHeaders = httpContext.Request.Headers.Where(x => AllRequestHeaders.All(h => h != x.Key)).Select(x => x.Key);
以下代码片段可用于检索所有响应标头:
List < string > AllResponseHeaders = new List < string > ();
var uniqueResponseHeaders = httpContext.Response.Headers.Where(x => AllResponseHeaders.All(h => h != x.Key)).Select(x => x.Key);
构建一个中间件来读取请求和响应头
中间件是处理请求和响应的软件组件。ASP.Net Core 通常有一系列中间件组件——这些中间件组件要么处理请求,要么将它们传递给请求处理管道中的下一个组件。
在项目的根目录中创建一个新类并将其命名为 RequestResponseHeaderMiddleware。接下来,将默认代码替换为以下内容:
public class RequestResponseHeadersMiddleware {
private readonly RequestDelegate _next;
public RequestResponseHeadersMiddleware(RequestDelegate next) {
_next = next;
}
public async Task Invoke(HttpContext httpContext) {
await _next.Invoke(httpContext);
}
}
这是 ASP.NET Core 中中间件的极简实现。但是,除了将控制权传递给管道中的下一个组件之外,它不会做任何事情。
我们需要添加读取请求和响应头的逻辑。我们已经在上一节中编写了代码。这是我们中间件的更新版本:
public class RequestResponseHeadersMiddleware {
private readonly RequestDelegate _next;
public readonly List < string > AllRequestHeaders = new List < string > ();
public readonly List < string > AllResponseHeaders = new List < string > ();
public RequestResponseHeadersMiddleware(RequestDelegate next) {
_next = next;
}
public async Task Invoke(HttpContext httpContext) {
var requestHeaders = httpContext.Request.Headers.Where(x => AllRequestHeaders.All(h => h != x.Key)).Select(x => x.Key);
AllRequestHeaders.AddRange(requestHeaders);
await this._next.Invoke(httpContext);
var uniqueResponseHeaders = httpContext.Response.Headers.Where(x => AllResponseHeaders.All(h => h != x.Key)).Select(x => x.Key);
AllResponseHeaders.AddRange(uniqueResponseHeaders);
await _next.Invoke(httpContext);
}
}
为中间件创建扩展方法
我们现在将为我们的中间件创建一个扩展方法,以便能够在 Startup 类的 Configure 方法中方便地配置中间件。
为此,请在名为 RequestResponseHeadersMiddlewareExtensions.cs 的文件中创建一个名为 RequestResponseHeadersMiddlewareExtensions 的新类,其中包含以下代码:
public static class RequestResponseHeadersMiddlewareExtensions {
public static IApplicationBuilder UseRequestResponseHeadersMiddleware(this IApplicationBuilder builder) {
return builder.UseMiddleware < RequestResponseHeadersMiddleware > ();
}
}
在启动类中配置中间件
您可以在 Startup 类的 Configure 方法中编写以下代码来启用我们迄今为止构建的自定义中间件。
app.UseRequestResponseHeadersMiddleware();
创建模型
现在在扩展名为 .cs 的同名文件中创建以下类。我们将使用它来存储请求和响应标头值。
public class RequestResponseHeader {
public string RequestHeader {
get;
set;
}
public string ResponseHeader {
get;
set;
}
}
创建 DbManager 类
DbManager 类使用 dotConnect for Postgresql 包装对数据库的所有调用。它只有一种名为 Save 的方法来将请求和响应头值保存在 Postgresql 数据库中。
public class DbManager {
private readonly string connectionString = "Some connection string...";
public int Save(RequestResponseHeader requestResponseHeader) {
try {
using(PgSqlConnection pgSqlConnection = new PgSqlConnection(connectionString)) {
using(PgSqlCommand cmd = new PgSqlCommand()) {
cmd.CommandText = "INSERT INTO
public.requestresponseheaders " +
"(requestheader, responseheader) " + "VALUES (@requestheader, @responseheader)";
cmd.Connection = pgSqlConnection;
cmd.Parameters.AddWithValue("requestkey", requestResponseHeader.RequestHeader);
cmd.Parameters.AddWithValue("responsevalue", requestResponseHeader.ResponseHeader);
if (pgSqlConnection.State != System.Data.ConnectionState.Open) pgSqlConnection.Open();
return cmd.ExecuteNonQuery();
}
}
} catch {
throw;
}
}
}
从中间件调用 Save 方法
我们现在将修改我们实现的中间件,以使用 dotConnect for PostgreSQL 在 PostgreSQL 数据库中存储请求和响应标头。
您可以使用以下代码片段从我们之前实现的中间件中调用 DbManager 类的 Save 方法。
for (int index = 0; index < AllRequestHeaders.Count; index++) {
RequestResponseHeader requestResponseHeader = new
RequestResponseHeader();
requestResponseHeader.RequestHeader = AllRequestHeaders[index];
requestResponseHeader.ResponseHeader = AllResponseHeaders[index];
dbManager.Save(requestResponseHeader);
}
正如您在此处看到的,有两个字符串集合,即 AllRequestHeaders 和 AllResponseHeaders,分别保存请求和响应标头值。我们在文章前面看到了它是如何完成的。
在此代码片段中,创建了 RequestResponseHeader 的一个实例,初始化其属性,然后将此实例作为参数传递给 Save 方法。
下面是中间件的完整代码,供大家参考:
public class RequestResponseHeadersMiddleware {
private readonly RequestDelegate _next;
public readonly List < string > AllRequestHeaders = new List < string > ();
public readonly List < string > AllResponseHeaders = new List < string > ();
private readonly DbManager dbManager = new DbManager();
public RequestResponseHeadersMiddleware(RequestDelegate next) {
_next = next;
}
public async Task Invoke(HttpContext httpContext) {
var requestHeaders = httpContext.Request.Headers.Where(x => AllRequestHeaders.All(h => h != x.Key)).Select(x => x.Key);
AllRequestHeaders.AddRange(requestHeaders);
await this._next.Invoke(httpContext);
var uniqueResponseHeaders = httpContext.Response.Headers.Where(x => AllResponseHeaders.All(h => h != x.Key)).Select(x => x.Key);
AllResponseHeaders.AddRange(uniqueResponseHeaders);
await _next.Invoke(httpContext);
for (int index = 0; index < AllRequestHeaders.Count; index++) {
RequestResponseHeader requestResponseHeader = new
RequestResponseHeader();
requestResponseHeader.RequestHeader = AllRequestHeaders[index];
requestResponseHeader.ResponseHeader = AllResponseHeaders[index];
dbManager.Save(requestResponseHeader);
}
}
}
总结
在 ASP.NET Core 中,您可以轻松读取应用程序中的请求和响应标头。请求标头允许您使用存储为键值对的可选数据。响应头包括关于响应的额外信息,允许将响应发送到客户端的更全面的上下文。