Skip to content

Instantly share code, notes, and snippets.

@chester89
Created August 10, 2016 09:34
Show Gist options
  • Save chester89/897ebd84b1bece4051a4453e3fdf780a to your computer and use it in GitHub Desktop.
Save chester89/897ebd84b1bece4051a4453e3fdf780a to your computer and use it in GitHub Desktop.
OOP stuff
public abstract class RequestBuilderBase
{
protected readonly string _clientKey;
protected readonly UsageMode _mode;
protected readonly string _clientId;
protected readonly string _cryptoKey;
protected string _domain = "https://maps.googleapis.com";
protected const string _apiPath = "/maps/api/geocode/json?";
/// <param name="domain"></param>
/// <param name="isProtected">only needed so that signature doesnt collide with another ctor</param>
protected RequestBuilderBase(string domain, bool isProtected = true)
{
_domain = domain;
}
/// <summary>
/// Dont use a Google API key and use default anonymous access.
/// NOTE: Throttling may apply.
/// </summary>
public RequestBuilderBase()
{
_mode = UsageMode.Free;
}
/// <summary>
/// Initialize GeocodeClient with your Google API key to utilize it in the requests to Google and bypass the default annonymous throttling.
/// </summary>
/// <param name="apiKey">Google Maps API Key</param>
public RequestBuilderBase(string apiKey)
{
_clientKey = apiKey;
_mode = UsageMode.ClientKey;
}
/// <summary>
/// Initialize GeocodeClient with your Google API key to utilize it in the requests to Google and bypass the default annonymous throttling.
/// </summary>
/// <param name="clientId">The client ID. Applicable when using Maps API for Work.</param>
/// <param name="cryptoKey">The base64 encoded crypto key. Applicable when using Maps API for Work.</param>
/// <remarks>
/// See - https://developers.google.com/maps/documentation/business/webservices/#client_id
/// </remarks>
public RequestBuilderBase(string clientId, string cryptoKey)
{
_clientId = clientId;
_cryptoKey = cryptoKey;
_mode = UsageMode.ApiForWork;
}
public abstract string BuildUrl(ComponentFilter filter, string region);
public abstract string BuildUrl(ComponentFilter filter, string region, string address, string language);
}
public class DefaultRequestBuilder: RequestBuilderBase
{
protected DefaultRequestBuilder(string domain, bool isProtected = true) : base(domain, isProtected)
{
}
public DefaultRequestBuilder()
{
}
public DefaultRequestBuilder(string apiKey): base(apiKey)
{
}
public DefaultRequestBuilder(string clientId, string cryptoKey): base(clientId, cryptoKey)
{
}
public override string BuildUrl(ComponentFilter filter, string region)
{
if (filter == null)
throw new ArgumentNullException("filter");
var addressPortion = BuildAddressPortion(filter, region);
var authPortion = BuildAuthPortion(addressPortion);
return string.Format("{0}{1}{2}{3}", _domain, _apiPath, addressPortion, authPortion);
}
public override string BuildUrl(ComponentFilter filter, string region, string address, string language)
{
if (string.IsNullOrWhiteSpace(address)) throw new ArgumentNullException("address");
var addressPortion = BuildAddressPortion(address, region, language, filter);
var authPortion = BuildAuthPortion(addressPortion);
return string.Format("{0}{1}{2}{3}", _domain, _apiPath, addressPortion, authPortion);
}
private string BuildAuthPortion(string addressPortion)
{
switch (_mode)
{
case UsageMode.Free:
return string.Empty;
case UsageMode.ClientKey:
return string.Format("&key={0}", _clientKey);
case UsageMode.ApiForWork:
return BuildApiForWorkUrl(addressPortion);
default:
return string.Empty;
}
}
private string BuildAddressPortion(ComponentFilter filter, string region)
{
var filterString = filter.ToUrlParameters();
if (string.IsNullOrWhiteSpace(filterString))
throw new ArgumentException("Component filter doesn't contain any component", "filter");
var addressPortion = string.Format("components={0}", filterString);
if (!string.IsNullOrWhiteSpace(region))
{
addressPortion += string.Format("&region={0}", Uri.EscapeDataString(region));
}
return addressPortion;
}
private string BuildAddressPortion(string address, string region, string language, ComponentFilter filter)
{
var addressPortion = string.Format("address={0}", Uri.EscapeDataString(address));
if (!string.IsNullOrWhiteSpace(region))
{
addressPortion += string.Format("&region={0}", Uri.EscapeDataString(region));
}
if (!string.IsNullOrWhiteSpace(language))
{
addressPortion += string.Format("&language={0}", Uri.EscapeDataString(language));
}
if (filter != null)
{
var filterString = filter.ToUrlParameters();
if (!string.IsNullOrWhiteSpace(filterString))
{
addressPortion += string.Format("&components={0}", filterString);
}
}
return addressPortion;
}
private string BuildApiForWorkUrl(string addressPortion)
{
var cryptoBytes = Convert.FromBase64String(_cryptoKey.Replace("-", "+").Replace("_", "/"));
var hashThis = string.Format("{0}{1}&client={2}", _apiPath, addressPortion, _clientId);
var hashThisBytes = Encoding.ASCII.GetBytes(hashThis);
using (var sha1 = new HMACSHA1(cryptoBytes))
{
var hash = sha1.ComputeHash(hashThisBytes);
var signature = Convert.ToBase64String(hash).Replace("+", "-").Replace("/", "_");
return string.Format("&client={0}&signature={1}", _clientId, signature);
}
}
}
public class NginxProxyRequestBuilder : DefaultRequestBuilder
{
public NginxProxyRequestBuilder(string domain, bool isProtected = true) : base(domain, isProtected)
{
}
public NginxProxyRequestBuilder(string apiKey) : base(apiKey)
{
}
public NginxProxyRequestBuilder(string clientId, string cryptoKey) : base(clientId, cryptoKey)
{
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment