You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This might help someone. I had some problems with signatures not validating correctly. MixPanel documentation now says the signature way of authenticating is deprecated. So I've made changes to make the code work again.
I've pasted my changes to MixPanelDataClient.cs, MixPanelEndpoint.cs and MixPanelClientWrapper.cs below which include:
Added Segmentation Method for my own benefit
Fixed URL encoding of query string parameters
Replace old HTTP + signature authentication code with HTTPS + Basic auth
I don't have the time or will to commit this and create a pull request but maybe someone else does.
public class MixpanelDataClient : IMixpanelData {
private readonly IHttpClient httpClient;
public string ApiKey { get; private set; }
public string ApiSecret { get; private set; }
public string Token { get; private set; }
public MixpanelDataClient(string apiKey, string apiSecret, string apiToken) {
ApiKey = apiKey;
ApiSecret = apiSecret;
Token = apiToken;
httpClient = new HttpClientWrapper(apiSecret);
}
public async Task<Stream> ExportStream(DateTime from, DateTime to, ICollection<string> events = null, string where = "", string bucket = "") {
var parameters = new NameValueCollection();
parameters.AddIfNotIsNullOrWhiteSpace("from_date", from.ToString("yyyy-MM-dd"));
parameters.AddIfNotIsNullOrWhiteSpace("to_date", to.ToString("yyyy-MM-dd"));
parameters.AddIfNotIsNullOrWhiteSpace("where", where);
var endpoint = new Endpoint().Create()
.ForMethod(MethodEnum.Export)
.WithParameters(parameters)
.Build();
this.httpClient.TimeOut = TimeSpan.FromHours(1);
var response = await this.httpClient.GetAsync(endpoint, HttpCompletionOption.ResponseHeadersRead);
if(response.IsSuccessStatusCode) {
return await response.Content.ReadAsStreamAsync();
}
return null;
}
public async Task<ExportResponse> Export(DateTime from, DateTime to, ICollection<string> events = null, string where = "", string bucket = "") {
var stream = await this.ExportStream(from, to, events, where, bucket);
var reader = new StreamReader(stream);
var exportResponse = new ExportResponse();
while(reader.Peek() > -1) {
exportResponse.Add(JsonConvert.DeserializeObject<Event>(reader.ReadLine()));
}
return exportResponse;
}
public async Task<EngageResponse> Engage(string where = "", string sessionId = "", int page = 0) {
var parameters = new NameValueCollection();
parameters.AddIfNotIsNullOrWhiteSpace("where", where);
parameters.AddIfNotIsNullOrWhiteSpace("session_id", sessionId);
parameters.AddIfNotIsNullOrWhiteSpace("page", page.ToString());
var endpoint = new Endpoint().Create()
.ForMethod(MethodEnum.Engage)
.WithParameters(parameters)
.Build();
var response = await this.httpClient.GetAsync(endpoint);
if(response.IsSuccessStatusCode) {
return await response.Content.ReadAsAsync<EngageResponse>();
}
return null;
}
public async Task<SegmentationResponse> Segmentation(string eventName, DateTime from, DateTime to, string on = null, string where = null) {
var parameters = new NameValueCollection();
parameters.AddIfNotIsNullOrWhiteSpace("event", eventName);
parameters.AddIfNotIsNullOrWhiteSpace("from_date", from.ToString("yyyy-MM-dd"));
parameters.AddIfNotIsNullOrWhiteSpace("to_date", to.ToString("yyyy-MM-dd"));
parameters.AddIfNotIsNullOrWhiteSpace("on", on);
parameters.AddIfNotIsNullOrWhiteSpace("where", where);
var endpoint = new Endpoint().Create()
.ForMethod(MethodEnum.Segmentation)
.WithParameters(parameters)
.Build();
var response = await this.httpClient.GetAsync(endpoint);
if(response.IsSuccessStatusCode) {
return await response.Content.ReadAsAsync<SegmentationResponse>();
}
string body = await response.Content.ReadAsStringAsync();
throw new ApplicationException($"MixPanel API returned HTTP status:{response.StatusCode} response: {body}");
}
}
public class HttpClientWrapper : IHttpClient {
private readonly HttpClient httpClient;
public HttpClientWrapper(string apiSecret) {
httpClient = new HttpClient();
var byteArray = Encoding.ASCII.GetBytes($"{apiSecret}:");
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
}
public async Task<HttpResponseMessage> GetAsync(string requestUri) {
return await httpClient.GetAsync(requestUri);
}
public async Task<HttpResponseMessage> GetAsync(string requestUri, HttpCompletionOption httpCompletionOption) {
return await httpClient.GetAsync(requestUri, httpCompletionOption);
}
public async Task<HttpResponseMessage> PostAsync(string requestUri, HttpContent content) {
return await httpClient.PostAsync(requestUri, content);
}
public TimeSpan TimeOut {
get { return httpClient.Timeout; }
set { httpClient.Timeout = value; }
}
}
public class Endpoint {
public string BaseEndpoint { get; private set; }
public string Method { get; private set; }
public NameValueCollection Parameters { get; private set; }
public Endpoint Create() {
return this;
}
public Endpoint ForMethod(MethodEnum method) {
this.Method = method.ToDescriptionString();
this.BaseEndpoint = "https://mixpanel.com/api/2.0/";
if(method == MethodEnum.Export) {
this.BaseEndpoint = "https://data.mixpanel.com/api/2.0/";
}
return this;
}
public Endpoint WithParameters(NameValueCollection parameters) {
this.Parameters = parameters;
return this;
}
public string Build() {
return this.ToString();
}
public override string ToString() {
var uriBuilder = new UriBuilder($"{BaseEndpoint}/{Method}"); ;
uriBuilder.Query = ToQueryString(this.Parameters);
var endpoint = uriBuilder.ToString();
return endpoint;
}
private string ToQueryString(NameValueCollection nvc) {
var array = (from key in nvc.AllKeys
from value in nvc.GetValues(key)
select string.Format("{0}={1}", WebUtility.UrlEncode(key), WebUtility.UrlEncode(value)))
.ToArray();
return string.Join("&", array);
}
}
The text was updated successfully, but these errors were encountered:
This might help someone. I had some problems with signatures not validating correctly. MixPanel documentation now says the signature way of authenticating is deprecated. So I've made changes to make the code work again.
I've pasted my changes to MixPanelDataClient.cs, MixPanelEndpoint.cs and MixPanelClientWrapper.cs below which include:
I don't have the time or will to commit this and create a pull request but maybe someone else does.
The text was updated successfully, but these errors were encountered: