// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Specialized;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web.Http.Controllers;
using System.Xml.Linq;
namespace Microsoft.AspNet.WebHooks
{
///
/// Provides an implementation which supports generic WebHooks
/// containing valid JSON with no special validation logic or security requirements. This can for
/// example be used to receive WebHooks from IFTTT's Maker Channel or a Zapier WebHooks Action.
/// A sample WebHook URI is 'https://<host>/api/webhooks/incoming/genericjson/{id}?code=83699ec7c1d794c0c780e49a5c72972590571fd8'.
/// For security reasons the WebHook URI must be an https URI and contain a 'code' query parameter with the
/// same value as configured in the 'MS_WebHookReceiverSecret_GenericJson' application setting, optionally using IDs
/// to differentiate between multiple WebHooks, for example 'secret0, id1=secret1, id2=secret2'.
/// The 'code' parameter must be between 32 and 128 characters long.
/// The URI may optionally include a 'action' query parameter which will serve as the WebHook action.
///
public class SitecoreJsonWebHookReceiver : WebHookReceiver
{
internal const string RecName = "sitecorejson";
internal const string ActionQueryParameter = "action";
internal const string DefaultAction = "change";
///
/// Content type
///
public static string ContentType;
///
/// Gets the receiver name for this receiver.
///
public static string ReceiverName
{
get { return RecName; }
}
///
public override string Name
{
get { return RecName; }
}
///
public override async Task ReceiveAsync(string id, HttpRequestContext context, HttpRequestMessage request)
{
if (id == null)
{
throw new ArgumentNullException(nameof(id));
}
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
if (request == null)
{
throw new ArgumentNullException(nameof(request));
}
if (request.Method != HttpMethod.Post)
{
return CreateBadMethodResponse(request);
}
ContentType = request.Content.Headers.ContentType.MediaType.ToString();
// Ensure that we use https and have a valid code parameter
await EnsureValidCode(request, id);
// Get the action
NameValueCollection queryParameters = request.RequestUri.ParseQueryString();
string action = queryParameters[ActionQueryParameter];
if (string.IsNullOrEmpty(action))
{
action = DefaultAction;
}
JToken data=null;
XElement xmldata = null;
switch (ContentType)
{
case "application/json":
// Read the request entity body
data = await ReadAsJsonTokenAsync(request);
// Call registered handlers
return await ExecuteWebHookAsync(id, context, request, new[] { action }, data);
case "application/xml":
// Read the request entity body
xmldata = await ReadAsXmlAsync(request);
// Call registered handlers
return await ExecuteWebHookAsync(id, context, request, new[] { action }, xmldata);
default:
return CreateBadMethodResponse(request);
}
}
}
}