/// <summary> /// Calls the token endpoint to obtain an access token. /// </summary> /// <param name="body">The request body.</param> /// <param name="errorMessage">The error message.</param> protected void CallTokenEndpoint(string body) { WebRequest request = HttpUtilities.BuildRequest(TOKEN_ENDPOINT, "POST", config); request.ContentType = "application/x-www-form-urlencoded"; using (StreamWriter writer = new StreamWriter(request.GetRequestStream())) { writer.Write(body); } LogEntry logEntry = new LogEntry(config, new DefaultDateTimeProvider()); logEntry.LogRequest(request, body, REQUEST_HEADERS_TO_MASK); WebResponse response = null; try { response = request.GetResponse(); string contents = MediaUtilities.GetStreamContentsAsString(response.GetResponseStream()); logEntry.LogResponse(response, false, contents, RESPONSE_FIELDS_TO_MASK, new JsonBodyFormatter()); logEntry.Flush(); Dictionary<string, string> values = ParseJsonObjectResponse(contents); if (values.ContainsKey("access_token")) { this.AccessToken = values["access_token"]; } if (values.ContainsKey("refresh_token")) { this.RefreshToken = values["refresh_token"]; } if (values.ContainsKey("token_type")) { this.tokenType = values["token_type"]; } if (values.ContainsKey("expires_in")) { this.expiresIn = int.Parse(values["expires_in"]); } this.updatedOn = DateTime.Now; if (this.OnOAuthTokensObtained != null) { this.OnOAuthTokensObtained(this); } } catch (WebException e) { string contents = ""; response = e.Response; try { contents = MediaUtilities.GetStreamContentsAsString(response.GetResponseStream()); logEntry.LogResponse(response, true, contents, RESPONSE_FIELDS_TO_MASK, new JsonBodyFormatter()); } catch { contents = e.Message; logEntry.LogResponse(response, true, contents); } logEntry.Flush(); throw new ApplicationException(contents, e); } finally { if (response != null) { response.Close(); } } }
/// <summary> /// Downloads a report to stream. /// </summary> /// <param name="downloadUrl">The download url.</param> /// <param name="postBody">The POST body.</param> private ReportResponse DownloadReport(string downloadUrl, string postBody) { AdWordsErrorHandler errorHandler = new AdWordsErrorHandler(this.User as AdWordsUser); while (true) { WebResponse response = null; HttpWebRequest request = BuildRequest(downloadUrl, postBody); LogEntry logEntry = new LogEntry(User.Config, new DefaultDateTimeProvider()); logEntry.LogRequest(request, postBody, HEADERS_TO_MASK); try { response = request.GetResponse(); logEntry.LogResponse(response, false, "Response truncated."); logEntry.Flush(); return new ReportResponse(response); } catch (WebException e) { Exception reportsException = null; string contents = HttpUtilities.GetErrorResponseBody(e); logEntry.LogResponse(e.Response, true, contents); logEntry.Flush(); reportsException = ParseException(e, contents); if (AdWordsErrorHandler.IsOAuthTokenExpiredError(reportsException)) { reportsException = new AdWordsCredentialsExpiredException( request.Headers["Authorization"]); } if (errorHandler.ShouldRetry(reportsException)) { errorHandler.PrepareForRetry(reportsException); } else { throw reportsException; } } } }
/// <summary> /// Performs the SOAP and HTTP logging. /// </summary> /// <param name="service">The SOAP service.</param> /// <param name="soapResponse">The SOAP response xml.</param> /// <param name="soapRequest">The SOAP request xml.</param> private void PerformLogging(AdsClient service, string soapRequest, string soapResponse) { if (service == null || service.User == null || soapRequest == null || soapResponse == null) { return; } bool isFailure = service.LastResponse != null && service.LastResponse is HttpWebResponse && (service.LastResponse as HttpWebResponse).StatusCode == HttpStatusCode.InternalServerError; LogEntry logEntry = new LogEntry(config, dateTimeProvider); logEntry.LogRequestDetails(service.LastRequest, soapRequest, GetFieldsToMask(), new SoapTraceFormatter()); logEntry.LogResponseDetails(service.LastResponse, soapResponse, new HashSet<string>(), new DefaultBodyFormatter()); logEntry.LogRequestSummary(service.LastRequest, GetSummaryRequestLogs(soapRequest)); logEntry.LogResponseSummary(isFailure, GetSummaryResponseLogs(soapResponse)); logEntry.Flush(); ContextStore.AddKey("FormattedSoapLog", logEntry.DetailedLog); ContextStore.AddKey("FormattedRequestLog", logEntry.SummaryLog); }
/// <summary> /// Revokes the refresh token. /// </summary> /// <exception cref="ArgumentNullException">Thrown if one of the following /// OAuth2 parameters are empty: RefreshToken.</exception> public void RevokeRefreshToken() { ValidateOAuth2Parameter("RefreshToken", RefreshToken); string url = string.Format("{0}?token={1}", REVOKE_ENDPOINT, RefreshToken); WebRequest request = HttpWebRequest.Create(url); request.Proxy = config.Proxy; LogEntry logEntry = new LogEntry(this.Config, new DefaultDateTimeProvider()); logEntry.LogRequest(request, "", new HashSet<string>()); WebResponse response = null; try { response = request.GetResponse(); string contents = MediaUtilities.GetStreamContentsAsString(response.GetResponseStream()); logEntry.LogResponse(response, false, contents); logEntry.Flush(); } catch (WebException e) { string contents = ""; response = e.Response; try { contents = MediaUtilities.GetStreamContentsAsString(response.GetResponseStream()); } catch { contents = e.Message; } logEntry.LogResponse(response, true, contents); logEntry.Flush(); throw new AdsOAuthException("Failed to revoke refresh token.\n" + contents, e); } finally { if (response != null) { response.Close(); } } }
/// <summary> /// Uploads a chunk of data for the batch job. /// </summary> /// <param name="url">The resumable upload URL.</param> /// <param name="postBody">The post body.</param> /// <param name="start">The start of range of bytes to be uploaded.</param> /// <param name="end">The end of range of bytes to be uploaded.</param> private void UploadChunk(string url, byte[] postBody, int start, int end) { BulkJobErrorHandler errorHandler = new BulkJobErrorHandler(user); while (true) { WebResponse response = null; LogEntry logEntry = new LogEntry(User.Config, new DefaultDateTimeProvider()); int bytesToWrite = end - start + 1; HttpWebRequest request = (HttpWebRequest) HttpUtilities.BuildRangeRequest( url, bytesToWrite, string.Format("bytes {0}-{1}/{2}", start, end, postBody.Length), user.Config); request.ContentType = "application/xml"; try { using (Stream requestStream = request.GetRequestStream()) { requestStream.Write(postBody, start, bytesToWrite); } logEntry.LogRequest(request, "Truncated", HEADERS_TO_MASK); response = request.GetResponse(); logEntry.LogResponse(response, true, ""); logEntry.Flush(); return; } catch (WebException e) { response = e.Response; if (IsPartialUploadSuccessResponse(e)) { logEntry.LogResponse(e.Response, true, ""); logEntry.Flush(); return; } else { HandleCloudException(errorHandler, logEntry, e); } } } }
/// <summary> /// Handles the exception from Google Cloud Storage servers when uploading /// operations. /// </summary> /// <param name="errorHandler">The error handler.</param> /// <param name="logEntry">The log entry.</param> /// <param name="e">The web exception that was thrown by the server.</param> /// <returns>True if this is a success, false if this was a server error. /// </returns> private void HandleCloudException(BulkJobErrorHandler errorHandler, LogEntry logEntry, WebException e) { Exception downloadException = null; using (WebResponse response = e.Response) { string contents = HttpUtilities.GetErrorResponseBody(e); logEntry.LogResponse(response, false, contents); logEntry.Flush(); downloadException = ParseException(e, contents); if (errorHandler.ShouldRetry(downloadException)) { errorHandler.PrepareForRetry(downloadException); } else { throw downloadException; } } }
/// <summary> /// Gets the upload progress. /// </summary> /// <param name="url">The resumable upload URL.</param> /// <param name="totalLength">The total length of upload.</param> /// <returns>The number of bytes uploaded so far.</returns> private int GetUploadProgress(string url, int totalLength) { int retval = 0; BulkJobErrorHandler errorHandler = new BulkJobErrorHandler(user); while (true) { WebResponse response = null; WebRequest request = HttpUtilities.BuildRangeRequest(url, 0, string.Format("bytes */{0}", totalLength), user.Config); LogEntry logEntry = new LogEntry(User.Config, new DefaultDateTimeProvider()); logEntry.LogRequest(request, "Truncated", HEADERS_TO_MASK); try { response = request.GetResponse(); } catch (WebException e) { if (IsPartialUploadSuccessResponse(e)) { retval = ExtractUpperRange(e.Response.Headers["Range"], retval); logEntry.LogResponse(e.Response, true, ""); logEntry.Flush(); break; } else { HandleCloudException(errorHandler, logEntry, e); } } } return retval; }
/// <summary> /// Downloads the batch job results from a specified URL. /// </summary> /// <param name="url">The download URL from a batch job.</param> /// <returns>The results from the batch job.</returns> public BatchJobMutateResponse Download(string url) { BulkJobErrorHandler errorHandler = new BulkJobErrorHandler(user); while (true) { WebRequest request = HttpUtilities.BuildRequest(url, "GET", user.Config); WebResponse response = null; LogEntry logEntry = new LogEntry(User.Config, new DefaultDateTimeProvider()); logEntry.LogRequest(request, "", HEADERS_TO_MASK); try { response = request.GetResponse(); string contents = MediaUtilities.GetStreamContentsAsString( response.GetResponseStream()); logEntry.LogResponse(response, false, contents); logEntry.Flush(); return ParseResponse(contents); } catch (WebException e) { HandleCloudException(errorHandler, logEntry, e); } } }
/// <summary> /// Initializes a new instance of the <see cref="TraceHelperTests"/> class. /// </summary> public TraceHelperTests() { logEntry = new LogEntry(CONFIG, DATE_PROVIDER); }