Closed dingfengwu closed 4 years ago
Maybe we could add here some more information: SSE (Server-Sent Events) isn't working for me
I've faced with same problem. Our .NET Core backend sits behind API Gateway (Ocelot) and I've added SignalR hub recently. We only need one-way communication from backend to SPA (front-end app). Server-Sent Event (SSE) transport is one of three options SignalR provides and it looks like a perfect lightweight candiate. Client app works flawlesly when it is connected direcetly to the backend (which is IIS hosted), but when accessing via API Gateway the Ocelot stucks.
First request (the handshake) passes fine:
HTTP POST /myservice/hubs/notifications/negotiate HTTP/1.1
HTTP/1.1 200 OK
Content-Length: 125
Content-Type: application/json
Server: Kestrel
Date: Fri, 01 Nov 2019 12:49:48 GMT
{"connectionId":"IepBcjkYfdnXxg3Vn-z24Q","availableTransports":[{"transport":"ServerSentEvents","transferFormats":["Text"]}]}
However the second connection which should be a long-living text/event-stream connection fails after few seconds:
GET /myservice/hubs/notifications?id=IepBcjkYfdnXxg3Vn-z24Q HTTP/1.1
HTTP/1.1 200 OK
Cache-Control: no-cache
Content-Length: 49
Content-Type: text/event-stream
Server: Kestrel
Date: Fri, 01 Nov 2019 12:50:03 GMT
:
data: {"error":"Handshake was canceled."}
The Ocelot outputs this into console log:
18:14:29:637 Debug: Ocelot.Requester.Middleware.HttpRequesterMiddleware requestId: 0HLQUQ3CANMQU:00000002, previousRequestId: no previous request id, message: setting http response message
18:14:29:642 Debug: Ocelot.Responder.Middleware.ResponderMiddleware requestId: 0HLQUQ3CANMQU:00000002, previousRequestId: no previous request id, message: no pipeline errors, setting and returning completed response
18:14:29:644 Debug: Ocelot.Errors.Middleware.ExceptionHandlerMiddleware requestId: 0HLQUQ3CANMQU:00000002, previousRequestId: no previous request id, message: ocelot pipeline finished
After short investigation it appears that pipeline was not designed to pass-though streamed responses:
HttpRequesterMiddleware simply reads the whole response:
var response = await _requester.GetResponse(context);
...
context.DownstreamResponse = new DownstreamResponse(response.Data);
await _next.Invoke(context);
The requested uses standard HttpClient to read the response.
However, I see that Ocelot has special (dedicated) pipeline to handle websocket connections:
// If the request is for websockets upgrade we fork into a different pipeline
builder.MapWhen(context => context.HttpContext.WebSockets.IsWebSocketRequest,
app =>
{
app.UseDownstreamRouteFinderMiddleware();
app.UseDownstreamRequestInitialiser();
app.UseLoadBalancingMiddleware();
app.UseDownstreamUrlCreatorMiddleware();
app.UseWebSocketsProxyMiddleware();
});
The WebSocketsProxyMiddleware middleware contains an infinite loop that pumps the data in both directions:
var destinationUri = new Uri(serverEndpoint);
await client.ConnectAsync(destinationUri, context.RequestAborted);
using (var server = await context.WebSockets.AcceptWebSocketAsync(client.SubProtocol))
{
var bufferSize = DefaultWebSocketBufferSize;
await Task.WhenAll(PumpWebSocket(client, server, bufferSize, context.RequestAborted), PumpWebSocket(server, client, bufferSize, context.RequestAborted));
}
The HttpRequesterMiddleware does not make any attempts to pump streamable content (say if HTTP Content-Type is text/event-stream).
Can we please have either alternative pipeline for SSE or, may be, some adjustments in HttpRequesterMiddleware that will make pumping SSE traffic possible?
I would appreciate if @TomPallister comment on this :)
@snb83 That means it's not working for you, right?
@snb83 That means it's not working for you, right?
Yes, SSE transport does not work for me when notifications are routed via Ocelot API Gateway.
Hi, ¿there are some update about that?
Hi, any update on this?
Hello any update on this? I am also facing the same issue.
Interested on looking how this goes too. 👀
Watching this issue for the updates. I faced the same challenge today and had to spend several late night hours before concluding...
@krishnankuppaswamy @byjokese @coppercarpenter @ganhj99 @luheorga @trickreich Hello guys!
@dingfengwu And, dear author,
Welcome to Ocelot to contribute! As a team, we are open to discuss, review PRs... If someone has an intention to contribute, then Welcome!
@snb83 commented on Nov 1, 2019
Hi Sergei! Right, we have different pipelines for Http & Websoket traffic.
Can we please have either alternative pipeline for SSE or, may be, some adjustments in
HttpRequesterMiddleware
that will make pumping SSE traffic possible?
Yes, we can. But, will you contribute actively? Seems we have to design & develop 3rd pipeline for SSE protocol... I'm not sure we can reuse Http pipeline somehow... I can reopen this issue, if you're still with Ocelot... 😉
keeping some notes for the feature:
HttpContext.Features.Get<IHttpResponseBodyFeature>().DisableBuffering()
https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.http.features.ihttpresponsebodyfeature?view=aspnetcore-8.0
@ggnaegi @raman-m
it's related to this discussion: https://github.com/ThreeMammals/Ocelot/discussions/1943
add config in public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
, not using middleware
app.Use(async (context, next) => {
context.Request.EnableBuffering();
await next();
});
Ocelot setting json:
{
"DownstreamPathTemplate": "/notice/{eveything}",
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 9000
}
],
"UpstreamPathTemplate": "/notice/{eveything}",
"UpstreamHttpMethod": [ "POST", "PUT", "GET", "DELETE", "PATCH" ],
"DangerousAcceptAnyServerCertificateValidator": true
},
Hello @truongnguyengithub! What were you trying to communicate or demonstrate?
Were you suggesting that the Server-Side Events protocol functions effectively with context.Request.EnableBuffering()
without the need for .DisableBuffering()
?
I would mention that in certain applications and user environments, both methods might be viable, although we do not officially support the SSE protocol. There have been no professional pull requests for an Ocelot Core update. However, we acknowledge the widespread popularity of SSE, and as a team, we are prepared to give priority to the development of this protocol to finally enable it in routing schemes.
Hi @raman-m
I am looking to solve the SSE issue when using Ocelot for my project. It would be great if Ocelot Core was updated with this protocol. I hope to have a release soon.
@truongnguyengithub, are you prepared for a professional contribution? If so, I will reopen the issue once the PR is opened.
❓
Message from repo maintainer on November 30, 2023
Hello Devin Wu! My short answer: No Ocelot doesn't support SSE protocol.
Why did you close the issue on Jul 24, 2020? 🥲 Tired of notifications?...