public GatewayStoreModel( GlobalEndpointManager endpointManager, ISessionContainer sessionContainer, TimeSpan requestTimeout, ConsistencyLevel defaultConsistencyLevel, DocumentClientEventSource eventSource, JsonSerializerSettings serializerSettings, UserAgentContainer userAgent, ApiType apiType = ApiType.None, HttpMessageHandler messageHandler = null) { // CookieContainer is not really required, but is helpful in debugging. this.cookieJar = new CookieContainer(); this.endpointManager = endpointManager; HttpClient httpClient = new HttpClient(messageHandler ?? new HttpClientHandler { CookieContainer = this.cookieJar }); this.sessionContainer = sessionContainer; this.defaultConsistencyLevel = defaultConsistencyLevel; // Use max of client specified and our own request timeout value when sending // requests to gateway. Otherwise, we will have gateway's transient // error hiding retries are of no use. httpClient.Timeout = (requestTimeout > this.requestTimeout) ? requestTimeout : this.requestTimeout; httpClient.DefaultRequestHeaders.CacheControl = new CacheControlHeaderValue { NoCache = true }; httpClient.AddUserAgentHeader(userAgent); httpClient.AddApiTypeHeader(apiType); // Set requested API version header that can be used for // version enforcement. httpClient.DefaultRequestHeaders.Add(HttpConstants.HttpHeaders.Version, HttpConstants.Versions.CurrentVersion); httpClient.DefaultRequestHeaders.Add(HttpConstants.HttpHeaders.Accept, RuntimeConstants.MediaTypes.Json); this.eventSource = eventSource; this.gatewayStoreClient = new GatewayStoreClient( httpClient, this.eventSource, serializerSettings); }
public GatewayStoreModel( GlobalEndpointManager endpointManager, ISessionContainer sessionContainer, ConsistencyLevel defaultConsistencyLevel, DocumentClientEventSource eventSource, JsonSerializerSettings serializerSettings, HttpClient httpClient) { this.endpointManager = endpointManager; this.sessionContainer = sessionContainer; this.defaultConsistencyLevel = defaultConsistencyLevel; this.eventSource = eventSource; this.gatewayStoreClient = new GatewayStoreClient( httpClient, this.eventSource, serializerSettings); }
private void Dispose(bool disposing) { if (disposing) { if (this.gatewayStoreClient != null) { try { this.gatewayStoreClient.Dispose(); } catch (Exception exception) { DefaultTrace.TraceWarning("Exception {0} thrown during dispose of HttpClient, this could happen if there are inflight request during the dispose of client", exception); } this.gatewayStoreClient = null; } } }
public override Task <HttpResponseMessage> GetAsync( Uri uri, INameValueCollection additionalHeaders, ResourceType resourceType, HttpTimeoutPolicy timeoutPolicy, CosmosDiagnosticsContext diagnosticsContext, CancellationToken cancellationToken) { if (uri == null) { throw new ArgumentNullException(nameof(uri)); } // GetAsync doesn't let clients to pass in additional headers. So, we are // internally using SendAsync and add the additional headers to requestMessage. ValueTask <HttpRequestMessage> CreateRequestMessage() { HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Get, uri); if (additionalHeaders != null) { foreach (string header in additionalHeaders) { if (GatewayStoreClient.IsAllowedRequestHeader(header)) { requestMessage.Headers.TryAddWithoutValidation(header, additionalHeaders[header]); } } } return(new ValueTask <HttpRequestMessage>(requestMessage)); } return(this.SendHttpAsync( CreateRequestMessage, resourceType, timeoutPolicy, diagnosticsContext, cancellationToken)); }
public virtual async Task <DocumentServiceResponse> ProcessMessageAsync(DocumentServiceRequest request, CancellationToken cancellationToken = default) { await GatewayStoreModel.ApplySessionTokenAsync( request, this.defaultConsistencyLevel, this.sessionContainer, this.partitionKeyRangeCache, this.clientCollectionCache, this.endpointManager); DocumentServiceResponse response; try { Uri physicalAddress = GatewayStoreClient.IsFeedRequest(request.OperationType) ? this.GetFeedUri(request) : this.GetEntityUri(request); // Collect region name only for document resources if (request.ResourceType.Equals(ResourceType.Document) && this.endpointManager.TryGetLocationForGatewayDiagnostics(request.RequestContext.LocationEndpointToRoute, out string regionName)) { request.RequestContext.RegionName = regionName; } response = await this.gatewayStoreClient.InvokeAsync(request, request.ResourceType, physicalAddress, cancellationToken); } catch (DocumentClientException exception) { if ((!ReplicatedResourceClient.IsMasterResource(request.ResourceType)) && (exception.StatusCode == HttpStatusCode.PreconditionFailed || exception.StatusCode == HttpStatusCode.Conflict || (exception.StatusCode == HttpStatusCode.NotFound && exception.GetSubStatus() != SubStatusCodes.ReadSessionNotAvailable))) { await this.CaptureSessionTokenAndHandleSplitAsync(exception.StatusCode, exception.GetSubStatus(), request, exception.Headers); } throw; } await this.CaptureSessionTokenAndHandleSplitAsync(response.StatusCode, response.SubStatusCode, request, response.Headers); return(response); }
internal static async Task <DocumentServiceResponse> ParseResponseAsync(HttpResponseMessage responseMessage, JsonSerializerSettings serializerSettings = null, DocumentServiceRequest request = null) { using (responseMessage) { IClientSideRequestStatistics requestStatistics = request?.RequestContext?.ClientRequestStatistics; if ((int)responseMessage.StatusCode < 400) { INameValueCollection headers = GatewayStoreClient.ExtractResponseHeaders(responseMessage); Stream contentStream = await GatewayStoreClient.BufferContentIfAvailableAsync(responseMessage); return(new DocumentServiceResponse( body: contentStream, headers: headers, statusCode: responseMessage.StatusCode, clientSideRequestStatistics: requestStatistics, serializerSettings: serializerSettings)); } else if (request != null && request.IsValidStatusCodeForExceptionlessRetry((int)responseMessage.StatusCode)) { INameValueCollection headers = GatewayStoreClient.ExtractResponseHeaders(responseMessage); Stream contentStream = await GatewayStoreClient.BufferContentIfAvailableAsync(responseMessage); return(new DocumentServiceResponse( body: contentStream, headers: headers, statusCode: responseMessage.StatusCode, clientSideRequestStatistics: requestStatistics, serializerSettings: serializerSettings)); } else { throw await GatewayStoreClient.CreateDocumentClientExceptionAsync(responseMessage, requestStatistics); } } }
private async ValueTask <HttpRequestMessage> PrepareRequestMessageAsync( DocumentServiceRequest request, Uri physicalAddress) { HttpMethod httpMethod = HttpMethod.Head; if (request.OperationType == OperationType.Create || request.OperationType == OperationType.Upsert || request.OperationType == OperationType.Query || request.OperationType == OperationType.SqlQuery || request.OperationType == OperationType.Batch || request.OperationType == OperationType.ExecuteJavaScript || request.OperationType == OperationType.QueryPlan) { httpMethod = HttpMethod.Post; } else if (request.OperationType == OperationType.Read || request.OperationType == OperationType.ReadFeed) { httpMethod = HttpMethod.Get; } else if (request.OperationType == OperationType.Replace) { httpMethod = HttpMethod.Put; } else if (request.OperationType == OperationType.Delete) { httpMethod = HttpMethod.Delete; } else if (request.OperationType == OperationType.Patch) { // There isn't support for PATCH method in .NetStandard 2.0 httpMethod = httpPatchMethod; } else { throw new NotImplementedException(); } HttpRequestMessage requestMessage = new HttpRequestMessage(httpMethod, physicalAddress); // The StreamContent created below will own and dispose its underlying stream, but we may need to reuse the stream on the // DocumentServiceRequest for future requests. Hence we need to clone without incurring copy cost, so that when // HttpRequestMessage -> StreamContent -> MemoryStream all get disposed, the original stream will be left open. if (request.Body != null) { await request.EnsureBufferedBodyAsync(); MemoryStream clonedStream = new MemoryStream(); // WriteTo doesn't use and update Position of source stream. No point in setting/restoring it. request.CloneableBody.WriteTo(clonedStream); clonedStream.Position = 0; requestMessage.Content = new StreamContent(clonedStream); } if (request.Headers != null) { foreach (string key in request.Headers) { if (GatewayStoreClient.IsAllowedRequestHeader(key)) { if (key.Equals(HttpConstants.HttpHeaders.ContentType, StringComparison.OrdinalIgnoreCase)) { requestMessage.Content.Headers.ContentType = new MediaTypeHeaderValue(request.Headers[key]); } else { requestMessage.Headers.TryAddWithoutValidation(key, request.Headers[key]); } } } } // add activityId Guid activityId = Trace.CorrelationManager.ActivityId; Debug.Assert(activityId != Guid.Empty); requestMessage.Headers.Add(HttpConstants.HttpHeaders.ActivityId, activityId.ToString()); return(requestMessage); }
public void TestIsFeedRequestForBatchOperation() { Assert.IsTrue(GatewayStoreClient.IsFeedRequest(OperationType.Batch)); }
public static Task <DocumentServiceResponse> ParseResponseAsync(HttpResponseMessage responseMessage, JsonSerializerSettings serializerSettings = null, DocumentServiceRequest request = null) { return(GatewayStoreClient.ParseResponseAsync(responseMessage, serializerSettings, request)); }