Skip to content

Make Application.cfc full script in this example #307

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 64 additions & 58 deletions examples/api_rateLimited/Application.cfc
Original file line number Diff line number Diff line change
@@ -1,72 +1,78 @@
<cfcomponent extends="taffy.core.api">
<cfscript>
component extends="taffy.core.api" {
this.name = "rate_limiting_example";

this.name = "rate_limiting_example";
function onApplicationStart(){
application.accessLog = queryNew('apiKey,accessTime','varchar,time');
application.accessLimit = 100; //requests
application.accessPeriod = 60; //seconds

function onApplicationStart(){
application.accessLog = queryNew('apiKey,accessTime','varchar,time');
application.accessLimit = 100; //requests
application.accessPeriod = 60; //seconds
return super.onApplicationStart();
}

return super.onApplicationStart();
function onTaffyRequest(verb, cfc, requestArguments, mimeExt){
var usage = 0;
//require some api key
if (!structKeyExists(requestArguments, "apiKey")){
return noData().withStatus(401, "API Key Required");
}

function onTaffyRequest(verb, cfc, requestArguments, mimeExt){
var usage = 0;

//require some api key
if (!structKeyExists(requestArguments, "apiKey")){
return noData().withStatus(401, "API Key Required");
}

//check usage
usage = getAccessRate(requestArguments.apiKey);
if (usage lte application.accessLimit){
logAccess(requestArguments.apiKey);
return true;
}else{
return noData().withStatus(420, "Enhance your calm");
}

//check usage
usage = getAccessRate(requestArguments.apiKey);
if (usage lte application.accessLimit){
logAccess(requestArguments.apiKey);
return true;
}else{
return noData().withStatus(420, "Enhance your calm");
}
</cfscript>

<cffunction name="getAccessRate" access="private" output="false">
<cfargument name="apiKey" required="true" />
<cfset var local = structNew() />
<!--- now get matches for the current api key --->
<cfquery name="local.accessLookup" dbtype="query">
return true;
}


private function getAccessRate(apiKey){
var accessLookup = queryExecute("
select accessTime
from application.accessLog
where apiKey = <cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.apiKey#" />
and accessTime > <cfqueryparam cfsqltype="cf_sql_timestamp" value="#dateAdd("s",(-1 * application.accessPeriod),now())#" />
</cfquery>
<!--- if access log is getting long, do some cleanup --->
<cfif local.accessLookup.recordCount gt application.accessLimit>
<cfset pruneAccessLog() />
</cfif>
<cfreturn local.accessLookup.recordCount />
</cffunction>
where apiKey = :k
and accessTime > :t
",
{
t : dateAdd("s",(-1 * application.accessPeriod),now()),
k : arguments.apiKey
},
{
dbtype : "query"
});

<cffunction name="logAccess" access="private" output="true">
<cfargument name="apiKey" required="true" type="string" />
<cfset var qLog = '' />
<cflock timeout="10" type="readonly" name="logging">
<cfset queryAddRow(application.accessLog)/>
<cfset querySetCell(application.accessLog, "accessTime", now()) />
<cfset querySetCell(application.accessLog, "apiKey", arguments.apiKey) />
</cflock>
</cffunction>
if( local.accessLookup.recordCount gt application.accessLimit ){
pruneAccessLog();
}
return local.accessLookup.recordCount;
}

private function logAccess(apiKey){
lock timeout="10" type="readonly" name="logging"{
queryAddRow (application.accessLog);
querySetCell(application.accessLog, "accessTime", now());
querySetCell(application.accessLog, "apiKey", arguments.apiKey);
}
}

<cffunction name="pruneAccessLog" access="private" output="false">
<cflock timeout="10" type="readonly" name="logging">
<cfquery name="application.accessLog" dbtype="query">
delete
private function pruneAccessLog(){
lock timeout="10" type="readonly" name="logging"{
var rest = queryExecute("
select *
from application.accessLog
where accessTime < <cfqueryparam cfsqltype="cf_sql_timestamp" value="#dateAdd("s",(-1 * application.accessPeriod),now())#" />
</cfquery>
</cflock>
</cffunction>
where accessTime > :t
",
{
t : dateAdd("s",(-1 * application.accessPeriod),now())
},
{
dbtype : "query"
});
application.accessLog = rest;
}
}

</cfcomponent>
}