public async ValueTask <IActionResult> Post(CancellationToken token) { string body; using (var reader = new StreamReader(Request.Body)) { body = await reader.ReadToEndAsync(); } var headers = string.Join('\n', Request.Headers.Select(x => $"{x.Key}: {x.Value}")); var eventLog = await _eventLogRepository.CreateFromPayloadAsync(body, headers, token); if (!string.IsNullOrEmpty(_secrets.WebHookSecret)) { if (!Request.Headers.ContainsKey("X-Hub-Signature")) { eventLog.Error("Signature is not provided. X-Hub-Signature header is missing."); await _eventLogRepository.UpdateAsync(eventLog); _log.LogError("Signature is not provided. X-Hub-Signature header is missing."); return(BadRequest("Please sign payload. X-Hub-Signature header is missing.")); } if (!IsValidSignature(Request.Headers["X-Hub-Signature"], body)) { eventLog.Error("Invalid signature."); await _eventLogRepository.UpdateAsync(eventLog); _log.LogError("Invalid signature"); return(BadRequest("Invalid signature")); } } var payload = DeserializePayload(body); if (payload?.Ref == null) { eventLog.Error("Unsupported payload. Ref property is empty."); await _eventLogRepository.UpdateAsync(eventLog); return(BadRequest("Unsupported payload. Only push events are supported for now.")); } var result = await _pushEventProcessor.Process(eventLog.Id, payload, token); if (result.Success) { return(Ok("Rule matched. Work queued")); } eventLog.Succeeded = false; eventLog.StatusMessage = "No matching rule found"; await _eventLogRepository.UpdateAsync(eventLog); _log.LogInformation("No matching rule found"); return(Ok("No matching rule found")); }