Left: | ||
Right: |
LEFT | RIGHT |
---|---|
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 25 matching lines...) Expand all Loading... | |
36 | 36 |
37 namespace Google.Apis.Services | 37 namespace Google.Apis.Services |
38 { | 38 { |
39 /// <summary> | 39 /// <summary> |
40 /// A thread-safe base class for a client service which provides common mech anism for all services, like· | 40 /// A thread-safe base class for a client service which provides common mech anism for all services, like· |
41 /// serialization and GZip support. | 41 /// serialization and GZip support. |
42 /// This class adds a special <see cref="Google.Apis.Http.IHttpExecuteInterc eptor"/> to the· | 42 /// This class adds a special <see cref="Google.Apis.Http.IHttpExecuteInterc eptor"/> to the· |
43 /// <see cref="Google.Apis.Http.ConfigurableMessageHandler"/> execute interc eptor list, which uses the given· | 43 /// <see cref="Google.Apis.Http.ConfigurableMessageHandler"/> execute interc eptor list, which uses the given· |
44 /// Authenticator. It calls to its applying authentication method, and injec ts the "Authorization" header in the· | 44 /// Authenticator. It calls to its applying authentication method, and injec ts the "Authorization" header in the· |
45 /// request. | 45 /// request. |
46 /// If the given Authenticator implements <see cref="Google.Apis.Http.IUnsuc cessfulReponseHandler"/>, this class | 46 /// If the given Authenticator implements <see cref="Google.Apis.Http.IHttpU nsuccessfulResponseHandler"/>, this· |
47 /// adds the Authenticator to the <see cref="Google.Apis.Http.ConfigurableMe ssageHandler"/>'s unsuccessful response | 47 /// class adds the Authenticator to the <see cref="Google.Apis.Http.Configur ableMessageHandler"/>'s unsuccessful· |
48 /// handler list. | 48 /// response handler list. |
49 /// </summary> | 49 /// </summary> |
50 public abstract class BaseClientService : IClientService | 50 public abstract class BaseClientService : IClientService |
51 { | 51 { |
52 /// <summary> The class logger. </summary> | 52 /// <summary>The class logger.</summary> |
53 private static readonly ILogger Logger = ApplicationContext.Logger.ForTy pe<BaseClientService>(); | 53 private static readonly ILogger Logger = ApplicationContext.Logger.ForTy pe<BaseClientService>(); |
54 | 54 |
55 /// <summary>The default maximum allowed length of a URL string for GET requests.</summary> | 55 /// <summary>The default maximum allowed length of a URL string for GET requests.</summary> |
56 private const uint DefaultMaxUrlLength = 2048; | 56 [VisibleForTestOnly] |
57 internal const uint DefaultMaxUrlLength = 2048; | |
57 | 58 |
58 #region Initializer | 59 #region Initializer |
59 | 60 |
60 /// <summary>· | 61 /// <summary>An initializer class for the client service.</summary> |
61 /// Indicates if exponential back-off is used automatically on exception in a service request and\or when 503· | |
62 /// response is returned form the server. | |
63 /// </summary> | |
64 [Flags] | |
65 public enum ExponentialBackOffPolicy | |
66 { | |
67 None = 0, | |
68 Exception = 1, | |
69 UnsuccessfulResponse503 = 2 | |
70 } | |
71 | |
72 /// <summary> An initializer class for the client service. </summary> | |
73 public class Initializer | 62 public class Initializer |
74 { | 63 { |
75 /// <summary> | 64 /// <summary> |
76 /// Gets or sets the factory for creating <see cref="System.Net.Http .HttpClient"/> instance. If this· | 65 /// Gets or sets the factory for creating <see cref="System.Net.Http .HttpClient"/> instance. If this· |
77 /// property is not set the service uses a new <see cref="Google.Api s.Http.HttpClientFactory"/> instance. | 66 /// property is not set the service uses a new <see cref="Google.Api s.Http.HttpClientFactory"/> instance. |
78 /// </summary> | 67 /// </summary> |
79 public IHttpClientFactory HttpClientFactory { get; set; } | 68 public IHttpClientFactory HttpClientFactory { get; set; } |
80 | 69 |
81 /// <summary> | 70 /// <summary> |
82 /// Gets or sets an Http client initializer which is able to customi ze properties on· | 71 /// Gets or sets a HTTP client initializer which is able to customiz e properties on· |
83 /// <see cref="Google.Apis.Http.ConfigurableHttpClient"/> and· | 72 /// <see cref="Google.Apis.Http.ConfigurableHttpClient"/> and· |
84 /// <see cref="Google.Apis.Http.ConfigurableMessageHandler"/>. | 73 /// <see cref="Google.Apis.Http.ConfigurableMessageHandler"/>. |
85 /// </summary> | 74 /// </summary> |
86 public IConfigurableHttpClientInitializer HttpClientInitializer { ge t; set; } | 75 public IConfigurableHttpClientInitializer HttpClientInitializer { ge t; set; } |
87 | 76 |
88 /// <summary> | 77 /// <summary> |
89 /// Get or sets the exponential back-off policy used by the service. Default value is· | 78 /// Get or sets the exponential back-off policy used by the service. Default value is· |
90 /// <c>UnsuccessfulResponse503</c>, which means that exponential bac k-off is used on 503 abnormal HTTP | 79 /// <c>UnsuccessfulResponse503</c>, which means that exponential bac k-off is used on 503 abnormal HTTP |
91 /// response. | 80 /// response. |
92 /// If the value is set to <c>None</c>, no exponential back-off poli cy is used, and it's up to user to | 81 /// If the value is set to <c>None</c>, no exponential back-off poli cy is used, and it's up to user to |
93 /// configure the <seealso cref="Google.Apis.Http.ConfigurableMessag eHandler"/> in an | 82 /// configure the <seealso cref="Google.Apis.Http.ConfigurableMessag eHandler"/> in an |
94 /// <seealso cref="Google.Apis.Http.IConfigurableHttpClientInitializ er"/> to set a specific back-off | 83 /// <seealso cref="Google.Apis.Http.IConfigurableHttpClientInitializ er"/> to set a specific back-off |
95 /// implementation (using <seealso cref="Google.Api.Http.BackOffHand ler"/>). | 84 /// implementation (using <seealso cref="Google.Apis.Http.BackOffHan dler"/>). |
96 /// </summary> | 85 /// </summary> |
97 public ExponentialBackOffPolicy DefaultExponentialBackOffPolicy { ge t; set; } | 86 public ExponentialBackOffPolicy DefaultExponentialBackOffPolicy { ge t; set; } |
98 | 87 |
99 /// <summary> Gets or sets whether this service supports GZip. Defau lt value is <c>true</c>. </summary> | 88 /// <summary>Gets or sets whether this service supports GZip. Defaul t value is <c>true</c>.</summary> |
100 public bool GZipEnabled { get; set; } | 89 public bool GZipEnabled { get; set; } |
101 | 90 |
102 /// <summary> | 91 /// <summary> |
103 /// Gets and Sets the Serializer. Default value is <see cref="Google .Apis.Json.NewtonsoftJsonSerializer"/>. | 92 /// Gets and Sets the serializer. Default value is <see cref="Google .Apis.Json.NewtonsoftJsonSerializer"/>. |
104 /// </summary> | 93 /// </summary> |
105 public ISerializer Serializer { get; set; } | 94 public ISerializer Serializer { get; set; } |
106 | 95 |
107 /// <summary> Gets or sets the API Key. Default value is <c>null</c> . </summary> | 96 /// <summary>Gets or sets the API Key. Default value is <c>null</c>. </summary> |
108 public string ApiKey { get; set; } | 97 public string ApiKey { get; set; } |
109 | 98 |
110 /// <summary> | 99 /// <summary> |
111 /// Gets or sets the Authenticator. Default value is· | 100 /// Gets or sets the Authenticator. Default value is· |
112 /// <see cref="Google.Apis.Authentication.NullAuthenticator.Instance "/>. | 101 /// <see cref="Google.Apis.Authentication.NullAuthenticator.Instance "/>. |
113 /// </summary> | 102 /// </summary> |
114 public IAuthenticator Authenticator { get; set; } | 103 public IAuthenticator Authenticator { get; set; } |
115 | 104 |
116 /// <summary> | 105 /// <summary> |
117 /// Gets or sets Application name to be used in the User-Agent heade r. Default value is <c>null</c>.· | 106 /// Gets or sets Application name to be used in the User-Agent heade r. Default value is <c>null</c>.· |
118 /// </summary> | 107 /// </summary> |
119 public string ApplicationName { get; set; } | 108 public string ApplicationName { get; set; } |
120 | 109 |
121 /// <summary> | 110 /// <summary> |
122 /// Maximum allowed length of a URL string for GET requests. Default value is <c>2048</c>. | 111 /// Maximum allowed length of a URL string for GET requests. Default value is <c>2048</c>. If the value is |
112 /// set to <c>0</c>, requests will never be modified due to URL stri ng length. | |
123 /// </summary> | 113 /// </summary> |
124 public uint MaxUrlLength { get; set; } | 114 public uint MaxUrlLength { get; set; } |
125 | 115 |
126 /// <summary> Constructs a new initializer with default values. </su mmary> | 116 /// <summary>Constructs a new initializer with default values.</summ ary> |
127 public Initializer() | 117 public Initializer() |
128 { | 118 { |
129 GZipEnabled = true; | 119 GZipEnabled = true; |
130 Serializer = new NewtonsoftJsonSerializer(); | 120 Serializer = new NewtonsoftJsonSerializer(); |
131 Authenticator = NullAuthenticator.Instance; | 121 Authenticator = NullAuthenticator.Instance; |
132 DefaultExponentialBackOffPolicy = ExponentialBackOffPolicy.Unsuc cessfulResponse503; | 122 DefaultExponentialBackOffPolicy = ExponentialBackOffPolicy.Unsuc cessfulResponse503; |
133 MaxUrlLength = DefaultMaxUrlLength; | 123 MaxUrlLength = DefaultMaxUrlLength; |
134 } | 124 } |
135 } | 125 } |
136 | 126 |
137 /// <summary> | |
138 /// An initializer which adds exponential back-off as exception handler and\or unsuccessful response handler by | |
139 /// the given <seealso cref="BaseClientService.ExponentialBackOffPolicy" />. | |
140 /// </summary> | |
141 private class ExponentialBackOffInitializer : IConfigurableHttpClientIni tializer | |
142 { | |
143 private ExponentialBackOffPolicy Policy { get; set; } | |
144 private Func<BackOffHandler> CreateBackOff { get; set; } | |
145 | |
146 /// <summary> | |
147 /// Constructs a new back-off initializer with the given policy and back-off handler create function. | |
148 /// </summary> | |
149 public ExponentialBackOffInitializer(ExponentialBackOffPolicy policy , Func<BackOffHandler> createBackOff) | |
150 { | |
151 Policy = policy; | |
152 CreateBackOff = createBackOff; | |
153 } | |
154 | |
155 public void Initialize(ConfigurableHttpClient httpClient) | |
156 { | |
157 var backOff = CreateBackOff(); | |
158 | |
159 // add exception handler and\or unsuccessful response handler | |
160 if ((Policy & ExponentialBackOffPolicy.Exception) == Exponential BackOffPolicy.Exception) | |
161 { | |
162 httpClient.MessageHandler.ExceptionHandlers.Add(backOff); | |
163 } | |
164 | |
165 if ((Policy & ExponentialBackOffPolicy.UnsuccessfulResponse503) == | |
166 ExponentialBackOffPolicy.UnsuccessfulResponse503) | |
167 { | |
168 httpClient.MessageHandler.UnsuccessfulResponseHandlers.Add(b ackOff); | |
169 } | |
170 } | |
171 } | |
172 | |
173 #endregion | 127 #endregion |
174 | 128 |
175 /// <summary> Constructs a new base client with the specified initialize r. </summary> | 129 /// <summary>Constructs a new base client with the specified initializer .</summary> |
176 protected BaseClientService(Initializer initializer) | 130 protected BaseClientService(Initializer initializer) |
177 { | 131 { |
178 // sets the right properties by the initializer's properties | 132 // Set the right properties by the initializer's properties. |
179 GZipEnabled = initializer.GZipEnabled; | 133 GZipEnabled = initializer.GZipEnabled; |
180 Serializer = initializer.Serializer; | 134 Serializer = initializer.Serializer; |
181 ApiKey = initializer.ApiKey; | 135 ApiKey = initializer.ApiKey; |
182 Authenticator = initializer.Authenticator; | 136 Authenticator = initializer.Authenticator; |
183 ApplicationName = initializer.ApplicationName; | 137 ApplicationName = initializer.ApplicationName; |
184 if (ApplicationName == null) | 138 if (ApplicationName == null) |
185 { | 139 { |
186 Logger.Warning("Application name is not set. Please set Initiali zer.ApplicationName property"); | 140 Logger.Warning("Application name is not set. Please set Initiali zer.ApplicationName property"); |
187 } | 141 } |
188 HttpClientInitializer = initializer.HttpClientInitializer; | 142 HttpClientInitializer = initializer.HttpClientInitializer; |
189 | 143 |
190 // create an Http client for this service | 144 // Create a HTTP client for this service. |
191 HttpClient = CreateHttpClient(initializer); | 145 HttpClient = CreateHttpClient(initializer); |
192 } | 146 } |
193 | 147 |
194 /// <summary> Return <c>true</c> if this service contains the specified feature. </summary> | 148 /// <summary>Returns <c>true</c> if this service contains the specified feature.</summary> |
195 private bool HasFeature(Features feature) | 149 private bool HasFeature(Features feature) |
196 { | 150 { |
197 return Features.Contains(feature.GetStringValue()); | 151 return Features.Contains(feature.GetStringValue()); |
198 } | 152 } |
199 | 153 |
200 private ConfigurableHttpClient CreateHttpClient(Initializer initializer) | 154 private ConfigurableHttpClient CreateHttpClient(Initializer initializer) |
201 { | 155 { |
202 // if factory wasn't set use the default Http client factory | 156 // If factory wasn't set use the default HTTP client factory. |
203 var factory = initializer.HttpClientFactory ?? new HttpClientFactory (); | 157 var factory = initializer.HttpClientFactory ?? new HttpClientFactory (); |
204 var args = new CreateHttpClientArgs | 158 var args = new CreateHttpClientArgs |
205 { | 159 { |
206 GZipEnabled = GZipEnabled, | 160 GZipEnabled = GZipEnabled, |
207 ApplicationName = ApplicationName, | 161 ApplicationName = ApplicationName, |
208 }; | 162 }; |
209 | 163 |
210 // add the user's input initializer | 164 // Add the user's input initializer. |
211 if (HttpClientInitializer != null) | 165 if (HttpClientInitializer != null) |
212 { | 166 { |
213 args.Initializers.Add(HttpClientInitializer); | 167 args.Initializers.Add(HttpClientInitializer); |
214 } | 168 } |
215 | 169 |
216 // add exponential back-off initializer if necessary | 170 // Add exponential back-off initializer if necessary. |
217 if (initializer.DefaultExponentialBackOffPolicy != ExponentialBackOf fPolicy.None) | 171 if (initializer.DefaultExponentialBackOffPolicy != ExponentialBackOf fPolicy.None) |
218 { | 172 { |
219 args.Initializers.Add(new ExponentialBackOffInitializer(initiali zer.DefaultExponentialBackOffPolicy, | 173 args.Initializers.Add(new ExponentialBackOffInitializer(initiali zer.DefaultExponentialBackOffPolicy, |
220 CreateBackOffHandler)); | 174 CreateBackOffHandler)); |
221 } | 175 } |
222 | 176 |
223 // add authenticator initializer to intercept a request and add the "Authorization" header and also handle | 177 // Add authenticator initializer to intercept a request and add the "Authorization" header and also handle |
224 // abnormal 401 responses in case the authenticator is an instance o f unsuccessful response handler. | 178 // abnormal 401 responses in case the authenticator is an instance o f unsuccessful response handler. |
225 args.Initializers.Add(new AuthenticatorMessageHandlerInitializer(Aut henticator)); | 179 args.Initializers.Add(new AuthenticatorMessageHandlerInitializer(Aut henticator)); |
226 ············ | 180 ············ |
227 var httpClient = factory.CreateHttpClient(args); | 181 var httpClient = factory.CreateHttpClient(args); |
228 httpClient.MessageHandler.ExecuteInterceptors.Add(new MaxUrlLengthIn terceptor(initializer.MaxUrlLength)); | 182 if (initializer.MaxUrlLength > 0) |
183 { | |
184 httpClient.MessageHandler.ExecuteInterceptors.Add( | |
185 new MaxUrlLengthInterceptor(initializer.MaxUrlLength)); | |
186 } | |
229 return httpClient; | 187 return httpClient; |
230 } | 188 } |
231 | 189 |
232 /// <summary> | 190 /// <summary> |
233 /// Creates the back-off handler with <seealso cref="Google.Apis.Util.Ex ponentialBackOff"/>.· | 191 /// Creates the back-off handler with <seealso cref="Google.Apis.Util.Ex ponentialBackOff"/>.· |
234 /// Overrides this method to change the default behavior of back-off han dler (e.g. you can change the maximum | 192 /// Overrides this method to change the default behavior of back-off han dler (e.g. you can change the maximum |
235 /// waited request's time span, or create a back-off handler with you ow n implementation of· | 193 /// waited request's time span, or create a back-off handler with you ow n implementation of· |
236 /// <seealso cref="Google.Apis.Util.IBackOff"/>). | 194 /// <seealso cref="Google.Apis.Util.IBackOff"/>). |
237 /// </summary> | 195 /// </summary> |
238 protected virtual BackOffHandler CreateBackOffHandler() | 196 protected virtual BackOffHandler CreateBackOffHandler() |
239 { | 197 { |
240 // TODO(peleyal): consider return here interface and not the concret e class | 198 // TODO(peleyal): consider return here interface and not the concret e class |
241 return new BackOffHandler(new ExponentialBackOff()); | 199 return new BackOffHandler(new ExponentialBackOff()); |
242 } | 200 } |
243 | 201 |
244 #region IClientService Members | 202 #region IClientService Members |
245 | 203 |
246 public ConfigurableHttpClient HttpClient { get; private set; } | 204 public ConfigurableHttpClient HttpClient { get; private set; } |
247 | 205 |
248 public IConfigurableHttpClientInitializer HttpClientInitializer { get; p rivate set; } | 206 public IConfigurableHttpClientInitializer HttpClientInitializer { get; p rivate set; } |
249 | 207 |
250 public bool GZipEnabled { get; private set; } | 208 public bool GZipEnabled { get; private set; } |
251 | 209 |
252 public string ApiKey { get; private set; } | 210 public string ApiKey { get; private set; } |
253 | 211 |
254 public IAuthenticator Authenticator { get; private set; } | 212 public IAuthenticator Authenticator { get; private set; } |
255 | 213 |
256 public string ApplicationName { get; private set; } | 214 public string ApplicationName { get; private set; } |
257 | 215 |
258 public int MaxUrlLength { get; private set; } | |
peleyal
2013/08/26 01:28:48
but you don't set it now :)
So you can remove it f
ngmiceli
2013/08/29 19:17:06
...oh right.
Done :)
| |
259 | |
260 public void SetRequestSerailizedContent(HttpRequestMessage request, obje ct body) | 216 public void SetRequestSerailizedContent(HttpRequestMessage request, obje ct body) |
261 { | 217 { |
262 if (body == null) | 218 if (body == null) |
263 { | 219 { |
264 return; | 220 return; |
265 } | 221 } |
266 | 222 |
267 HttpContent content = null; | 223 HttpContent content = null; |
268 | 224 |
269 var mediaType = "application/" + Serializer.Format; | 225 var mediaType = "application/" + Serializer.Format; |
(...skipping 21 matching lines...) Expand all Loading... | |
291 public ISerializer Serializer { get; private set; } | 247 public ISerializer Serializer { get; private set; } |
292 | 248 |
293 public virtual string SerializeObject(object obj) | 249 public virtual string SerializeObject(object obj) |
294 { | 250 { |
295 if (HasFeature(Discovery.Features.LegacyDataResponse)) | 251 if (HasFeature(Discovery.Features.LegacyDataResponse)) |
296 { | 252 { |
297 // Legacy path | 253 // Legacy path |
298 var request = new StandardResponse<object> { Data = obj }; | 254 var request = new StandardResponse<object> { Data = obj }; |
299 return Serializer.Serialize(request); | 255 return Serializer.Serialize(request); |
300 } | 256 } |
301 | |
302 // New v1.0 path | |
303 return Serializer.Serialize(obj); | 257 return Serializer.Serialize(obj); |
304 } | 258 } |
305 | 259 |
306 public virtual async Task<T> DeserializeResponse<T>(HttpResponseMessage response) | 260 public virtual async Task<T> DeserializeResponse<T>(HttpResponseMessage response) |
307 { | 261 { |
308 var text = await response.Content.ReadAsStringAsync().ConfigureAwait (false); | 262 var text = await response.Content.ReadAsStringAsync().ConfigureAwait (false); |
309 | 263 |
310 // If a string is request, don't parse the response. | 264 // If a string is request, don't parse the response. |
311 if (typeof(T).Equals(typeof(string))) | 265 if (typeof(T).Equals(typeof(string))) |
312 { | 266 { |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
381 // Standard response (which contains data and error properties) | 335 // Standard response (which contains data and error properties) |
382 throw new GoogleApiException(Name, | 336 throw new GoogleApiException(Name, |
383 "An Error occurred, but the error response could not be dese rialized", ex); | 337 "An Error occurred, but the error response could not be dese rialized", ex); |
384 } | 338 } |
385 | 339 |
386 return errorResponse.Error; | 340 return errorResponse.Error; |
387 } | 341 } |
388 | 342 |
389 #endregion | 343 #endregion |
390 | 344 |
391 #region Abstract Memebrs | 345 #region Abstract Members |
392 | 346 |
393 public abstract string Name { get; } | 347 public abstract string Name { get; } |
394 public abstract string BaseUri { get; } | 348 public abstract string BaseUri { get; } |
395 public abstract string BasePath { get; } | 349 public abstract string BasePath { get; } |
396 | 350 |
397 public abstract IList<string> Features { get; } | 351 public abstract IList<string> Features { get; } |
398 | 352 |
399 #endregion | 353 #endregion |
400 | 354 |
401 #endregion | 355 #endregion |
402 | 356 |
403 /// <summary> Creates a GZip stream by the given serialized object. </su mmary> | 357 /// <summary>Creates a GZip stream by the given serialized object.</summ ary> |
404 private static Stream CreateGZipStream(string serializedObject) | 358 private static Stream CreateGZipStream(string serializedObject) |
405 { | 359 { |
406 byte[] bytes = System.Text.Encoding.UTF8.GetBytes(serializedObject); | 360 byte[] bytes = System.Text.Encoding.UTF8.GetBytes(serializedObject); |
407 using (System.IO.MemoryStream ms = new System.IO.MemoryStream()) | 361 using (System.IO.MemoryStream ms = new System.IO.MemoryStream()) |
408 { | 362 { |
409 using (GZipStream gzip = new GZipStream(ms, CompressionMode.Comp ress, true)) | 363 using (GZipStream gzip = new GZipStream(ms, CompressionMode.Comp ress, true)) |
410 { | 364 { |
411 gzip.Write(bytes, 0, bytes.Length); | 365 gzip.Write(bytes, 0, bytes.Length); |
412 } | 366 } |
413 | 367 |
414 // reset the stream to the beginning. It doesn't work otherwise! | 368 // reset the stream to the beginning. It doesn't work otherwise! |
415 ms.Position = 0; | 369 ms.Position = 0; |
416 byte[] compressed = new byte[ms.Length]; | 370 byte[] compressed = new byte[ms.Length]; |
417 ms.Read(compressed, 0, compressed.Length); | 371 ms.Read(compressed, 0, compressed.Length); |
418 return new MemoryStream(compressed); | 372 return new MemoryStream(compressed); |
419 } | 373 } |
420 } | 374 } |
421 | 375 |
422 public virtual void Dispose() | 376 public virtual void Dispose() |
423 { | 377 { |
424 if (HttpClient != null) | 378 if (HttpClient != null) |
425 { | 379 { |
426 HttpClient.Dispose(); | 380 HttpClient.Dispose(); |
427 } | 381 } |
428 } | 382 } |
429 } | 383 } |
430 | |
431 [VisibleForTestOnly] | |
432 /// <summary> | |
433 /// Intercepts HTTP GET requests with a URLs longer than <see cref="MaxUrlLe ngth" />. | |
peleyal
2013/08/26 01:28:48
<see cref="Initializer.MaxUrlLength"
ngmiceli
2013/08/29 19:17:06
Done.
| |
434 /// The interceptor will change such requests as follows:· | |
435 /// <list type="bullet"> | |
436 /// <item>The request type will be changed to POST</item> | |
peleyal
2013/08/26 01:28:48
I think you mean "request's method" and not "reque
ngmiceli
2013/08/29 19:17:06
Done.
| |
437 /// <item>A <c>X-HTTP-Method-Override</c> header will be added with the valu e <c>GET</c></item> | |
438 /// <item>Any query parameters from the URI will be moved into the body of t he request. | |
439 /// <item>If query parameters are moved, the content type is set to <c>appli cation/x-www-form-urlencoded</c></item> | |
440 /// </item></list> | |
441 /// </summary> | |
442 internal class MaxUrlLengthInterceptor : IHttpExecuteInterceptor· | |
443 { | |
444 private readonly uint maxUrlLength; | |
445 | |
446 ///<summary>Constructs a new Max URL length interceptor with the given m ax length.</summary> | |
447 public MaxUrlLengthInterceptor(uint maxUrlLength) | |
448 { | |
449 this.maxUrlLength = maxUrlLength; | |
450 } | |
451 | |
452 public void Intercept(HttpRequestMessage request) | |
453 { | |
454 if (request.Method == HttpMethod.Get && request.RequestUri.AbsoluteU ri.Length > maxUrlLength) { | |
peleyal
2013/08/26 01:28:48
[optional]
I think that you are the one that actua
ngmiceli
2013/08/29 19:17:06
Hey, you're right! I do prefer that :)
Done.
| |
455 // Change the method to POST | |
456 request.Method = HttpMethod.Post; | |
457 var query = request.RequestUri.Query; | |
458 if (! String.IsNullOrEmpty(query)) | |
peleyal
2013/08/26 01:28:48
if (! String.IsNullOrEmpty(query))
=>
if (!String.
ngmiceli
2013/08/29 19:17:06
Done.
| |
459 { | |
460 // Move query parameters to the body (without the "?") | |
461 request.Content = new StringContent(query.Substring(1)); | |
462 request.Content.Headers.ContentType = new MediaTypeHeaderVal ue("application/x-www-form-urlencoded"); | |
463 var requestString = request.RequestUri.ToString(); | |
464 request.RequestUri = new Uri(requestString.Remove(requestStr ing.IndexOf("?") - 1)); | |
465 } | |
466 request.Headers.Add("X-HTTP-Method-Override", "GET"); | |
467 } | |
468 } | |
469 } | |
470 } | 384 } |
LEFT | RIGHT |