예제 #1
0
        /// <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);
                }
            }
        }
예제 #2
0
        /// <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);
                }
            }
        }
예제 #3
0
        /// <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);
        }
예제 #7
0
        /// <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();
                }
            }
        }
예제 #8
0
        /// <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;
                    }
                }
            }
        }
예제 #9
0
        /// <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);
        }
예제 #11
0
        /// <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);
            }
        }