Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HttpContext.OnClose not firing #588

Open
faljse opened this issue Oct 30, 2023 · 1 comment
Open

HttpContext.OnClose not firing #588

faljse opened this issue Oct 30, 2023 · 1 comment

Comments

@faljse
Copy link

faljse commented Oct 30, 2023

I am sending sse events to my clients;
HTTPContext.onClose should fire if the http connection is closed; however it never does.

[Route(HttpVerbs.Get, "/alarms")]
public async Task<string> ReadAlarms() {
    Response.ContentType = "text/event-stream";
    CancellationTokenSource source = new CancellationTokenSource();
    HttpContext.OnClose((IHttpContext context) => {
        source.Cancel();
    });
    while(!source.Token.IsCancellationRequested) {
        await Task.Delay(1000);
        await Response.OutputStream.WriteAsync(new byte[] { 46 },0,1);
    }
}

Am i doing something wrong here?
Edit: also tried setting server.Listener.IgnoreWriteExceptions = false with no success: no exception thrown ever (#457)
It did work for #317; could using a controller/Route make a difference?

@rdeago
Copy link
Collaborator

rdeago commented Nov 2, 2023

Hello @faljse, thanks for using EmbedIO!

Your ReadAlarms method needs to return for the HTTP context to be closed. That's the very point of the HTTP context: it exists as long as the request is being served.

My advice is to use WebSockets for the type of communications you're aiming at here.

Alternatively, you can use HttpContext's own cancellation token to end your loop:

[Route(HttpVerbs.Get, "/alarms")]
public async Task<string> ReadAlarms() {
    Response.ContentType = "text/event-stream";
    for (; ;) {
        await Task.Delay(1000, HttpContext.CancellationToken);
        await Response.OutputStream.WriteAsync(new byte[] { 46 }, 0, 1, HttpContext.CancellationToken);
    }
}

Note that you don't need to check IsCancellationRequested: just pass the cancellation token along to any async method you call and let EmbedIO take care of any OperationCanceledException caused by the token.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants