Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(465)

Delta Between Two Patch Sets: Src/GoogleApis/Apis/Http/ConfigurableMessageHandler.cs

Issue 13412046: Reimplement OAuth2 library - Step 1 (Closed) Base URL: https://google-api-dotnet-client.googlecode.com/hg/
Left Patch Set: Created 10 years, 10 months ago
Right Patch Set: minor Created 10 years, 10 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
LEFTRIGHT
1 /* 1 /*
2 Copyright 2013 Google Inc 2 Copyright 2013 Google Inc
3 3
4 Licensed under the Apache License, Version 2.0 (the "License"); 4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License. 5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at 6 You may obtain a copy of the License at
7 7
8 http://www.apache.org/licenses/LICENSE-2.0 8 http://www.apache.org/licenses/LICENSE-2.0
9 9
10 Unless required by applicable law or agreed to in writing, software 10 Unless required by applicable law or agreed to in writing, software
(...skipping 15 matching lines...) Expand all
26 using Google.Apis.Logging; 26 using Google.Apis.Logging;
27 using Google.Apis.Testing; 27 using Google.Apis.Testing;
28 28
29 namespace Google.Apis.Http 29 namespace Google.Apis.Http
30 { 30 {
31 /// <summary> 31 /// <summary>
32 /// This message handler contains the main logic of our HTTP requests. It co ntains a list of· 32 /// This message handler contains the main logic of our HTTP requests. It co ntains a list of·
33 /// <see cref="IHttpUnsuccessfulResponseHandler"/>s for handling abnormal re sponses, a list of· 33 /// <see cref="IHttpUnsuccessfulResponseHandler"/>s for handling abnormal re sponses, a list of·
34 /// <see cref="IHttpExceptionHandler"/>s for handling exception in a request and a list of· 34 /// <see cref="IHttpExceptionHandler"/>s for handling exception in a request and a list of·
35 /// <see cref="IHttpExecuteInterceptor"/>s for intercepting a request before it has been sent to the server. 35 /// <see cref="IHttpExecuteInterceptor"/>s for intercepting a request before it has been sent to the server.
36 /// It also contains important properties like number of tires, follow redir ect, etc. 36 /// It also contains important properties like number of tires, follow redir ect, etc.
class 2013/09/21 03:12:10 Should this be number of retries?
peleyal 2013/09/23 12:01:16 tries The property is NumTries. On 2013/09/21 03
37 /// </summary> 37 /// </summary>
38 public class ConfigurableMessageHandler : DelegatingHandler 38 public class ConfigurableMessageHandler : DelegatingHandler
39 { 39 {
40 /// <summary> The class logger. </summary> 40 /// <summary>The class logger.</summary>
41 private static readonly ILogger Logger = ApplicationContext.Logger.ForTy pe<ConfigurableMessageHandler>(); 41 private static readonly ILogger Logger = ApplicationContext.Logger.ForTy pe<ConfigurableMessageHandler>();
42 42
43 /// <summary> Maximum allowed number of tries. </summary> 43 /// <summary>Maximum allowed number of tries.</summary>
44 [VisibleForTestOnly] 44 [VisibleForTestOnly]
45 internal const int MaxAllowedNumTries = 20; 45 internal const int MaxAllowedNumTries = 20;
46 46
47 /// <summary> The current API version of this client library. </summary> 47 /// <summary>The current API version of this client library.</summary>
48 private static readonly string ApiVersion = Google.Apis.Util.Utilities.G etLibraryVersion(); 48 private static readonly string ApiVersion = Google.Apis.Util.Utilities.G etLibraryVersion();
49 49
50 /// <summary> The User-Agent suffix header which contains the <seealso c ref="ApiVersion"/>. </summary> 50 /// <summary>The User-Agent suffix header which contains the <seealso cr ef="ApiVersion"/>.</summary>
51 private static readonly string UserAgentSuffix = "google-api-dotnet-clie nt/" ApiVersion " (gzip)"; 51 private static readonly string UserAgentSuffix = "google-api-dotnet-clie nt/" ApiVersion " (gzip)";
52 52
53 #region IHttpUnsuccessfulResponseHandler, IHttpExceptionHandler and IHtt pExecuteInterceptor lists 53 #region IHttpUnsuccessfulResponseHandler, IHttpExceptionHandler and IHtt pExecuteInterceptor lists
54 54
55 /// <summary> A list of <see cref="IHttpUnsuccessfulResponseHandler"/>. </summary> 55 /// <summary>A list of <see cref="IHttpUnsuccessfulResponseHandler"/>.</ summary>
56 private readonly IList<IHttpUnsuccessfulResponseHandler> unsuccessfulRes ponseHandlers = 56 private readonly IList<IHttpUnsuccessfulResponseHandler> unsuccessfulRes ponseHandlers =
57 new List<IHttpUnsuccessfulResponseHandler>(); 57 new List<IHttpUnsuccessfulResponseHandler>();
58 58
59 /// <summary> A list of <see cref="IHttpExceptionHandler"/>. </summary> 59 /// <summary>A list of <see cref="IHttpExceptionHandler"/>.</summary>
60 private readonly IList<IHttpExceptionHandler> exceptionHandlers = 60 private readonly IList<IHttpExceptionHandler> exceptionHandlers =
61 new List<IHttpExceptionHandler>(); 61 new List<IHttpExceptionHandler>();
62 62
63 /// <summary> A list of <see cref="IHttpExecuteInterceptor"/>. </summary > 63 /// <summary>A list of <see cref="IHttpExecuteInterceptor"/>.</summary>
64 private readonly IList<IHttpExecuteInterceptor> executeInterceptors = 64 private readonly IList<IHttpExecuteInterceptor> executeInterceptors =
65 new List<IHttpExecuteInterceptor>(); 65 new List<IHttpExecuteInterceptor>();
66 66
67 /// <summary> Gets a list of <see cref="IHttpUnsuccessfulResponseHandler "/>. </summary> 67 /// <summary>Gets a list of <see cref="IHttpUnsuccessfulResponseHandler" />.</summary>
68 public IList<IHttpUnsuccessfulResponseHandler> UnsuccessfulResponseHandl ers 68 public IList<IHttpUnsuccessfulResponseHandler> UnsuccessfulResponseHandl ers
69 { 69 {
70 get { return unsuccessfulResponseHandlers; } 70 get { return unsuccessfulResponseHandlers; }
71 } 71 }
72 72
73 /// <summary> Gets a list of <see cref="IHttpExceptionHandler"/>. </summ ary> 73 /// <summary>Gets a list of <see cref="IHttpExceptionHandler"/>.</summar y>
74 public IList<IHttpExceptionHandler> ExceptionHandlers 74 public IList<IHttpExceptionHandler> ExceptionHandlers
75 { 75 {
76 get { return exceptionHandlers; } 76 get { return exceptionHandlers; }
77 } 77 }
78 78
79 /// <summary> Gets a list of <see cref="IHttpExecuteInterceptor"/>. </su mmary> 79 /// <summary>Gets a list of <see cref="IHttpExecuteInterceptor"/>.</summ ary>
80 public IList<IHttpExecuteInterceptor> ExecuteInterceptors 80 public IList<IHttpExecuteInterceptor> ExecuteInterceptors
81 { 81 {
82 get { return executeInterceptors; } 82 get { return executeInterceptors; }
83 } 83 }
84 84
85 #endregion 85 #endregion
86 86
87 /// <summary> Number of tries. Default is <c>3</c>. </summary> 87 /// <summary>Number of tries. Default is <c>3</c>.</summary>
88 private int numTries = 3; 88 private int numTries = 3;
89 89
90 /// <summary> 90 /// <summary>
91 /// Gets or sets the number of tries that will be allowed to execute. Re tries occur as a result of either 91 /// Gets or sets the number of tries that will be allowed to execute. Re tries occur as a result of either
92 /// <see cref="IHttpUnsuccessfulResponseHandler"/> or <see cref="IHttpEx ceptionHandler"/> which handles the 92 /// <see cref="IHttpUnsuccessfulResponseHandler"/> or <see cref="IHttpEx ceptionHandler"/> which handles the
93 /// abnormal Http response or exception, before being terminated.· 93 /// abnormal HTTP response or exception, before being terminated.·
94 /// Set <c>1</c> for not retrying requests. The default value is <c>3</c >". 94 /// Set <c>1</c> for not retrying requests. The default value is <c>3</c >".
95 /// </summary> 95 /// </summary>
96 public int NumTries 96 public int NumTries
97 { 97 {
98 get { return numTries; } 98 get { return numTries; }
99 set 99 set
100 { 100 {
101 if (value > MaxAllowedNumTries || value < 1) 101 if (value > MaxAllowedNumTries || value < 1)
102 { 102 {
103 throw new ArgumentOutOfRangeException("NumTries"); 103 throw new ArgumentOutOfRangeException("NumTries");
104 } 104 }
105 numTries = value; 105 numTries = value;
106 } 106 }
107 } 107 }
108 108
109 /// <summary> 109 /// <summary>
110 /// Gets or sets whether the handler should follow a redirect when a red irect response is received. Default· 110 /// Gets or sets whether the handler should follow a redirect when a red irect response is received. Default·
111 /// value is <c>true</c>. 111 /// value is <c>true</c>.
112 /// </summary> 112 /// </summary>
113 public bool FollowRedirect { get; set; } 113 public bool FollowRedirect { get; set; }
114 114
115 /// <summary> Gets or sets whether logging is enabled. Default value is <c>true</c>. </summary> 115 /// <summary>Gets or sets whether logging is enabled. Default value is < c>true</c>.</summary>
116 public bool IsLoggingEnabled { get; set; } 116 public bool IsLoggingEnabled { get; set; }
117 117
118 /// <summary> Gets or sets the application name which will be used on th e User-Agent header. </summary> 118 /// <summary>Gets or sets the application name which will be used on the User-Agent header.</summary>
119 public string ApplicationName { get; set; } 119 public string ApplicationName { get; set; }
120 120
121 /// <summary> Constructs a new configurable message handler </summary> 121 /// <summary>Constructs a new configurable message handler </summary>
122 public ConfigurableMessageHandler(HttpMessageHandler httpMessageHandler) 122 public ConfigurableMessageHandler(HttpMessageHandler httpMessageHandler)
123 : base(httpMessageHandler) 123 : base(httpMessageHandler)
124 { 124 {
125 // set default values 125 // set default values
126 FollowRedirect = true; 126 FollowRedirect = true;
127 IsLoggingEnabled = true; 127 IsLoggingEnabled = true;
128 } 128 }
129 129
130 /// <summary> 130 /// <summary>
131 /// The main logic of sending a request to the server. This send method adds the User-Agent header to a request 131 /// The main logic of sending a request to the server. This send method adds the User-Agent header to a request
132 /// with <see cref="ApplicationName"/> and the library version. It also calls interceptors before each attempt, 132 /// with <see cref="ApplicationName"/> and the library version. It also calls interceptors before each attempt,
133 /// and unsuccessful response handler or exception handlers when abnorma l response or exception occurred. 133 /// and unsuccessful response handler or exception handlers when abnorma l response or exception occurred.
134 /// </summary> 134 /// </summary>
135 protected override async Task<HttpResponseMessage> SendAsync(HttpRequest Message request, 135 protected override async Task<HttpResponseMessage> SendAsync(HttpRequest Message request,
136 CancellationToken cancellationToken) 136 CancellationToken cancellationToken)
137 { 137 {
138 var loggable = IsLoggingEnabled && Logger.IsDebugEnabled; 138 var loggable = IsLoggingEnabled && Logger.IsDebugEnabled;
139 139
140 int triesRemaining = NumTries; 140 int triesRemaining = NumTries;
141 Exception lastException = null; 141 Exception lastException = null;
142 142
143 // set User-Agent header 143 // Set User-Agent header.
144 var userAgent = (ApplicationName == null ? "" : ApplicationName " ") UserAgentSuffix; 144 var userAgent = (ApplicationName == null ? "" : ApplicationName " ") UserAgentSuffix;
145 // TODO: setting the User-Agent won't work on Silverlight. We may ne ed to create a special callback here to· 145 // TODO: setting the User-Agent won't work on Silverlight. We may ne ed to create a special callback here to·
146 // set it correctly. Also check what happen in WP? 146 // set it correctly.
147 request.Headers.Add("User-Agent", userAgent); 147 request.Headers.Add("User-Agent", userAgent);
148 148
149 HttpResponseMessage response = null; 149 HttpResponseMessage response = null;
150 do // while (triesRemaining > 0) 150 do // While (triesRemaining > 0)
151 { 151 {
152 cancellationToken.ThrowIfCancellationRequested(); 152 cancellationToken.ThrowIfCancellationRequested();
153 153
154 if (response != null) 154 if (response != null)
155 { 155 {
156 response.Dispose(); 156 response.Dispose();
157 response = null; 157 response = null;
158 } 158 }
159 lastException = null; 159 lastException = null;
160 160
161 // intercept the request 161 // Intercept the request.
162 foreach (var interceptor in executeInterceptors) 162 foreach (var interceptor in executeInterceptors)
163 { 163 {
164 await interceptor.InterceptAsync(request, cancellationToken) .ConfigureAwait(false); 164 await interceptor.InterceptAsync(request, cancellationToken) .ConfigureAwait(false);
165 } 165 }
166 166
167 try 167 try
168 { 168 {
169 // send the request! 169 // Send the request!
170 response = await base.SendAsync(request, cancellationToken). ConfigureAwait(false); 170 response = await base.SendAsync(request, cancellationToken). ConfigureAwait(false);
171 } 171 }
172 catch (Exception ex) 172 catch (Exception ex)
173 { 173 {
174 lastException = ex; 174 lastException = ex;
175 } 175 }
176 176
177 // decrease the number of retries 177 // Decrease the number of retries.
178 triesRemaining--; 178 triesRemaining--;
179 179
180 // exception was thrown , try to handle it 180 // Exception was thrown, try to handle it.
181 if (response == null) 181 if (response == null)
182 { 182 {
183 var exceptionHandled = false; 183 var exceptionHandled = false;
184 184
185 // try to handle the exception with each handler 185 // Try to handle the exception with each handler.
186 foreach (var handler in exceptionHandlers) 186 foreach (var handler in exceptionHandlers)
187 { 187 {
188 exceptionHandled |= await handler.HandleExceptionAsync(n ew HandleExceptionArgs 188 exceptionHandled |= await handler.HandleExceptionAsync(n ew HandleExceptionArgs
189 { 189 {
190 Request = request, 190 Request = request,
191 Exception = lastException, 191 Exception = lastException,
192 TotalTries = NumTries, 192 TotalTries = NumTries,
193 CurrentFailedTry = NumTries - triesRemaining, 193 CurrentFailedTry = NumTries - triesRemaining,
194 CancellationToken = cancellationToken 194 CancellationToken = cancellationToken
195 }).ConfigureAwait(false); 195 }).ConfigureAwait(false);
196 } 196 }
197 197
198 if (!exceptionHandled) 198 if (!exceptionHandled)
199 { 199 {
200 Logger.Error(lastException, 200 Logger.Error(lastException,
201 "Exception was thrown while executing a HTTP request and it wasn't handled"); 201 "Exception was thrown while executing a HTTP request and it wasn't handled");
202 throw lastException; 202 throw lastException;
203 } 203 }
204 else if (loggable) 204 else if (loggable)
205 { 205 {
206 Logger.Debug("Exception {0} was thrown, but it was handl ed by an exception handler", 206 Logger.Debug("Exception {0} was thrown, but it was handl ed by an exception handler",
207 lastException.Message); 207 lastException.Message);
208 } 208 }
209 } 209 }
210 else 210 else
211 { 211 {
212 if (response.IsSuccessStatusCode) 212 if (response.IsSuccessStatusCode)
213 { 213 {
214 // no need to retry, the response was successful 214 // No need to retry, the response was successful.
215 triesRemaining = 0; 215 triesRemaining = 0;
216 } 216 }
217 else 217 else
218 { 218 {
219 bool errorHandled = false; 219 bool errorHandled = false;
220 220
221 // try to handle the abnormal HTTP response with each ha ndler 221 // Try to handle the abnormal HTTP response with each ha ndler.
222 foreach (var handler in unsuccessfulResponseHandlers) 222 foreach (var handler in unsuccessfulResponseHandlers)
223 { 223 {
224 errorHandled |= await handler.HandleResponseAsync(ne w HandleUnsuccessfulResponseArgs 224 errorHandled |= await handler.HandleResponseAsync(ne w HandleUnsuccessfulResponseArgs
225 { 225 {
226 Request = request, 226 Request = request,
227 Response = response, 227 Response = response,
228 TotalTries = NumTries, 228 TotalTries = NumTries,
229 CurrentFailedTry = NumTries - triesRemaining , 229 CurrentFailedTry = NumTries - triesRemaining ,
230 CancellationToken = cancellationToken 230 CancellationToken = cancellationToken
231 }).ConfigureAwait(false); 231 }).ConfigureAwait(false);
(...skipping 11 matching lines...) Expand all
243 } 243 }
244 } 244 }
245 else 245 else
246 { 246 {
247 if (loggable) 247 if (loggable)
248 { 248 {
249 Logger.Debug("An abnormal response wasn't ha ndled. Status code is {0}", 249 Logger.Debug("An abnormal response wasn't ha ndled. Status code is {0}",
250 response.StatusCode); 250 response.StatusCode);
251 } 251 }
252 252
253 // no need to retry, because no handler handled the abnormal response 253 // No need to retry, because no handler handled the abnormal response.
254 triesRemaining = 0; 254 triesRemaining = 0;
255 } 255 }
256 } 256 }
257 else if (loggable) 257 else if (loggable)
258 { 258 {
259 Logger.Debug("An abnormal response was handled by an unsuccessful response handler. " 259 Logger.Debug("An abnormal response was handled by an unsuccessful response handler. "
260 "Status Code is {0}", response.StatusCode); 260 "Status Code is {0}", response.StatusCode);
261 } 261 }
262 } 262 }
263 } 263 }
264 } while (triesRemaining > 0); // not a success status code but it wa s handled 264 } while (triesRemaining > 0); // Not a successful status code but it was handled.
265 265
266 // if the response is null, we should throw the last exception 266 // If the response is null, we should throw the last exception.
267 if (response == null) 267 if (response == null)
268 { 268 {
269 Logger.Error(lastException, "Exception was thrown while executin g a HTTP request"); 269 Logger.Error(lastException, "Exception was thrown while executin g a HTTP request");
270 throw lastException; 270 throw lastException;
271 } 271 }
272 else if (!response.IsSuccessStatusCode) 272 else if (!response.IsSuccessStatusCode)
273 { 273 {
274 Logger.Debug("Abnormal response is being returned. Status Code i s {0}", response.StatusCode); 274 Logger.Debug("Abnormal response is being returned. Status Code i s {0}", response.StatusCode);
275 } 275 }
276 276
(...skipping 16 matching lines...) Expand all
293 return false; 293 return false;
294 } 294 }
295 295
296 var request = message.RequestMessage; 296 var request = message.RequestMessage;
297 request.RequestUri = new Uri(request.RequestUri, uri); 297 request.RequestUri = new Uri(request.RequestUri, uri);
298 // Status code for a resource that has moved to a new URI and should be retrieved using GET. 298 // Status code for a resource that has moved to a new URI and should be retrieved using GET.
299 if (message.StatusCode == HttpStatusCode.SeeOther) 299 if (message.StatusCode == HttpStatusCode.SeeOther)
300 { 300 {
301 request.Method = HttpMethod.Get; 301 request.Method = HttpMethod.Get;
302 } 302 }
303 // clear Authorization and If-* headers 303 // Clear Authorization and If-* headers.
304 request.Headers.Remove("Authorization"); 304 request.Headers.Remove("Authorization");
305 request.Headers.IfMatch.Clear(); 305 request.Headers.IfMatch.Clear();
306 request.Headers.IfNoneMatch.Clear(); 306 request.Headers.IfNoneMatch.Clear();
307 request.Headers.IfModifiedSince = null; 307 request.Headers.IfModifiedSince = null;
308 request.Headers.IfUnmodifiedSince = null; 308 request.Headers.IfUnmodifiedSince = null;
309 request.Headers.Remove("If-Range"); 309 request.Headers.Remove("If-Range");
310 return true; 310 return true;
311 } 311 }
312 } 312 }
313 } 313 }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b