private ServiceResult <HttpRequestMessage> TryCreateHttpRequest(HttpMethod httpMethod, string relativeUrlPattern, IEnumerable <KeyValuePair <string, string> > uriParameters, IEnumerable <KeyValuePair <string, string> > requestHeaders) { string url = m_baseUrl.TrimEnd('/') + "/" + relativeUrlPattern.TrimStart('/'); if (uriParameters != null) { url = GetUrlFromPattern(url, uriParameters); } var requestMessage = new HttpRequestMessage(httpMethod, url); var headersResult = HttpServiceUtility.TryAddHeaders(requestMessage.Headers, requestHeaders); if (headersResult.IsFailure) { return(headersResult.AsFailure()); } return(ServiceResult.Success(requestMessage)); }
private ServiceResult <HttpRequestMessage> TryCreateHttpRequest(HttpMethod httpMethod, string relativeUriPattern, IEnumerable <KeyValuePair <string, string> > uriParameters, IEnumerable <KeyValuePair <string, string> > requestHeaders) { string uriText = m_baseUri.AbsoluteUri; if (!string.IsNullOrEmpty(relativeUriPattern)) { uriText = uriText.TrimEnd('/') + "/" + relativeUriPattern.TrimStart('/'); } Uri uri = uriParameters != null?GetUriFromPattern(uriText, uriParameters) : new Uri(uriText); var requestMessage = new HttpRequestMessage(httpMethod, uri); var headersResult = HttpServiceUtility.TryAddHeaders(requestMessage.Headers, requestHeaders); if (headersResult.IsFailure) { return(headersResult.AsFailure()); } return(ServiceResult.Success(requestMessage)); }
/// <summary> /// Attempts to handle a service method. /// </summary> protected async Task <HttpResponseMessage> TryHandleServiceMethodAsync <TRequest, TResponse>(HttpMethodMapping <TRequest, TResponse> mapping, HttpRequestMessage httpRequest, Func <TRequest, CancellationToken, Task <ServiceResult <TResponse> > > invokeMethodAsync, CancellationToken cancellationToken) where TRequest : ServiceDto, new() where TResponse : ServiceDto, new() { if (httpRequest.Method != mapping.HttpMethod) { return(null); } var pathParameters = TryMatchHttpRoute(httpRequest.RequestUri, m_rootPath + mapping.Path); if (pathParameters == null) { return(null); } var context = new ServiceHttpContext(); ServiceHttpContext.SetContext(httpRequest, context); var aspectHttpResponse = await AdaptTask(RequestReceivedAsync(httpRequest, cancellationToken)).ConfigureAwait(true); if (aspectHttpResponse != null) { return(aspectHttpResponse); } string mediaType = GetResponseMediaType(httpRequest); ServiceErrorDto error = null; object requestBody = null; if (mapping.RequestBodyType != null) { var requestResult = await AdaptTask(m_contentSerializer.ReadHttpContentAsync(mapping.RequestBodyType, httpRequest.Content, cancellationToken)).ConfigureAwait(true); if (requestResult.IsFailure) { error = requestResult.Error; } else { requestBody = requestResult.Value; } } TResponse response = null; if (error == null) { var request = mapping.CreateRequest(requestBody); var uriParameters = new Dictionary <string, string>(); foreach (var queryParameter in ParseQueryString(httpRequest.RequestUri.Query)) { uriParameters[queryParameter.Key] = queryParameter.Value[0]; } foreach (var pathParameter in pathParameters) { uriParameters[pathParameter.Key] = pathParameter.Value; } request = mapping.SetUriParameters(request, uriParameters); request = mapping.SetRequestHeaders(request, HttpServiceUtility.CreateDictionaryFromHeaders(httpRequest.Headers)); context.Request = request; var methodResult = await invokeMethodAsync(request, cancellationToken).ConfigureAwait(true); if (methodResult.IsFailure) { error = methodResult.Error; } else { response = methodResult.Value; } context.Result = error != null?ServiceResult.Failure(error) : ServiceResult.Success <ServiceDto>(response); } HttpResponseMessage httpResponse; if (error == null) { var responseMappingGroups = mapping.ResponseMappings .GroupBy(x => x.MatchesResponse(response)) .Where(x => x.Key != false) .OrderByDescending(x => x.Key) .ToList(); if (responseMappingGroups.Count >= 1 && responseMappingGroups[0].Count() == 1) { var responseMapping = responseMappingGroups[0].Single(); httpResponse = new HttpResponseMessage(responseMapping.StatusCode); var headersResult = HttpServiceUtility.TryAddHeaders(httpResponse.Headers, mapping.GetResponseHeaders(response)); if (headersResult.IsFailure) { throw new InvalidOperationException(headersResult.Error.Message); } if (responseMapping.ResponseBodyType != null) { httpResponse.Content = m_contentSerializer.CreateHttpContent(responseMapping.GetResponseBody(response), mediaType); } } else { throw new InvalidOperationException($"Found {responseMappingGroups.Sum(x => x.Count())} valid HTTP responses for {typeof(TResponse).Name}: {response}"); } } else { var statusCode = error.Code == null ? HttpStatusCode.InternalServerError : (TryGetCustomHttpStatusCode(error.Code) ?? HttpServiceErrors.TryGetHttpStatusCode(error.Code) ?? HttpStatusCode.InternalServerError); httpResponse = new HttpResponseMessage(statusCode); if (statusCode != HttpStatusCode.NoContent && statusCode != HttpStatusCode.NotModified) { httpResponse.Content = m_contentSerializer.CreateHttpContent(error, mediaType); } } httpResponse.RequestMessage = httpRequest; await AdaptTask(ResponseReadyAsync(httpResponse, cancellationToken)).ConfigureAwait(true); return(httpResponse); }