So, I am writing an application for caching geocoding data when importing records. It works fine for me when I use an unsigned request, but I canβt understand what happened when I try to use my clientid firm and signature. I always get the forbidden 403.
Here is my url constructor:
private const string _googleUri = "http://maps.googleapis.com/maps/api/geocode/xml?address="; private const string _googleClientId = "XXXXXXXX"; private const string _googleSignature = "XXXXXXXXXXXXXXXXXXXXXXXX"; //RESOLVED private static String GetGeocodeUri(string address) { ASCIIEncoding encoding = new ASCIIEncoding(); string url = String.Format("{0}{1}&client={2}&sensor=false" , _googleUri , HttpUtility.UrlEncode(address) , _googleClientId); // converting key to bytes will throw an exception, need to replace '-' and '_' characters first. string usablePrivateKey = _googleSignature.Replace("-", "+").Replace("_", "/"); byte[] privateKeyBytes = Convert.FromBase64String(usablePrivateKey); Uri uri = new Uri(url); byte[] encodedPathAndQueryBytes = encoding.GetBytes( uri.LocalPath + uri.Query ); // compute the hash HMACSHA1 algorithm = new HMACSHA1(privateKeyBytes); byte[] hash = algorithm.ComputeHash(encodedPathAndQueryBytes); // convert the bytes to string and make url-safe by replacing '+' and '/' characters string signature = Convert.ToBase64String(hash).Replace("+", "-").Replace("/", "_"); // Add the signature to the existing URI. return uri.Scheme + "://" + uri.Host + uri.LocalPath + uri.Query + "&signature=" + signature; }
Here is the program:
public static AddressClass GetResponseAddress(string address) { AddressClass GoogleAddress = new AddressClass(); XmlDocument doc = new XmlDocument(); String myUri = GetGeocodeUri(address); try { doc.Load(myUri); XmlNode root = doc.DocumentElement; if (root.SelectSingleNode("/GeocodeResponse/status").InnerText == "OK") { GoogleAddress.Latitude = Double.Parse(root.SelectSingleNode("/GeocodeResponse/result/geometry/location/lat").InnerText); GoogleAddress.Longitude = Double.Parse(root.SelectSingleNode("/GeocodeResponse/result/geometry/location/lat").InnerText); } } catch (Exception ex) { Console.WriteLine("Exception <" + ex.Message + ">"); } return GoogleAddress; }
Now, my initial reaction to it does not work, is that Google should skip the domain of the abstract, because it must be registered. So I tried this with HttpWebRequest and installed the referent in my domain, but still not a cube.
//Not needed, Just an alternate method public static AddressClass GetResponseAddress(string address) { AddressClass GoogleAddress = new AddressClass(); WebClient client = new WebClient(); XmlDocument doc = new XmlDocument(); Uri myUri = new Uri(GetGeocodeUri(address)); HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(myUri); myRequest.Referer = "http://www.myDomain.com/"; //I've even tried pretending to be Chrome //myRequest.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.75 Safari/535.7"; try { doc.Load(myRequest.GetResponse().GetResponseStream()); XmlNode root = doc.DocumentElement; if (root.SelectSingleNode("/GeocodeResponse/status").InnerText == "OK") { GoogleAddress.Latitude = Double.Parse(root.SelectSingleNode("/GeocodeResponse/result/geometry/location/lat").InnerText); GoogleAddress.Longitude = Double.Parse(root.SelectSingleNode("/GeocodeResponse/result/geometry/location/lat").InnerText); } } catch (Exception ex) { Console.WriteLine("Exception <" + ex.Message + ">"); } return GoogleAddress; }
Any help would be greatly appreciated.
source share