SampleController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;
namespace App.Controllers
{
[Throttle]
public class SampleController : ApiController
{
[HttpGet]
public async Task<IHttpActionResult>
Get() =>
await Task.FromResult(Ok(Guid.NewGuid().ToString()));
}
}
ThrottleAttribute.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;
namespace App
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class ThrottleAttribute : ActionFilterAttribute
{
private readonly HandleRequest _handleRequest;
public ThrottleAttribute()
{
this._handleRequest =
new HandleRequest();
}
public override async Task
OnActionExecutingAsync(HttpActionContext actionContext, CancellationToken cancellationToken)
{
var valid =
await this._handleRequest.IsValidRequest(actionContext.Request);
if (!valid)
{
actionContext.Response =
new HttpResponseMessage((HttpStatusCode)
429) { ReasonPhrase =
"Too Many Requests!" };
}
}
}
}
HandleRequest.cs
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Net.Http;
using System.ServiceModel.Channels;
using System.Threading.Tasks;
using System.Web;
using System.Web.Caching;
namespace App
{
public class HandleRequest
{
private string Name {
get; } =
"Client1";
private int Seconds {
get; } =
int.Parse(ConfigurationManager.AppSettings.Get(
"waitMillisecond"));
public async Task<
bool>
IsValidRequest(HttpRequestMessage requestMessage)
{
var allowExecute =
false;
await Task.Factory.StartNew(() =>
{
var key =
string.Concat(Name,
"-", GetClientIp(requestMessage));
if (HttpRuntime.Cache[key] ==
null)
{
HttpRuntime.Cache.Add(key,
true,
null,
DateTime.Now.AddMilliseconds(Seconds),
Cache.NoSlidingExpiration,
CacheItemPriority.Low,
null);
allowExecute =
true;
}
});
return allowExecute;
}
private string GetClientIp(HttpRequestMessage request)
{
if (request.Properties.ContainsKey(
"MS_HttpContext"))
{
return ((HttpContextWrapper)request.Properties[
"MS_HttpContext"]).Request.UserHostAddress;
}
if (request.Properties.ContainsKey(RemoteEndpointMessageProperty.Name))
{
RemoteEndpointMessageProperty prop;
prop = (RemoteEndpointMessageProperty)request.Properties[RemoteEndpointMessageProperty.Name];
return prop.Address;
}
return null;
}
}
}
运行结果:
1分钟内,连续请求的结果: