public static async System.Threading.Tasks.Task ExtractResultAsync(ServiceResponse response) { switch (response.Request.response.type) { case "json": if (response.Request.response.jsonPath == null) // json routine but no jsonPath specified. just ignore. { return; } Settings.Request request = response.Request; if (response.ResponseJToken == null || string.IsNullOrEmpty(response.ResponseJToken.ToString())) { response.ResponseResult = request.response.missingResponse; if (Options.options.debugLevel >= 3) { Log.WriteLine(response.ResponseResult); } } else { // not sure how to handle array result //response.ResponseResult = response.ResponseJToken.SelectTokens(service.response.jsonPath).ToString(); // jq.net doesn't seem to be supported. I don't know how to instantiate it as there's no constructor. I haven't found a substitute. IEnumerable <Newtonsoft.Json.Linq.JToken> jtoks = response.ResponseJToken.SelectTokens(request.response.jsonPath); response.ResponseResult = string.Empty; foreach (Newtonsoft.Json.Linq.JToken jtok in jtoks) { response.ResponseResult += ", " + jtok.ToString(); } if (response.ResponseResult.Length > 0) { response.ResponseResult = response.ResponseResult.Substring(2); } if (Options.options.debugLevel >= 3) { Log.WriteLine(response.ResponseJToken.Path + ": " + response.ResponseResult); } } break; case "xml": // not implemented/debugged response.ResponseXml.LoadXml(response.ResponseResult); response.ResponseXmlNodeList = response.ResponseXml.SelectNodes(response.Request.response.xpath); response.ResponseXmlFormatted = response.ResponseXmlNodeList.ToString(); // must be wrong break; default: break; } }
private static List <Tuple <string, string> > MakeHeaders(Settings.Request request) { List <Tuple <string, string> > headers = new List <Tuple <string, string> >(); if (request == null || request.headers == null) { return(headers); } foreach (Settings.Header h in request.headers) { // TODO: need to expand request headers to include any header. Use Value instead of "Generic" or concrete name (Accept, ContentType) switch (h.Name) { case "BearerAuthentication": AccessTokenInfo accessTokenInfo = ImageAuth.PerformAuthenticationAsync(request, h).Result; // TODO: make this method async so don't have to do Wait? headers.Add(new Tuple <string, string>("Authorization", "Bearer " + accessTokenInfo.access_token)); break; case "BasicAuthentication": string userpass = Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(string.Format("{0}:{1}", h.BasicAuthentication.username, h.BasicAuthentication.password).Replace('+', '-').Replace('/', '_'))); headers.Add(new Tuple <string, string>("Authorization", "Basic " + userpass)); break; case "HoundifyAuthentication": // will be passed in but must skip, don't let default break; case "OcpApimSubscriptionKey": headers.Add(new Tuple <string, string>("Ocp-Apim-Subscription-Key", h.OcpApimSubscriptionKey)); // needs rewrite. see above. break; default: if (h.Generic == null) { throw new Exception("Header: Generic is null"); } headers.Add(new Tuple <string, string>(h.Name, h.Generic)); break; } } return(headers); }
private static async System.Threading.Tasks.Task GetAsync(ServiceResponse response, Uri uri, List <Tuple <string, string> > UriSubstitutes, List <Tuple <string, string> > headers, List <Tuple <string, string> > postDataSubstitutes, string text, System.Collections.Generic.Dictionary <string, string> apiArgs, int maxResponseLength = 10000000) { Settings.Request request = response.Request; bool binaryResponse = request.response.type == "binary"; if (uri == null) { uri = MakeUri(request, apiArgs, UriSubstitutes, text); } if (headers == null) { headers = MakeHeaders(request); } List <string> texts = MakePostDataSubstitutes(request, text, null, apiArgs, postDataSubstitutes); if (texts.Count != 1) { throw new Exception("multipart GET not allowed"); } await MakeGetCurl(uri, headers, request.response.jq, binaryResponse); #if WINDOWS_UWP ServiceResponse response; if (Options.options.Services.APIs.PreferSystemNet) { await SystemNetAsync("GET", uri, headers, new System.Net.Http.ByteArrayContent(requestContent), binaryResponse, maxResponseLength); } else { await WindowsWebAsync("GET", new Uri(requestUri), audioBytes, sampleRate, contentType, headerValue); } #else await SystemNetAsync(response, "GET", uri, headers, null, binaryResponse, maxResponseLength); #endif response.FileName = "curl-" + httpCallCount; }
private static async System.Threading.Tasks.Task PostAsync(ServiceResponse response, Uri uri, List <Tuple <string, string> > UriSubstitutes, List <Tuple <string, string> > headers, List <Tuple <string, string> > postDataSubstitutes, string text, System.Collections.Generic.Dictionary <string, string> apiArgs, int maxResponseLength = 10000000) { Settings.Request request = response.Request; bool binaryResponse = request.response.type == "binary"; if (uri == null) { uri = MakeUri(request, apiArgs, UriSubstitutes, text); } if (headers == null) { headers = MakeHeaders(request); } List <string> data = MakePostDataSubstitutes(request, text, null, apiArgs, postDataSubstitutes); if (data.Count == 1 && !isMultipart(headers)) { await MakePostCurl(uri, headers, data, request == null?null : request.response.jq, binaryResponse); System.Net.Http.HttpContent requestContent = new System.Net.Http.StringContent(data[0]); await SystemNetAsync(response, "POST", uri, headers, requestContent, binaryResponse, maxResponseLength); response.FileName = "curl-" + httpCallCount; return; } else { #if true // MicrosoftCognitiveInsightService can use multipart? See Post Byte[] overload above for helpful details. throw new Exception("PostAsync: multipart/form-data not implemented. Doesn't seem to work with System.Net.Http"); #else List <KeyValuePair <string, string> > kvps = new List <KeyValuePair <string, string> >(); foreach (string s in data) { kvps.Add(new KeyValuePair <string, string>(s.Substring(0, s.IndexOf("=")), s.Substring(s.IndexOf("=") + 1))); } await MakePostMultiPartCurl(uri, headers, kvps, request.response.jq, binaryResponse); List <KeyValuePair <string, string> > newkvps = new List <KeyValuePair <string, string> >(); foreach (KeyValuePair <string, string> kvp in kvps) { string s = kvp.Value; if (kvp.Value[0] == '@') { byte[] bytes = System.IO.File.ReadAllBytes(kvp.Value.Substring(1)); s = Convert.ToBase64String(bytes); } newkvps.Add(new KeyValuePair <string, string>(kvp.Key, s)); } System.Net.Http.MultipartFormDataContent multiPartRequestContent = new System.Net.Http.MultipartFormDataContent(); multiPartRequestContent.Add(new System.Net.Http.FormUrlEncodedContent(newkvps)); await SystemNetAsync(response, "POST", uri, headers, multiPartRequestContent, binaryResponse, maxResponseLength); response.FileName = "curl-" + httpCallCount; #endif } #if WINDOWS_UWP // major bit rot. Multi-part not implemented. if (Options.options.Services.APIs.PreferSystemNet) { response = await SystemNetAsync("POST", uri, headers, new System.Net.Http.ByteArrayContent(requestContent), binaryResponse, maxResponseLength); } else { response = await WindowsWebAsync("POST", new Uri(requestUri), audioBytes, sampleRate, contentType, headerValue); } #else { response = await SystemNetAsync("POST", uri, headers, requestContent, binaryResponse, maxResponseLength); } response.FileName = "curl-" + httpCallCount; return(response); #endif }
private static async System.Threading.Tasks.Task PostAsync(ServiceResponse response, Uri uri, List <Tuple <string, string> > UriSubstitutes, List <Tuple <string, string> > headers, List <Tuple <string, string> > postDataSubstitutes, byte[] bytes, System.Collections.Generic.Dictionary <string, string> apiArgs, int maxResponseLength = 10000000) { Settings.Request request = response.Request; bool binaryResponse = request.response.type == "binary"; string fileName = null; if (apiArgs.ContainsKey("fileName")) { fileName = apiArgs["fileName"]; } if (uri == null) { uri = MakeUri(request, apiArgs, UriSubstitutes); } if (headers == null) { headers = MakeHeaders(request); } List <string> texts = MakePostDataSubstitutes(request, null, bytes, apiArgs, postDataSubstitutes); System.Net.Http.HttpContent requestContent; if (texts == null) { await MakePostCurl(uri, headers, bytes, request.response.jq, binaryResponse); requestContent = new System.Net.Http.ByteArrayContent(bytes); } else { if (texts.Count == 1 && !isMultipart(headers)) { await MakePostCurl(uri, headers, texts, request.response.jq, binaryResponse); if (texts[0] == null) // Houndify text intent { requestContent = new System.Net.Http.ByteArrayContent(bytes); } else { requestContent = new System.Net.Http.StringContent(texts[0]); } await SystemNetAsync(response, "POST", uri, headers, requestContent, binaryResponse, maxResponseLength); return; } else { List <KeyValuePair <string, string> > lkvp = new List <KeyValuePair <string, string> >(); foreach (string s in texts) { lkvp.Add(new KeyValuePair <string, string>(s.Substring(0, s.IndexOf("=")), s.Substring(s.IndexOf("=") + 1))); } await MakePostMultiPartCurl(uri, headers, lkvp, request.response.jq, binaryResponse); System.Net.Http.MultipartFormDataContent multiPartRequestContent = new System.Net.Http.MultipartFormDataContent(); foreach (KeyValuePair <string, string> kvp in lkvp) { System.Net.Http.HttpContent ht; switch (kvp.Key) { case "file": ht = new System.Net.Http.ByteArrayContent(bytes); ht.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream"); // optional for HPE Haven? multiPartRequestContent.Add(ht, "\"file\"", "\"" + fileName + "\""); break; default: ht = new System.Net.Http.StringContent(kvp.Value); ht.Headers.ContentType = null; multiPartRequestContent.Add(ht, '"' + kvp.Key + '"'); break; } } await SystemNetAsync(response, "POST", uri, headers, multiPartRequestContent, binaryResponse, maxResponseLength); response.FileName = "curl-" + httpCallCount; return; } } #if WINDOWS_UWP if (Options.options.Services.APIs.PreferSystemNet) { await SystemNetAsync("POST", uri, headers, new System.Net.Http.ByteArrayContent(requestContent), binaryResponse, maxResponseLength); } else { await WindowsWebAsync("POST", new Uri(requestUri), audioBytes, sampleRate, contentType, headerValue); } #else await SystemNetAsync(response, "POST", uri, headers, requestContent, binaryResponse, maxResponseLength); #endif response.FileName = "curl-" + httpCallCount; }
private static List <string> MakePostDataSubstitutes(Settings.Request request, string text, byte[] bytes, System.Collections.Generic.Dictionary <string, string> apiArgs, List <Tuple <string, string> > postDataSubstitutes) { if (request == null || request.data == null || request.data.type == null) // some POSTs have no data { return new List <string> { text } } ; if (text != null && bytes != null) { throw new Exception("MakePostDataSubstitutes: Both text and bytes are not null"); } string data = text; if (request.data.value != null) { data = request.data.value; } if (postDataSubstitutes != null) { foreach (Tuple <string, string> r in postDataSubstitutes) { data = data.Replace(r.Item1, r.Item2); } } string fileName = null; if (apiArgs.ContainsKey("fileName")) { fileName = apiArgs["fileName"]; } switch (request.data.type) { case "ascii": return(new List <string> { data }); case "base64": // TODO: use Helpers.stringToDictionary() if (data.Contains("=")) // TODO: use text or data? { List <string> base64content = new List <string>(); foreach (string multicontent in data.Split('&')) { string[] namecontent = multicontent.Split('='); if (namecontent.Length != 2) { throw new FormatException(); } base64content.Add(namecontent[0] + "=" + namecontent[1].Replace("{text}", Convert.ToBase64String(bytes))); } return(base64content); } else { return(new List <string> { data.Replace("{text}", Convert.ToBase64String(bytes)) }); } case "binary": return(null); case "json": // TODO: pass list of substitutes instead of hard coding? // TODO: issue with replacing "'" with "\\'". Seems to work when json properties are delimited with single-quotes but not with double-quotes. if (data.Contains("{base64}") ^ bytes != null) { throw new Exception("json: bytes ^ {base64} mismatch"); // can occur if string/url argument is passed to binary data API } if ((data.Contains("{text}") || data.Contains("{url}")) ^ text != null) // todo: remove when url is implemented { throw new Exception("json: text ^ {text} mismatch"); } // pass Uri here so request use Url instead of text //if (data.Contains("{url}") ^ text != null) //throw new Exception("json: text ^ {url} mismatch"); if (bytes != null) { return new List <string> { data.Replace("{guid}", Guid.NewGuid().ToString()).Replace("{base64}", Convert.ToBase64String(bytes)) } } ; else if (text != null) { return new List <string> { data.Replace("{guid}", Guid.NewGuid().ToString()).Replace("{url}", text).Replace("{text}", text.Replace("\"", "\\\"")) } } ; // bing sentiment uses guid. Replace '"' with '\"' else { throw new Exception("json: expecting bytes or text"); } case "multipart": // TODO: use Helpers.stringToDictionary() if (!data.Contains("=")) // && isMultipart(headers)? { throw new Exception("multipart is missing ="); } List <string> multipartcontent = new List <string>(); foreach (string multicontent in data.Split('&')) { string[] namecontent = multicontent.Split('='); if (namecontent.Length != 2) { throw new FormatException(); } if (fileName != null) { multipartcontent.Add(namecontent[0] + "=" + namecontent[1].Replace("{text}", fileName)); // hpe haven ocr } else if (bytes != null) { multipartcontent.Add(namecontent[0] + "=" + namecontent[1].Replace("{text}", Convert.ToBase64String(bytes))); // bing spell, Microsoft Detect } else if (text != null) { multipartcontent.Add(namecontent[0] + "=" + namecontent[1].Replace("{text}", text)); // bing spell, Microsoft Detect } } return(multipartcontent); case "raw": return(new List <string> { data }); case "string": return(new List <string> { data }); case "urlencode": // TODO: use Helpers.stringToDictionary() if (text == null) { throw new Exception("urlencode: expecting text"); } if (data.Contains("=")) // && isMultipart(headers)? { List <string> urlencodecontent = new List <string>(); foreach (string multicontent in data.Split('&')) { string[] namecontent = multicontent.Split('='); if (namecontent.Length != 2) { throw new FormatException(); } urlencodecontent.Add(namecontent[0] + "=" + (namecontent[1][0] == '@' ? namecontent[1] : System.Web.HttpUtility.UrlEncode(namecontent[1].Replace("{text}", text)))); } return(urlencodecontent); } else { return(new List <string> { System.Web.HttpUtility.UrlEncode(data) }); } case "xml": // TODO: pass list of substitutes instead of hard coding? if (bytes == null) { return new List <string> { data.Replace("{guid}", Guid.NewGuid().ToString()).Replace("{text}", text) } } ; // bing sentiment uses guid else { return new List <string> { data.Replace("{guid}", Guid.NewGuid().ToString()).Replace("{text}", Convert.ToBase64String(bytes)) } }; // bing sentiment uses guid default: throw new MissingFieldException(); } }
public static Uri MakeUri(Settings.Request request, Dictionary <string, string> apiArgs, List <Tuple <string, string> > uriSubstitutes = null, string text = null) { UriBuilder ub = new UriBuilder(); string scheme = request.uri.scheme; string host = request.uri.host; string path = request.uri.path; string query = request.uri.query; if (apiArgs != null) { foreach (KeyValuePair <string, string> r in apiArgs) { // so far only query needs substitutes string k = "{" + r.Key + "}"; scheme = scheme.Replace(k, r.Value); host = host.Replace(k, r.Value); path = path.Replace(k, r.Value); if (query == null) { query = string.Empty; } else { query = query.Replace(k, r.Value); } } } if (uriSubstitutes == null) { uriSubstitutes = new System.Collections.Generic.List <Tuple <string, string> >() { new Tuple <string, string>("{guid}", Guid.NewGuid().ToString()), // Microsoft SpeechToText new Tuple <string, string>("{locale}", Options.options.locale.language) // Microsoft SpeechToText }; if (text != null) { uriSubstitutes.Add(new Tuple <string, string>("{text}", text)); } } if (uriSubstitutes != null) { foreach (Tuple <string, string> r in uriSubstitutes) { // so far only query needs substitutes scheme = scheme.Replace(r.Item1, r.Item2); host = host.Replace(r.Item1, r.Item2); path = path.Replace(r.Item1, r.Item2); if (query == null) { query = string.Empty; } else { query = query.Replace(r.Item1, r.Item2); } } } ub.Scheme = scheme; ub.Host = host; ub.Path = path; ub.Query = query; ub.Query = query; return(ub.Uri); }
public async System.Threading.Tasks.Task <AccessTokenInfo> PerformAuthenticationAsync(Settings.Request request, Settings.Header h) { Settings.BearerAuthentication bearer = h.BearerAuthentication; if (request == null || h == null) { throw new Exception("request/h is null"); } if (h.OcpApimSubscriptionKey != null) // ClarifAi, OcpApimSubscriptionKey { Settings.BearerAuthentication BearerAuth = h.BearerAuthentication; Uri accessUri = new Uri(BearerAuth.uri); // todo: this only works for Microsoft APIs. Make code conditional on Microsoft? Break out as separate API to be execute first? Change headers in json file? headers = new System.Collections.Generic.List <Tuple <string, string> >() { new Tuple <string, string>("Content-Type", "application/x-www-form-urlencoded"), new Tuple <string, string>("Ocp-Apim-Subscription-Key", h.OcpApimSubscriptionKey) // TODO: need dictionary lookup instead of hardcoding }; ServiceResponse sr = new ServiceResponse(); HttpMethods.CallApiAuthAsync(sr, accessUri, "", headers).Wait(); accessTokenInfo = new AccessTokenInfo(); accessTokenInfo.access_token = sr.ResponseString; } else if (h.BearerAuthentication.clientID != null && h.BearerAuthentication.clientSecret != null) // Microsoft { string clientID = bearer.clientID; string clientSecret = bearer.clientSecret; //string scope = bearer.scope; this.request = request; System.Collections.Generic.List <Tuple <string, string> > grantSubstitutes = new System.Collections.Generic.List <Tuple <string, string> >() { new Tuple <string, string>("{clientID}", System.Web.HttpUtility.UrlEncode(clientID)), new Tuple <string, string>("{clientSecret}", System.Web.HttpUtility.UrlEncode(clientSecret)), //new Tuple<string, string>("{scope}", System.Web.HttpUtility.UrlEncode(scope)), }; grant = bearer.grant; foreach (Tuple <string, string> r in grantSubstitutes) { grant = grant.Replace(r.Item1, r.Item2); } accessUri = new Uri(bearer.uri); headers = new System.Collections.Generic.List <Tuple <string, string> >() { new Tuple <string, string>("Content-Type", "application/x-www-form-urlencoded") }; ServiceResponse sr = new ServiceResponse(); await HttpMethods.CallApiAuthAsync(sr, accessUri, grant, headers); accessTokenInfo = Newtonsoft.Json.JsonConvert.DeserializeObject <AccessTokenInfo>(sr.ResponseString); // renew the token every specfied minutes accessTokenRenewer = new System.Threading.Timer(new System.Threading.TimerCallback(OnTokenExpiredCallbackAsync), this, TimeSpan.FromMinutes(RefreshTokenDuration), TimeSpan.FromMilliseconds(-1)); } else if (h.BearerAuthentication.bearer != null) // Wit.Ai { accessTokenInfo.access_token = h.BearerAuthentication.bearer; } else { throw new Exception("Unknown Bearer Authentication"); } return(accessTokenInfo); }