Ocelot - 更改网关中的上游请求主体不会导致下游请求发生变化

Ocelot - Changing the upstream request body in gateway causes no change on downstream request

我设计的微服务架构如下:

网关使用Ocelot转发请求。我想更改从网关端的移动设备收到的请求中的正文,并在正文中添加新的 GUID。微服务使用 CQRS 模式,所以命令不应该 returns 任何东西。我实现了自定义中间件来更改 DownstreamContext:

    public override async Task Execute(DownstreamContext context)
    {
        var secondRequest = JObject.Parse(await context.DownstreamRequest.Content.ReadAsStringAsync());

        secondRequest["token"] = "test";
        secondRequest["newId"] = Guid.NewGuid();

        context.DownstreamRequest.Content = new StringContent(secondRequest.ToString(), Encoding.UTF8);

        await this.Next(context);
    }

我在调用 await this.Next(context) 之前调试了它和 DownstreamRequest 的内容;改变了,但是传入微服务的请求没有改变。有什么方法可以更改网关中的请求并将此请求以更改后的形式转发给微服务吗?

您可以为其使用自定义中间件

public class SetGuidMiddleware
{
    private readonly RequestDelegate _next

    public SetGuidMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        if (!HttpMethods.IsGet(context.Request.Method)
           && !HttpMethods.IsHead(context.Request.Method)
           && !HttpMethods.IsDelete(context.Request.Method)
           && !HttpMethods.IsTrace(context.Request.Method)
           && context.Request.ContentLength > 0)
        {
            //This line allows us to set the reader for the request back at the beginning of its stream.
            context.Request.EnableRewind();

            var buffer = new byte[Convert.ToInt32(context.Request.ContentLength)];
            await context.Request.Body.ReadAsync(buffer, 0, buffer.Length);
            var bodyAsText = Encoding.UTF8.GetString(buffer);

            var secondRequest = JObject.Parse(bodyAsText);
            secondRequest["token"] = "test";
            secondRequest["newId"] = Guid.NewGuid();

            var requestContent = new StringContent(secondRequest.ToString(), Encoding.UTF8, "application/json");
            context.Request.Body = await requestContent.ReadAsStreamAsync();
        }

        await _next(context);
    }
}

并在Ocelot之前使用它

app.UseMiddleware<SetGuidMiddleware>();
app.UseOcelot().Wait();