/// <param name="date">The current date and time, used to authenticate /// the API request. Typically, you should specify DateTime.UtcNow, /// but if you do not wish to rely on the system-wide clock, you may /// determine the current date/time by some other means.</param> /// <param name="timeout">The request timeout, in milliseconds. /// Specify 0 to use the system-default timeout. Use caution if /// you choose to specify a custom timeout - some API /// calls (particularly in the Auth APIs) will not /// return a response until an out-of-band authentication process /// has completed. In some cases, this may take as much as a /// small number of minutes.</param> public string ApiCall(string method, string path, Dictionary <string, string> parameters, int timeout, DateTime date, out HttpStatusCode statusCode) { string canon_params = DuoApi.CanonicalizeParams(parameters); string query = ""; if (!method.Equals("POST") && !method.Equals("PUT")) { if (parameters.Count > 0) { query = "?" + canon_params; } } string url = string.Format("{0}://{1}{2}{3}", this.url_scheme, this.host, path, query); string date_string = DuoApi.DateToRFC822(date); string auth = this.Sign(method, path, canon_params, date_string); HttpWebResponse response = AttemptRetriableHttpRequest( method, url, auth, date_string, canon_params, timeout); StreamReader reader = new StreamReader(response.GetResponseStream()); statusCode = response.StatusCode; return(reader.ReadToEnd()); }
/// <param name="date">The current date and time, used to authenticate /// the API request. Typically, you should specify DateTime.UtcNow, /// but if you do not wish to rely on the system-wide clock, you may /// determine the current date/time by some other means.</param> /// <param name="timeout">The request timeout, in milliseconds. /// Specify 0 to use the system-default timeout. Use caution if /// you choose to specify a custom timeout - some API /// calls (particularly in the Auth and Verify APIs) will not /// return a response until an out-of-band authentication process /// has completed. In some cases, this may take as much as a /// small number of minutes.</param> public string ApiCall(string method, string path, Dictionary <string, string> parameters, int timeout, DateTime date, out HttpStatusCode statusCode) { string canon_params = DuoApi.CanonicalizeParams(parameters); string query = ""; if (!method.Equals("POST") && !method.Equals("PUT")) { if (parameters.Count > 0) { query = "?" + canon_params; } } string url = string.Format("{0}://{1}{2}{3}", this.url_scheme, this.host, path, query); string date_string = DuoApi.DateToRFC822(date); string auth = this.Sign(method, path, canon_params, date_string); HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); request.Method = method; request.Accept = "application/json"; request.Headers.Add("Authorization", auth); request.Headers.Add("X-Duo-Date", date_string); request.UserAgent = this.user_agent; // If no proxy, check for and use WinHTTP proxy as autoconfig won't pick this up when run from a service if (!HasProxyServer(request)) { request.Proxy = GetWinhttpProxy(); } LogProxyInfo(request.Proxy); if (method.Equals("POST") || method.Equals("PUT")) { byte[] data = Encoding.UTF8.GetBytes(canon_params); request.ContentType = "application/x-www-form-urlencoded"; request.ContentLength = data.Length; using (Stream requestStream = request.GetRequestStream()) { requestStream.Write(data, 0, data.Length); } } if (timeout > 0) { request.Timeout = timeout; } // Do the request and process the result. HttpWebResponse response; try { response = (HttpWebResponse)request.GetResponse(); } catch (WebException ex) { response = (HttpWebResponse)ex.Response; if (response == null) { throw; } } StreamReader reader = new StreamReader(response.GetResponseStream()); statusCode = response.StatusCode; return(reader.ReadToEnd()); }