Created
July 8, 2012 00:05
-
-
Save davidwaterston/3068639 to your computer and use it in GitHub Desktop.
A ColdFusion function to grab geolocation details for an IP address using the free geoPlugin.net service.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<cfcomponent name="geoPlugin" output="no"> | |
<cffunction name="ipLocation" access="remote" returntype="struct" displayname="ipLocation" output="no"> | |
<!--- | |
This function takes an IP address and passes it to http://www.geoplugin.net, a free GeoLocation service that | |
returns info about where that IP address is located i.e. city, country, etc. The returned data from geoPlugin | |
is cleaned up and returned as a ColdFusion structure. | |
Where the IP address is not passed in then geoPlugin.net will use the IP of the calling page. The IP used is | |
always returned in the 'geoplugin.request' variable. | |
Written by: David Waterston (http://dvolvr.davidwaterston.com) | |
More info about this function: http://dvolvr.davidwaterston.com/2012/07/07/geolocating-ip…and-coldfusion | |
Made in Scotland. | |
---> | |
<cfargument name="ip" type="string" required="no" default=""> | |
<cfset var local = StructNew()> | |
<cftry> | |
<cfset local.ip = Trim(arguments.ip)> | |
<cfset local.url = "http://www.geoplugin.net/json.gp?ip=#local.ip#"> | |
<cfhttp result="local.ipRequest" url="#local.url#" method="get" timeout="5" throwOnError="yes"/> | |
<cfif isJSON(local.ipRequest.filecontent) EQ "No"> | |
<cfthrow message="geoPlugin response to #local.url# was not JSON format - #local.ipRequest.filecontent#"> | |
</cfif> | |
<!--- | |
All variables are returned with a "geoplugin_" prefix. | |
As we will return the response in a structure called geoplugin we can strip the prefix. | |
---> | |
<cfset local.ipRequest = Replace(local.ipRequest.filecontent,"geoplugin_","","all")> | |
<cfset local.return = StructNew()> | |
<cfset local.return["status"] = "OK"> | |
<cfset local.return["geoplugin"] = DeserializeJSON(local.ipRequest,true)> | |
<!--- To prevent values like 12 being returned as 12.0 or "12.0" we cast the relevant fields as integers ---> | |
<cfloop list="status,dmaCode,regionCode,areaCode" index="local.id"> | |
<cfif IsNumeric(local.return.geoplugin[local.id])> | |
<cfset local.return.geoplugin[local.id] = Javacast("int",local.return.geoplugin[local.id])> | |
</cfif> | |
</cfloop> | |
<!--- For consistency, we convert "null"s to empty strings ---> | |
<cfloop collection="#local.return.geoplugin#" item="local.id"> | |
<cfif local.return.geoplugin[local.id] EQ "null"> | |
<cfset local.return.geoplugin[local.id] = ""> | |
</cfif> | |
</cfloop> | |
<cfreturn local.return> | |
<cfcatch> | |
<cfset local.return = StructNew()> | |
<cfset local.return["status"] = "BAD"> | |
<cfset local.return["cfcatch"] = cfcatch> | |
<cfreturn local.return> | |
</cfcatch> | |
</cftry> | |
</cffunction> | |
</cfcomponent> |
Quite a few queries are returned without a regionName
and this throws an 'undefined' error in the collection cfloop. I've added the following after the deserialization of the JSON.
<cfif NOT structKeyExists(local.return.geoplugin,"regionName")>
<cfset local.return.geoplugin["regionName"] = "">
</cfif>
The code as it stands is very elegant and I imagine there may be a better way of doing this.
Once I sent the IP address to the function, what do I put on the calling page to check for the state?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks David! Very useful for checking where unwelcome spam originates.