internal async Task <HttpResponseMessage> ProcessAsync(HttpRequestMessage req, string functionName, Func <JArray, string, CancellationToken, Task <HttpResponseMessage> > eventsFunc, CancellationToken cancellationToken) { IEnumerable <string> eventTypeHeaders = null; string eventTypeHeader = null; if (req.Headers.TryGetValues("aeg-event-type", out eventTypeHeaders)) { eventTypeHeader = eventTypeHeaders.First(); } if (String.Equals(eventTypeHeader, "SubscriptionValidation", StringComparison.OrdinalIgnoreCase)) { string jsonArray = await req.Content.ReadAsStringAsync().ConfigureAwait(false); SubscriptionValidationEvent validationEvent = null; List <JObject> events = JsonConvert.DeserializeObject <List <JObject> >(jsonArray); // TODO remove unnecessary serialization validationEvent = ((JObject)events[0]["data"]).ToObject <SubscriptionValidationEvent>(); SubscriptionValidationResponse validationResponse = new SubscriptionValidationResponse { ValidationResponse = validationEvent.ValidationCode }; var returnMessage = new HttpResponseMessage(HttpStatusCode.OK); returnMessage.Content = new StringContent(JsonConvert.SerializeObject(validationResponse)); _logger.LogInformation($"perform handshake with eventGrid for function: {functionName}"); return(returnMessage); } else if (String.Equals(eventTypeHeader, "Notification", StringComparison.OrdinalIgnoreCase)) { JArray events = null; string requestContent = await req.Content.ReadAsStringAsync().ConfigureAwait(false); var token = JToken.Parse(requestContent); if (token.Type == JTokenType.Array) { // eventgrid schema events = (JArray)token; } else if (token.Type == JTokenType.Object) { // cloudevent schema events = new JArray { token }; } return(await eventsFunc(events, functionName, cancellationToken).ConfigureAwait(false)); } else if (String.Equals(eventTypeHeader, "Unsubscribe", StringComparison.OrdinalIgnoreCase)) { // TODO disable function? return(new HttpResponseMessage(HttpStatusCode.Accepted)); } return(new HttpResponseMessage(HttpStatusCode.BadRequest)); }
private async Task <HttpResponseMessage> ProcessAsync(HttpRequestMessage req) { // webjobs.script uses req.GetQueryNameValuePairs(); // which requires webapi.core...but this does not work for .netframework2.0 // TODO change this once webjobs.script is migrated var functionName = HttpUtility.ParseQueryString(req.RequestUri.Query)["functionName"]; if (String.IsNullOrEmpty(functionName) || !_listeners.ContainsKey(functionName)) { _tracer.Trace(new TraceEvent(System.Diagnostics.TraceLevel.Info, $"cannot find function: '{functionName}', available function names: [{string.Join(", ", _listeners.Keys.ToArray())}]")); return(new HttpResponseMessage(HttpStatusCode.NotFound)); } IEnumerable <string> eventTypeHeaders = null; string eventTypeHeader = null; if (req.Headers.TryGetValues("aeg-event-type", out eventTypeHeaders)) { eventTypeHeader = eventTypeHeaders.First(); } if (String.Equals(eventTypeHeader, "SubscriptionValidation", StringComparison.OrdinalIgnoreCase)) { string jsonArray = await req.Content.ReadAsStringAsync(); SubscriptionValidationEvent validationEvent = null; List <JObject> events = JsonConvert.DeserializeObject <List <JObject> >(jsonArray); // TODO remove unnecessary serialization validationEvent = ((JObject)events[0]["data"]).ToObject <SubscriptionValidationEvent>(); SubscriptionValidationResponse validationResponse = new SubscriptionValidationResponse { ValidationResponse = validationEvent.ValidationCode }; var returnMessage = new HttpResponseMessage(HttpStatusCode.OK); returnMessage.Content = new StringContent(JsonConvert.SerializeObject(validationResponse)); _tracer.Trace(new TraceEvent(System.Diagnostics.TraceLevel.Info, $"perform handshake with eventGrid for endpoint: {req.RequestUri}")); return(returnMessage); } else if (String.Equals(eventTypeHeader, "Notification", StringComparison.OrdinalIgnoreCase)) { string jsonArray = await req.Content.ReadAsStringAsync(); List <JObject> events = JsonConvert.DeserializeObject <List <JObject> >(jsonArray); foreach (var ev in events) { TriggeredFunctionData triggerData = new TriggeredFunctionData { TriggerValue = ev }; await _listeners[functionName].Executor.TryExecuteAsync(triggerData, CancellationToken.None); } return(new HttpResponseMessage(HttpStatusCode.Accepted)); } else if (String.Equals(eventTypeHeader, "Unsubscribe", StringComparison.OrdinalIgnoreCase)) { // TODO disable function? return(new HttpResponseMessage(HttpStatusCode.Accepted)); } return(new HttpResponseMessage(HttpStatusCode.BadRequest)); }
private async Task <HttpResponseMessage> ProcessAsync(HttpRequestMessage req) { // webjobs.script uses req.GetQueryNameValuePairs(); // which requires webapi.core...but this does not work for .netframework2.0 // TODO change this once webjobs.script is migrated var functionName = HttpUtility.ParseQueryString(req.RequestUri.Query)["functionName"]; if (String.IsNullOrEmpty(functionName) || !_listeners.ContainsKey(functionName)) { _tracer.Trace(new TraceEvent(System.Diagnostics.TraceLevel.Info, $"cannot find function: '{functionName}', available function names: [{string.Join(", ", _listeners.Keys.ToArray())}]")); return(new HttpResponseMessage(HttpStatusCode.NotFound) { Content = new StringContent($"cannot find function: '{functionName}'") }); } IEnumerable <string> eventTypeHeaders = null; string eventTypeHeader = null; if (req.Headers.TryGetValues("aeg-event-type", out eventTypeHeaders)) { eventTypeHeader = eventTypeHeaders.First(); } if (String.Equals(eventTypeHeader, "SubscriptionValidation", StringComparison.OrdinalIgnoreCase)) { string jsonArray = await req.Content.ReadAsStringAsync(); SubscriptionValidationEvent validationEvent = null; List <JObject> events = JsonConvert.DeserializeObject <List <JObject> >(jsonArray); // TODO remove unnecessary serialization validationEvent = ((JObject)events[0]["data"]).ToObject <SubscriptionValidationEvent>(); SubscriptionValidationResponse validationResponse = new SubscriptionValidationResponse { ValidationResponse = validationEvent.ValidationCode }; var returnMessage = new HttpResponseMessage(HttpStatusCode.OK); returnMessage.Content = new StringContent(JsonConvert.SerializeObject(validationResponse)); _tracer.Trace(new TraceEvent(System.Diagnostics.TraceLevel.Info, $"perform handshake with eventGrid for function: {functionName}")); return(returnMessage); } else if (String.Equals(eventTypeHeader, "Notification", StringComparison.OrdinalIgnoreCase)) { JArray events = null; string requestContent = await req.Content.ReadAsStringAsync(); var token = JToken.Parse(requestContent); if (token.Type == JTokenType.Array) { // eventgrid schema events = (JArray)token; } else if (token.Type == JTokenType.Object) { // cloudevent schema events = new JArray { token }; } List <Task <FunctionResult> > executions = new List <Task <FunctionResult> >(); foreach (var ev in events) { // assume each event is a JObject TriggeredFunctionData triggerData = new TriggeredFunctionData { TriggerValue = ev }; executions.Add(_listeners[functionName].Executor.TryExecuteAsync(triggerData, CancellationToken.None)); } await Task.WhenAll(executions); // FIXME without internal queuing, we are going to process all events in parallel // and return 500 if there's at least one failure...which will cause EventGrid to resend the entire payload foreach (var execution in executions) { if (!execution.Result.Succeeded) { return(new HttpResponseMessage(HttpStatusCode.InternalServerError) { Content = new StringContent(execution.Result.Exception.Message) }); } } return(new HttpResponseMessage(HttpStatusCode.Accepted)); } else if (String.Equals(eventTypeHeader, "Unsubscribe", StringComparison.OrdinalIgnoreCase)) { // TODO disable function? return(new HttpResponseMessage(HttpStatusCode.Accepted)); } return(new HttpResponseMessage(HttpStatusCode.BadRequest)); }