public static async Task EndHttpHandlerRequestAsync(this IResponse httpRes, bool skipHeaders = false, bool skipClose = false, Func <IResponse, Task> afterHeaders = null) { if (!skipHeaders) { httpRes.ApplyGlobalResponseHeaders(); } if (afterHeaders != null) { await afterHeaders(httpRes); } var req = httpRes.Request; if (req != null && !req.Items.ContainsKey(Keywords.HasLogged)) { HostContext.TryResolve <IRequestLogger>()? .Log(req, req.Dto, null, TimeSpan.Zero); } if (!skipClose && !httpRes.IsClosed) { httpRes.Close(); } HostContext.CompleteRequest(req); }
public static async Task EndHttpHandlerRequestAsync(this IResponse httpRes, bool skipHeaders = false, bool skipClose = false, Func <IResponse, Task> afterHeaders = null) { if (!skipHeaders) { httpRes.ApplyGlobalResponseHeaders(); } if (afterHeaders != null) { try { await afterHeaders(httpRes).ConfigAwait(); } catch (Exception e) { var log = LogManager.LogFactory.GetLogger(typeof(HttpExtensions)); log.Error("Error executing async afterHeaders: " + e.Message, e); } } var req = httpRes.Request; if (req != null && !req.Items.ContainsKey(Keywords.HasLogged)) { HostContext.TryResolve <IRequestLogger>()?.Log(req, req.Dto, httpRes.Dto, TimeSpan.Zero); } if (!skipClose && !httpRes.IsClosed) { await httpRes.CloseAsync().ConfigAwait(); } HostContext.CompleteRequest(req); }
public override Task ProcessRequestAsync(IRequest req, IResponse res, string operationName) { if (HostContext.ApplyCustomHandlerRequestFilters(req, res)) { return(EmptyTask); } res.ApplyGlobalResponseHeaders(); var feature = HostContext.GetPlugin <ServerEventsFeature>(); if (feature.OnHeartbeatInit != null) { feature.OnHeartbeatInit(req); } var subscriptionId = req.QueryString["id"]; if (!req.TryResolve <IServerEvents>().Pulse(subscriptionId)) { res.StatusCode = 404; res.StatusDescription = "Subscription {0} does not exist".Fmt(subscriptionId); } res.EndHttpHandlerRequest(skipHeaders: true); return(EmptyTask); }
public override Task ProcessRequestAsync(IRequest req, IResponse res, string operationName) { if (HostContext.ApplyCustomHandlerRequestFilters(req, res)) { return(TypeConstants.EmptyTask); } res.ApplyGlobalResponseHeaders(); var serverEvents = req.TryResolve <IServerEvents>(); serverEvents.RemoveExpiredSubscriptions(); var feature = HostContext.GetPlugin <ServerEventsFeature>(); if (feature.OnHeartbeatInit != null) { feature.OnHeartbeatInit(req); } if (req.Response.IsClosed) { return(TypeConstants.EmptyTask); } var subscriptionId = req.QueryString["id"]; var subscription = serverEvents.GetSubscriptionInfo(subscriptionId); if (subscription == null) { res.StatusCode = 404; res.StatusDescription = ErrorMessages.SubscriptionNotExistsFmt.Fmt(subscriptionId); res.EndHttpHandlerRequest(skipHeaders: true); return(TypeConstants.EmptyTask); } if (!feature.CanAccessSubscription(req, subscription)) { res.StatusCode = 403; res.StatusDescription = "Invalid User Address"; res.EndHttpHandlerRequest(skipHeaders: true); return(TypeConstants.EmptyTask); } if (!serverEvents.Pulse(subscriptionId)) { res.StatusCode = 404; res.StatusDescription = "Subscription {0} does not exist".Fmt(subscriptionId); } res.EndHttpHandlerRequest(skipHeaders: true); return(TypeConstants.EmptyTask); }
/// <summary> /// End a HttpHandler Request /// </summary> public static void EndHttpHandlerRequest(this IResponse httpRes, bool skipHeaders = false, bool skipClose = false, Action <IResponse> afterHeaders = null) { if (!skipHeaders) { httpRes.ApplyGlobalResponseHeaders(); } afterHeaders?.Invoke(httpRes); if (!skipClose && !httpRes.IsClosed) { httpRes.Close(); } HostContext.CompleteRequest(httpRes.Request); }
public static async Task WriteErrorToResponse(this IResponse httpRes, IRequest httpReq, string contentType, string operationName, string errorMessage, Exception ex, int statusCode) { if (ex == null) { ex = new Exception(errorMessage); } var errorDto = ex.ToErrorResponse(); httpRes.Dto = errorDto; HostContext.AppHost.OnExceptionTypeFilter(ex, errorDto.ResponseStatus); if (await HandleCustomErrorHandler(httpRes, httpReq, contentType, statusCode, errorDto, ex)) { return; } if (!httpRes.HasStarted) { if ((httpRes.ContentType == null || httpRes.ContentType == MimeTypes.Html) && contentType != null && contentType != httpRes.ContentType) { httpRes.ContentType = contentType; } if (HostContext.Config.AppendUtf8CharsetOnContentTypes.Contains(contentType)) { httpRes.ContentType += ContentFormat.Utf8Suffix; } var hold = httpRes.StatusDescription; var hasDefaultStatusDescription = hold == null || hold == "OK"; httpRes.StatusCode = statusCode; httpRes.StatusDescription = hasDefaultStatusDescription ? (errorMessage ?? HttpStatus.GetStatusDescription(statusCode)) : hold; httpRes.ApplyGlobalResponseHeaders(); } var serializer = HostContext.ContentTypes.GetStreamSerializerAsync(contentType ?? httpRes.ContentType); if (serializer != null) { await serializer(httpReq, errorDto, httpRes.OutputStream); } httpRes.EndHttpHandlerRequest(skipHeaders: true); }
/// <summary> /// End a HttpHandler Request /// </summary> public static void EndHttpHandlerRequest(this IResponse httpRes, bool skipHeaders = false, bool skipClose = false, Action <IResponse> afterHeaders = null) { if (!skipHeaders) { httpRes.ApplyGlobalResponseHeaders(); } if (afterHeaders != null) { afterHeaders(httpRes); } if (!skipClose) { httpRes.Close(); } //skipHeaders used when Apache+mod_mono doesn't like: //response.OutputStream.Flush(); //response.Close(); }
public static void WriteBytesToResponse(this IResponse res, byte[] responseBytes, string contentType) { res.ContentType = HostContext.Config.AppendUtf8CharsetOnContentTypes.Contains(contentType) ? contentType + ContentFormat.Utf8Suffix : contentType; res.ApplyGlobalResponseHeaders(); res.SetContentLength(responseBytes.Length); try { res.OutputStream.Write(responseBytes, 0, responseBytes.Length); res.Flush(); } catch (Exception ex) { ex.HandleResponseWriteException(res.Request, res, contentType); } finally { res.EndRequest(skipHeaders: true); } }
/// <summary> /// End a HttpHandler Request /// </summary> public static void EndHttpHandlerRequest(this IResponse httpRes, bool skipHeaders = false, bool skipClose = false, Action <IResponse> afterHeaders = null) { if (!skipHeaders) { httpRes.ApplyGlobalResponseHeaders(); } afterHeaders?.Invoke(httpRes); var req = httpRes.Request; if (req != null && !req.Items.ContainsKey(Keywords.HasLogged)) { HostContext.TryResolve <IRequestLogger>()?.Log(req, req.Dto, httpRes.Dto, TimeSpan.Zero); } if (!skipClose && !httpRes.IsClosed) { httpRes.Close(); } HostContext.CompleteRequest(req); }
public static async Task WriteBytesToResponse(this IResponse res, byte[] responseBytes, string contentType, CancellationToken token = default(CancellationToken)) { res.ContentType = HostContext.Config.AppendUtf8CharsetOnContentTypes.Contains(contentType) ? contentType + ContentFormat.Utf8Suffix : contentType; res.ApplyGlobalResponseHeaders(); res.SetContentLength(responseBytes.Length); try { await res.OutputStream.WriteAsync(responseBytes, token); await res.FlushAsync(token); } catch (Exception ex) { await ex.HandleResponseWriteException(res.Request, res, contentType); } finally { res.EndRequest(skipHeaders: true); } }
public override Task ProcessRequestAsync(IRequest req, IResponse res, string operationName) { if (HostContext.ApplyCustomHandlerRequestFilters(req, res)) { return(TypeConstants.EmptyTask); } var feature = HostContext.GetPlugin <ServerEventsFeature>(); var session = req.GetSession(); if (feature.LimitToAuthenticatedUsers && !session.IsAuthenticated) { session.ReturnFailedAuthentication(req); return(TypeConstants.EmptyTask); } res.ContentType = MimeTypes.ServerSentEvents; res.AddHeader(HttpHeaders.CacheControl, "no-cache"); res.ApplyGlobalResponseHeaders(); res.UseBufferedStream = false; res.KeepAlive = true; if (feature.OnInit != null) { feature.OnInit(req); } res.Flush(); var serverEvents = req.TryResolve <IServerEvents>(); var userAuthId = session != null ? session.UserAuthId : null; var anonUserId = serverEvents.GetNextSequence("anonUser"); var userId = userAuthId ?? ("-" + anonUserId); var displayName = session.GetSafeDisplayName() ?? "user" + anonUserId; var now = DateTime.UtcNow; var subscriptionId = SessionExtensions.CreateRandomSessionId(); //Handle both ?channel=A,B,C or ?channels=A,B,C var channels = new List <string>(); var channel = req.QueryString["channel"]; if (!string.IsNullOrEmpty(channel)) { channels.AddRange(channel.Split(',')); } channel = req.QueryString["channels"]; if (!string.IsNullOrEmpty(channel)) { channels.AddRange(channel.Split(',')); } if (channels.Count == 0) { channels = EventSubscription.UnknownChannel.ToList(); } var subscription = new EventSubscription(res) { CreatedAt = now, LastPulseAt = now, Channels = channels.ToArray(), SubscriptionId = subscriptionId, UserId = userId, UserName = session != null ? session.UserName : null, DisplayName = displayName, SessionId = req.GetSessionId(), IsAuthenticated = session != null && session.IsAuthenticated, UserAddress = req.UserHostAddress, OnPublish = feature.OnPublish, //OnError = feature.OnError, Meta = { { "userId", userId }, { "displayName", displayName }, { "channels", string.Join(",", channels) }, { AuthMetadataProvider.ProfileUrlKey, session.GetProfileUrl() ?? AuthMetadataProvider.DefaultNoProfileImgUrl }, } }; if (feature.OnCreated != null) { feature.OnCreated(subscription, req); } if (req.Response.IsClosed) { return(TypeConstants.EmptyTask); //Allow short-circuiting in OnCreated callback } var heartbeatUrl = feature.HeartbeatPath != null ? req.ResolveAbsoluteUrl("~/".CombineWith(feature.HeartbeatPath)).AddQueryParam("id", subscriptionId) : null; var unRegisterUrl = feature.UnRegisterPath != null ? req.ResolveAbsoluteUrl("~/".CombineWith(feature.UnRegisterPath)).AddQueryParam("id", subscriptionId) : null; heartbeatUrl = AddSessionParamsIfAny(heartbeatUrl, req); unRegisterUrl = AddSessionParamsIfAny(unRegisterUrl, req); subscription.ConnectArgs = new Dictionary <string, string>(subscription.Meta) { { "id", subscriptionId }, { "unRegisterUrl", unRegisterUrl }, { "heartbeatUrl", heartbeatUrl }, { "updateSubscriberUrl", req.ResolveAbsoluteUrl("~/event-subscribers/" + subscriptionId) }, { "heartbeatIntervalMs", ((long)feature.HeartbeatInterval.TotalMilliseconds).ToString(CultureInfo.InvariantCulture) }, { "idleTimeoutMs", ((long)feature.IdleTimeout.TotalMilliseconds).ToString(CultureInfo.InvariantCulture) } }; if (feature.OnConnect != null) { feature.OnConnect(subscription, subscription.ConnectArgs); } serverEvents.Register(subscription, subscription.ConnectArgs); var tcs = new TaskCompletionSource <bool>(); subscription.OnDispose = _ => { try { res.EndHttpHandlerRequest(skipHeaders: true); } catch { } tcs.SetResult(true); }; return(tcs.Task); }
public static async Task WriteErrorToResponse(this IResponse httpRes, IRequest httpReq, string contentType, string operationName, string errorMessage, Exception ex, int statusCode) { if (ex == null) { ex = new Exception(errorMessage); } httpRes.Dto = HostContext.AppHost.CreateErrorResponse(ex, request: httpReq?.Dto); if (await HandleCustomErrorHandler(httpRes, httpReq, contentType, statusCode, httpRes.Dto, ex)) { return; } var hostConfig = HostContext.Config; if (!httpRes.HasStarted) { if ((httpRes.ContentType == null || httpRes.ContentType == MimeTypes.Html) && contentType != null && contentType != httpRes.ContentType) { httpRes.ContentType = contentType; } if (hostConfig.AppendUtf8CharsetOnContentTypes.Contains(contentType)) { httpRes.ContentType += ContentFormat.Utf8Suffix; } var hold = httpRes.StatusDescription; var hasDefaultStatusDescription = hold is null or "OK"; httpRes.StatusCode = statusCode; httpRes.StatusDescription = hasDefaultStatusDescription ? (errorMessage ?? HttpStatus.GetStatusDescription(statusCode)) : hold; httpRes.ApplyGlobalResponseHeaders(); } var callback = httpReq.GetJsonpCallback(); var doJsonp = hostConfig.AllowJsonpRequests && !string.IsNullOrEmpty(callback); if (doJsonp) { httpRes.StatusCode = 200; await httpRes.OutputStream.WriteAsync(DataCache.CreateJsonpPrefix(callback)); } var serializer = HostContext.ContentTypes.GetStreamSerializerAsync(contentType ?? httpRes.ContentType); if (serializer != null) { var jsconfig = hostConfig.AllowJsConfig ? httpReq?.QueryString[Keywords.JsConfig] : null; using (jsconfig != null ? JsConfig.CreateScope(jsconfig) : null) { await serializer(httpReq, httpRes.Dto, httpRes.OutputStream); } } if (doJsonp) { await httpRes.OutputStream.WriteAsync(DataCache.JsonpSuffix); } httpRes.EndHttpHandlerRequest(skipHeaders: true); }
public override Task ProcessRequestAsync(IRequest req, IResponse res, string operationName) { var feature = HostContext.GetPlugin <ServerEventsFeature>(); var session = req.GetSession(); if (feature.LimitToAuthenticatedUsers && !session.IsAuthenticated) { session.ReturnFailedAuthentication(req); return(EmptyTask); } res.ContentType = MimeTypes.ServerSentEvents; res.AddHeader(HttpHeaders.CacheControl, "no-cache"); res.ApplyGlobalResponseHeaders(); res.UseBufferedStream = false; res.KeepAlive = true; if (feature.OnInit != null) { feature.OnInit(req); } res.Flush(); var serverEvents = req.TryResolve <IServerEvents>(); var userAuthId = session != null ? session.UserAuthId : null; var anonUserId = serverEvents.GetNextSequence("anonUser"); var userId = userAuthId ?? ("-" + anonUserId); var displayName = session.GetSafeDisplayName() ?? "user" + anonUserId; var now = DateTime.UtcNow; var subscriptionId = SessionExtensions.CreateRandomSessionId(); var subscription = new EventSubscription(res) { CreatedAt = now, LastPulseAt = now, Channel = req.QueryString["channel"] ?? EventSubscription.UnknownChannel, SubscriptionId = subscriptionId, UserId = userId, UserName = session != null ? session.UserName : null, DisplayName = displayName, SessionId = req.GetPermanentSessionId(), IsAuthenticated = session != null && session.IsAuthenticated, OnPublish = feature.OnPublish, Meta = { { "userId", userId }, { "displayName", displayName }, { AuthMetadataProvider.ProfileUrlKey, session.GetProfileUrl() ?? AuthMetadataProvider.DefaultNoProfileImgUrl }, } }; if (feature.OnCreated != null) { feature.OnCreated(subscription, req); } var heartbeatUrl = req.ResolveAbsoluteUrl("~/".CombineWith(feature.HeartbeatPath)) .AddQueryParam("id", subscriptionId); var unRegisterUrl = req.ResolveAbsoluteUrl("~/".CombineWith(feature.UnRegisterPath)) .AddQueryParam("id", subscriptionId); var privateArgs = new Dictionary <string, string>(subscription.Meta) { { "id", subscriptionId }, { "unRegisterUrl", unRegisterUrl }, { "heartbeatUrl", heartbeatUrl }, { "heartbeatIntervalMs", ((long)feature.HeartbeatInterval.TotalMilliseconds).ToString(CultureInfo.InvariantCulture) }, { "idleTimeoutMs", ((long)feature.IdleTimeout.TotalMilliseconds).ToString(CultureInfo.InvariantCulture) } }; if (feature.OnConnect != null) { feature.OnConnect(subscription, privateArgs); } serverEvents.Register(subscription, privateArgs); var tcs = new TaskCompletionSource <bool>(); subscription.OnDispose = _ => { try { res.EndHttpHandlerRequest(skipHeaders: true); } catch { } tcs.SetResult(true); }; return(tcs.Task); }