public async Task GivenABundleWithAGet_WhenNotAuthorized_ReturnsABundleResponseWithCorrectEntry() { var bundle = new Hl7.Fhir.Model.Bundle { Type = Hl7.Fhir.Model.Bundle.BundleType.Batch, Entry = new List <Hl7.Fhir.Model.Bundle.EntryComponent> { new Hl7.Fhir.Model.Bundle.EntryComponent { Request = new Hl7.Fhir.Model.Bundle.RequestComponent { Method = Hl7.Fhir.Model.Bundle.HTTPVerb.GET, Url = "/Patient", }, }, }, }; _router.When(r => r.RouteAsync(Arg.Any <RouteContext>())) .Do(RouteAsyncFunction); var bundleRequest = new BundleRequest(bundle.ToResourceElement()); BundleResponse bundleResponse = await _bundleHandler.Handle(bundleRequest, CancellationToken.None); var bundleResource = bundleResponse.Bundle.ToPoco <Hl7.Fhir.Model.Bundle>(); Assert.Equal(Hl7.Fhir.Model.Bundle.BundleType.BatchResponse, bundleResource.Type); Assert.Single(bundleResource.Entry); Hl7.Fhir.Model.Bundle.EntryComponent entryComponent = bundleResource.Entry.First(); Assert.Equal("403", entryComponent.Response.Status); var operationOutcome = entryComponent.Response.Outcome as OperationOutcome; Assert.NotNull(operationOutcome); Assert.Single(operationOutcome.Issue); var issueComponent = operationOutcome.Issue.First(); Assert.Equal(OperationOutcome.IssueSeverity.Error, issueComponent.Severity); Assert.Equal(OperationOutcome.IssueType.Forbidden, issueComponent.Code); Assert.Equal("Authorization failed.", issueComponent.Diagnostics); void RouteAsyncFunction(CallInfo callInfo) { var routeContext = callInfo.Arg <RouteContext>(); routeContext.Handler = context => { context.Response.StatusCode = 403; return(Task.CompletedTask); }; } }
private async Task ExecuteRequests(Hl7.Fhir.Model.Bundle responseBundle, Hl7.Fhir.Model.Bundle.HTTPVerb httpVerb) { foreach (RouteContext request in _requests[httpVerb]) { var entryComponent = new Hl7.Fhir.Model.Bundle.EntryComponent(); if (request.Handler != null) { HttpContext httpContext = request.HttpContext; await request.Handler.Invoke(httpContext); httpContext.Response.Body.Seek(0, SeekOrigin.Begin); string bodyContent = new StreamReader(httpContext.Response.Body).ReadToEnd(); ResponseHeaders responseHeaders = httpContext.Response.GetTypedHeaders(); entryComponent.Response = new Hl7.Fhir.Model.Bundle.ResponseComponent { Status = httpContext.Response.StatusCode.ToString(), Location = responseHeaders.Location?.OriginalString, Etag = responseHeaders.ETag?.ToString(), LastModified = responseHeaders.LastModified, }; if (!string.IsNullOrWhiteSpace(bodyContent)) { var entryComponentResource = _fhirJsonParser.Parse <Resource>(bodyContent); if (entryComponentResource.ResourceType == ResourceType.OperationOutcome) { entryComponent.Response.Outcome = entryComponentResource; } else { entryComponent.Resource = entryComponentResource; } } } else { entryComponent.Response = new Hl7.Fhir.Model.Bundle.ResponseComponent { Status = ((int)HttpStatusCode.NotFound).ToString() }; } responseBundle.Entry.Add(entryComponent); } }
private async Task ExecuteRequests(Hl7.Fhir.Model.Bundle responseBundle, Hl7.Fhir.Model.Bundle.HTTPVerb httpVerb) { foreach (RouteContext request in _requests[httpVerb]) { var entryComponent = new Hl7.Fhir.Model.Bundle.EntryComponent(); if (request.Handler != null) { HttpContext httpContext = request.HttpContext; IFhirRequestContext originalFhirRequestContext = _fhirRequestContextAccessor.FhirRequestContext; request.RouteData.Values.TryGetValue(KnownActionParameterNames.ResourceType, out object resourceType); var newFhirRequestContext = new FhirRequestContext( httpContext.Request.Method, httpContext.Request.GetDisplayUrl(), originalFhirRequestContext.BaseUri.OriginalString, originalFhirRequestContext.CorrelationId, httpContext.Request.Headers, httpContext.Response.Headers, resourceType?.ToString()) { Principal = originalFhirRequestContext.Principal, }; _fhirRequestContextAccessor.FhirRequestContext = newFhirRequestContext; _bundleHttpContextAccessor.HttpContext = httpContext; await request.Handler.Invoke(httpContext); httpContext.Response.Body.Seek(0, SeekOrigin.Begin); string bodyContent = new StreamReader(httpContext.Response.Body).ReadToEnd(); ResponseHeaders responseHeaders = httpContext.Response.GetTypedHeaders(); entryComponent.Response = new Hl7.Fhir.Model.Bundle.ResponseComponent { Status = httpContext.Response.StatusCode.ToString(), Location = responseHeaders.Location?.OriginalString, Etag = responseHeaders.ETag?.ToString(), LastModified = responseHeaders.LastModified, }; if (!string.IsNullOrWhiteSpace(bodyContent)) { var entryComponentResource = _fhirJsonParser.Parse <Resource>(bodyContent); if (entryComponentResource.ResourceType == ResourceType.OperationOutcome) { entryComponent.Response.Outcome = entryComponentResource; if (responseBundle.Type == Hl7.Fhir.Model.Bundle.BundleType.TransactionResponse) { ThrowTransactionException(httpContext, (OperationOutcome)entryComponentResource); } } else { entryComponent.Resource = entryComponentResource; } } else { if (httpContext.Response.StatusCode == (int)HttpStatusCode.Forbidden) { entryComponent.Response.Outcome = CreateOperationOutcome( OperationOutcome.IssueSeverity.Error, OperationOutcome.IssueType.Forbidden, Api.Resources.Forbidden); } } } else { entryComponent.Response = new Hl7.Fhir.Model.Bundle.ResponseComponent { Status = ((int)HttpStatusCode.NotFound).ToString(), Outcome = CreateOperationOutcome( OperationOutcome.IssueSeverity.Error, OperationOutcome.IssueType.NotFound, string.Format(Api.Resources.BundleNotFound, $"{request.HttpContext.Request.Path}{request.HttpContext.Request.QueryString}")), }; } responseBundle.Entry.Add(entryComponent); } }
/// <summary> /// Deserialize JSON into a FHIR Bundle /// </summary> public static void DeserializeJsonProperty(this Bundle current, ref Utf8JsonReader reader, JsonSerializerOptions options, string propertyName) { switch (propertyName) { case "identifier": current.Identifier = new Hl7.Fhir.Model.Identifier(); ((Hl7.Fhir.Model.Identifier)current.Identifier).DeserializeJson(ref reader, options); break; case "type": if (reader.TokenType == JsonTokenType.Null) { current.TypeElement = new Code <Hl7.Fhir.Model.Bundle.BundleType>(); reader.Skip(); } else { current.TypeElement = new Code <Hl7.Fhir.Model.Bundle.BundleType>(Hl7.Fhir.Utility.EnumUtility.ParseLiteral <Hl7.Fhir.Model.Bundle.BundleType>(reader.GetString())); } break; case "_type": if (current.TypeElement == null) { current.TypeElement = new Code <Hl7.Fhir.Model.Bundle.BundleType>(); } ((Hl7.Fhir.Model.Element)current.TypeElement).DeserializeJson(ref reader, options); break; case "timestamp": if (reader.TokenType == JsonTokenType.Null) { current.TimestampElement = new Instant(); reader.Skip(); } else { current.TimestampElement = new Instant(DateTimeOffset.Parse(reader.GetString())); } break; case "_timestamp": if (current.TimestampElement == null) { current.TimestampElement = new Instant(); } ((Hl7.Fhir.Model.Element)current.TimestampElement).DeserializeJson(ref reader, options); break; case "total": if (reader.TokenType == JsonTokenType.Null) { current.TotalElement = new UnsignedInt(); reader.Skip(); } else { current.TotalElement = new UnsignedInt(reader.GetInt32()); } break; case "_total": if (current.TotalElement == null) { current.TotalElement = new UnsignedInt(); } ((Hl7.Fhir.Model.Element)current.TotalElement).DeserializeJson(ref reader, options); break; case "link": if ((reader.TokenType != JsonTokenType.StartArray) || (!reader.Read())) { throw new JsonException($"Bundle error reading 'link' expected StartArray, found {reader.TokenType}! depth: {reader.CurrentDepth}, pos: {reader.BytesConsumed}"); } current.Link = new List <Bundle.LinkComponent>(); while (reader.TokenType != JsonTokenType.EndArray) { Hl7.Fhir.Model.Bundle.LinkComponent v_Link = new Hl7.Fhir.Model.Bundle.LinkComponent(); v_Link.DeserializeJson(ref reader, options); current.Link.Add(v_Link); if (!reader.Read()) { throw new JsonException($"Bundle error reading 'link' array, read failed! depth: {reader.CurrentDepth}, pos: {reader.BytesConsumed}"); } if (reader.TokenType == JsonTokenType.EndObject) { reader.Read(); } } if (current.Link.Count == 0) { current.Link = null; } break; case "entry": if ((reader.TokenType != JsonTokenType.StartArray) || (!reader.Read())) { throw new JsonException($"Bundle error reading 'entry' expected StartArray, found {reader.TokenType}! depth: {reader.CurrentDepth}, pos: {reader.BytesConsumed}"); } current.Entry = new List <Bundle.EntryComponent>(); while (reader.TokenType != JsonTokenType.EndArray) { Hl7.Fhir.Model.Bundle.EntryComponent v_Entry = new Hl7.Fhir.Model.Bundle.EntryComponent(); v_Entry.DeserializeJson(ref reader, options); current.Entry.Add(v_Entry); if (!reader.Read()) { throw new JsonException($"Bundle error reading 'entry' array, read failed! depth: {reader.CurrentDepth}, pos: {reader.BytesConsumed}"); } if (reader.TokenType == JsonTokenType.EndObject) { reader.Read(); } } if (current.Entry.Count == 0) { current.Entry = null; } break; case "signature": current.Signature = new Hl7.Fhir.Model.Signature(); ((Hl7.Fhir.Model.Signature)current.Signature).DeserializeJson(ref reader, options); break; // Complex: Bundle, Export: Bundle, Base: Resource default: ((Hl7.Fhir.Model.Resource)current).DeserializeJsonProperty(ref reader, options, propertyName); break; } }