我正在编写一个自定义OWIN中间件来记录所有http请求及其响应。我想用trackingId“关联”这些。这是代码:
public class PacketTrackingMiddleware
{
private readonly AppFunc _next;
public PacketTrackingMiddleware(AppFunc next)
{
_next = next;
}
public async Task Invoke(IDictionary<string, object> environment)
{
IOwinContext context = new OwinContext(environment);
var request = context.Request;
var response = context.Response;
//capture details about the caller identity
var identity = (request.User != null && request.User.Identity.IsAuthenticated)
? request.User.Identity.Name
: "(anonymous)";
var apiPacket = new ApiPacket
{
CallerIdentity = identity
};
//buffer the request stream in order to intercept downstream reads
var requestBuffer = new MemoryStream();
request.Body = requestBuffer;
//buffer the response stream in order to intercept downstream writes
var responseStream = response.Body;
var responseBuffer = new MemoryStream();
response.Body = responseBuffer;
//add the "Http-Tracking-Id" response header
context.Response.OnSendingHeaders(state =>
{
var ctx = state as IOwinContext;
if (ctx == null) return;
var resp = ctx.Response;
//adding the tracking id response header so that the user
//of the API can correlate the call back to this entry
resp.Headers.Add("http-tracking-id", new[] { apiPacket.TrackingId.ToString("d") });
}, context);
//invoke the next middleware in the pipeline
await _next.Invoke(environment);
//rewind the request and response buffers to record their content
WriteRequestHeaders(request, apiPacket);
requestBuffer.Seek(0, SeekOrigin.Begin);
var requestReader = new StreamReader(requestBuffer);
apiPacket.Request = await requestReader.ReadToEndAsync();
WriteResponseHeaders(response, apiPacket);
responseBuffer.Seek(0, SeekOrigin.Begin);
var reader = new StreamReader(responseBuffer);
apiPacket.Response = await reader.ReadToEndAsync();
//write the apiPacket to the database
//await database.InsterRecordAsync(apiPacket);
System.Diagnostics.Debug.WriteLine("TrackingId: " + apiPacket.TrackingId);
//make sure the response we buffered is flushed to the client
responseBuffer.Seek(0, SeekOrigin.Begin);
await responseBuffer.CopyToAsync(responseStream);
}
private static void WriteRequestHeaders(IOwinRequest request, ApiPacket packet)
{
packet.Verb = request.Method;
packet.RequestUri = request.Uri;
packet.RequestHeaders = request.Headers;
}
private static void WriteResponseHeaders(IOwinResponse response, ApiPacket packet)
{
packet.StatusCode = response.StatusCode;
packet.ReasonPhrase = response.ReasonPhrase;
packet.ResponseHeaders = response.Headers;
}
}
我在将http-tracking-id添加到响应标头时遇到了问题(这些行在这里)。
context.Response.OnSendingHeaders(state =>
{
var ctx = state as IOwinContext;
if (ctx == null) return;
var resp = ctx.Response;
resp.Headers.Add("http-tracking-id", new[] { apiPacket.TrackingId.ToString("d") });
}, context);
添加标题时,我有时会收到此错误:
用户代码未对HttpException进行处理。
其他信息:服务器无法在HTTP标头后追加标头 已发送。
编辑1: 我只是通过运行api来测试它,这会打开我的http://localhost:64051/地址的chrome。如果我浏览到任何实际的API(http://localhost:64051/api/Accounts/21067),例如,我没有收到错误。浏览到网站的根目录时,我应该以某种方式发回404吗?
答案 0 :(得分:1)
我认为这可能是一个简单的修复。请尝试:
SELECT
num_col1,
cast(num_col2 as number(10,5)) as num_col2,
flo_col1,
cast(flo_col2 as float(5)) as flo_col2
FROM OPENQUERY (ORADB, 'SELECT num_col1, num_col2, flo_col1, flo_col2 FROM oratab')
但不在var responseHeaders = (IDictionary<string, string[]>)environment["owin.ResponseHeaders"];
responseHeaders["http-tracking-id"] = new[] {apiPacket.TrackingId.ToString("d")};
。与其他人一致。