/// <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> /// Uploads the operations to a specified URL. /// </summary> /// <param name="url">The temporary URL returned by a batch job.</param> /// <param name="operations">The list of operations.</param> public void Upload(string url, Operation[] operations) { BulkJobErrorHandler errorHandler = new BulkJobErrorHandler(user); string postBody = GetPostBody(operations); while (true) { WebResponse response = null; HttpWebRequest request = BuildRequest(url, postBody); LogEntry logEntry = new LogEntry(User.Config, new DefaultDateTimeProvider()); logEntry.LogRequest(request, postBody, HEADERS_TO_MASK); try { response = request.GetResponse(); string contents = MediaUtilities.GetStreamContentsAsString( response.GetResponseStream()); logEntry.LogResponse(response, false, contents); logEntry.Flush(); break; } catch (WebException e) { 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> private void HandleCloudException(BulkJobErrorHandler errorHandler, LogEntry logEntry, WebException e) { string contents = ""; Exception downloadException = null; using (WebResponse response = e.Response) { try { contents = MediaUtilities.GetStreamContentsAsString( response.GetResponseStream()); } catch { contents = e.Message; } logEntry.LogResponse(response, true, contents); logEntry.Flush(); downloadException = ParseException(e, contents); } if (errorHandler.ShouldRetry(downloadException)) { errorHandler.PrepareForRetry(downloadException); } else { throw downloadException; } return; }
/// <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> protected string DownloadResults(string url) { // Mark the usage. featureUsageRegistry.MarkUsage(FEATURE_ID); 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(contents); } catch (WebException e) { HandleCloudException(errorHandler, logEntry, e); } finally { if (response != null) { response.Close(); } } } }
/// <summary> /// Generates a resumable upload URL for a job. This method should be used prior /// to calling the Upload() method when using API version >=v201601. /// </summary> /// <returns>The resumable upload URL.</returns> /// <param name="url">The temporary upload URL from BatchJobService.</param> public string GetResumableUploadUrl(string url) { WebRequest request = HttpUtilities.BuildRequest(url, "POST", user.Config); request.ContentType = "application/xml"; request.ContentLength = 0; request.Headers["x-goog-resumable"] = "start"; 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(response.Headers["Location"]); } catch (WebException e) { string contents = HttpUtilities.GetErrorResponseBody(e); logEntry.LogResponse(e.Response, false, contents); logEntry.Flush(); throw ParseException(e, contents); } finally { if (response != null) { response.Close(); } } }
/// <summary> /// Gets the upload progress. /// </summary> /// <param name="url">The resumable upload URL.</param> /// <returns>The number of bytes uploaded so far.</returns> protected virtual int GetUploadProgress(string url) { int totalLength = 0; int retval = 0; BulkJobErrorHandler errorHandler = new BulkJobErrorHandler(user); while (true) { WebResponse response = null; // As per https://cloud.google.com/storage/docs/resumable-uploads-xml#step_4wzxhzdk17query_title_for_the_upload_status, // one should be passing bytes */Length, where length is the actual // length of bytes that was being uploaded during the request that was // interrupted. In practice, passing length as 0 also works. WebRequest request = HttpUtilities.BuildRangeRequest(url, 0, string.Format("bytes */{0}", totalLength), user.Config); LogEntry logEntry = new LogEntry(User.Config, new DefaultDateTimeProvider()); logEntry.LogRequest(GenerateRequestInfo(request, ""), HEADERS_TO_MASK); try { response = request.GetResponse(); // This block of code is hit if the user uploaded without chunking and // then called this method. string contents = MediaUtilities.GetStreamContentsAsString( response.GetResponseStream()); Dictionary <string, object> temp = JsonConvert.DeserializeObject <Dictionary <string, object> >(contents); int.TryParse(temp["size"].ToString(), out retval); logEntry.LogResponse(GenerateResponseInfo(response, "", "")); logEntry.Flush(); break; } catch (WebException e) { // This block of code is hit if if chunking is enabled and the // operations upload is incomplete. The server responds with a 308 // status code. See // https://cloud.google.com/storage/docs/resumable-uploads-xml#step_4wzxhzdk17query_title_for_the_upload_status // for more details. if (IsPartialUploadSuccessResponse(e)) { retval = ExtractUpperRange(e.Response.Headers["Range"], retval) + 1; logEntry.LogResponse(GenerateResponseInfo(e.Response, "", "")); logEntry.Flush(); break; } else { HandleCloudException(errorHandler, logEntry, e); } } finally { if (response != null) { response.Close(); } } } return(retval); }
/// <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"; LogEntry logEntry = new LogEntry(config, new DefaultDateTimeProvider()); WebResponse response = null; try { HttpUtilities.WritePostBodyAndLog(request, body, logEntry, REQUEST_HEADERS_TO_MASK); 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.UtcNow; if (this.OnOAuthTokensObtained != null) { this.OnOAuthTokensObtained(this); } } catch (WebException e) { string contents = HttpUtilities.GetErrorResponseBody(e); logEntry.LogResponse(response, true, contents, RESPONSE_FIELDS_TO_MASK, new JsonBodyFormatter()); 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) { string contents = ""; Exception reportsException = null; using (response = e.Response) { try { contents = MediaUtilities.GetStreamContentsAsString( response.GetResponseStream()); } catch { contents = e.Message; } logEntry.LogResponse(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> /// Revokes the refresh token. /// </summary> /// <exception cref="ArgumentNullException">Thrown if one of the following /// OAuth2 parameters are empty: RefreshToken.</exception> public void RevokeRefreshToken() { // Mark the usage. featureUsageRegistry.MarkUsage(FEATURE_ID);; ValidateOAuth2Parameter("RefreshToken", RefreshToken); string url = string.Format("{0}?token={1}", REVOKE_ENDPOINT, RefreshToken); WebRequest request = HttpUtilities.BuildRequest(url, "GET", config); 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(); } } }
public void TestGetStreamContentsAsString() { string contents = MediaUtilities.GetStreamContentsAsString(sourceStream); Assert.AreEqual(FILE_CONTENTS, contents); }
/// <summary> /// Generates a ClientLogin token for use with various Ads APIs. /// </summary> /// <returns>The token string.</returns> /// <exception cref="AuthTokenException">If the token cannot be obtained, /// then an AuthTokenException is thrown with appropriate error code. /// </exception> private string GenerateToken() { WebRequest webRequest = HttpWebRequest.Create(url); webRequest.Method = "POST"; webRequest.ContentType = "application/x-www-form-urlencoded"; webRequest.Proxy = config.Proxy; webRequest.Timeout = config.Timeout; string postParams = "accountType=" + HttpUtility.UrlEncode(ACCOUNT_TYPE) + "&Email=" + HttpUtility.UrlEncode(Email) + "&Passwd=" + HttpUtility.UrlEncode(Password) + "&service=" + HttpUtility.UrlEncode(service) + "&source=" + HttpUtility.UrlEncode(SOURCE); byte[] postBytes = Encoding.UTF8.GetBytes(postParams); webRequest.ContentLength = postBytes.Length; using (Stream strmReq = webRequest.GetRequestStream()) { strmReq.Write(postBytes, 0, postBytes.Length); } LogEntry logEntry = new LogEntry(config, new DefaultDateTimeProvider()); logEntry.LogRequest(webRequest, postParams, REQUEST_HEADERS_TO_MASK); Dictionary <string, string> tblResponse = null; WebResponse response = null; try { response = webRequest.GetResponse(); string contents = MediaUtilities.GetStreamContentsAsString(response.GetResponseStream()); logEntry.LogResponse(response, false, contents, RESPONSE_FIELDS_TO_MASK, new KeyValueMessageFormatter()); logEntry.Flush(); tblResponse = ParseResponse(contents); } catch (WebException e) { string contents = ""; response = e.Response; try { contents = MediaUtilities.GetStreamContentsAsString(response.GetResponseStream()); } catch { contents = e.Message; } logEntry.LogResponse(response, true, contents, RESPONSE_FIELDS_TO_MASK, new KeyValueMessageFormatter()); logEntry.Flush(); AuthTokenException authException = ExtractException(e, contents); throw authException; } finally { if (response != null) { response.Close(); } } if (tblResponse.ContainsKey("Auth")) { return((string)tblResponse["Auth"]); } else { throw new AuthTokenException(AuthTokenErrorCode.Unknown, null, String.Empty, null, "Login failed - Could not find Auth key in response", null); } }