Giter Club home page Giter Club logo

fhir-works-on-aws-routing's Introduction

fhir-works-on-aws-routing

This GitHub repository has been migrated. You can now find FHIR Works on AWS at https://github.com/aws-solutions/fhir-works-on-aws.

Purpose

Please visit fhir-works-on-aws-deployment for overall vision of the project and for more context.

This package is an implementation of the routing of the FHIR Works interface. It is responsible for taking a FHIR based HTTP request and routing it to the correct sub-component. It also does all the resource validatation by way of JSON schemas. Finally, This component is responsible for generating the Capability Statement, which is used to describe what a FHRI API can do. To use and deploy this component (with the other 'out of the box' components) please follow the overall README

Infrastructure

This package assumes certain infrastructure:

  • API Gateway - We expect all the routing to invoke the FHIR Works Lambda
  • Lambda - We expect the input to be entering our function in a certain way

Usage

For usage please add this package to your package.json file and install as a dependency. For usage examples please see the deployment component's package.json

Dependency tree

This package is dependent on a type of each subcomponent:

NOTE: if your use-case does not require one of the above features/components, please set the your configuration as such and the router will route accordingly

Known issues

For known issues please track the issues on the GitHub repository

Security

See CONTRIBUTING for more information.

License

This project is licensed under the Apache-2.0 License.

fhir-works-on-aws-routing's People

Contributors

allanhodkinson avatar amazon-auto avatar awsbakha avatar bingjiling avatar carvantes avatar chrisbednarski avatar dependabot[bot] avatar emilhdiaz avatar github-actions[bot] avatar jn1119 avatar justinusmenzel avatar kcadette avatar kosach avatar liquid36 avatar medhost-gkersting avatar nguyen102 avatar nisankep avatar organom avatar rsmayda avatar sanketd92 avatar ssvegaraju avatar zambonilli avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fhir-works-on-aws-routing's Issues

Missing Express types

Hi,
I'm hitting a transpile error when using the routing npm package without the other fhir-works components:

node_modules/fhir-works-on-aws-routing/lib/app.d.ts:2:119 - error TS2307: Cannot find module 'express-serve-static-core' or its corresponding type declarations.

2 export declare function generateServerlessRouter(fhirConfig: FhirConfig, supportedGenericResources: string[]): import("express-serve-static-core").Express; 

Just need to add @types/express-serve-static-core into the dependencies.
Thanks!
Allan

Create interaction without response causes runtime error

The return type of the persistence component create method is of type GenericResponse. The response element is optional, if it's not present we get an undefined runtime error from this line of code:

Solution is to test for existence of response before testing for for existence of response.meta.
I think that the Express response .send should work as expected if response is undefined.

GET returns 404 unless id param matches the case of the stored resource

FHIR resource ids are stored in a case sensitive way in dynamodb
When a resource is created via the POST operation with a lower case id, I am not able to retrieve it (via the GET) with an upper or mixed case id

To Reproduce
Steps to reproduce the behavior:

  1. POST to fhir/MedicationReqest using a lower case id
  2. GET fhir/MedicationReqest/upper case of the same id
  3. See Not Found error 404

Expected behavior
Resource is found and returned with status code 200

Versions (please complete the following information):

  • Release Version 6.1.1

Getting error "Cannot read property 'lookup' of undefined at ServerResponse.header"

Describe the bug

Getting a 500 response from the fhirserver when building with the mainline branch's code. The error below is what the fhirServer throws.

This seems like a dependency issue. When the setContentTypeMiddleware is called mime.chartset.loopkup() is failing inside the express module because mine.charset is undefined.

ERROR	Unhandled Error TypeError: Cannot read property 'lookup' of undefined
    at ServerResponse.header (/var/task/src/webpack:/node_modules/express/lib/response.js:771:1)
    at ServerResponse.contentType (/var/task/src/webpack:/node_modules/express/lib/response.js:604:1)
    at setContentTypeMiddleware (/var/task/src/webpack:/node_modules/fhir-works-on-aws-routing/lib/router/middlewares/setContentType.js:15:1)
    at Layer.handle [as handle_request] (/var/task/src/webpack:/node_modules/express/lib/router/layer.js:95:1)
    at trim_prefix (/var/task/src/webpack:/node_modules/express/lib/router/index.js:323:1)
    at /var/task/src/webpack:/node_modules/express/lib/router/index.js:284:1
    at Function.process_params (/var/task/src/webpack:/node_modules/express/lib/router/index.js:341:1)
    at next (/var/task/src/webpack:/node_modules/express/lib/router/index.js:275:1)
    at /var/task/src/webpack:/node_modules/fhir-works-on-aws-routing/lib/router/middlewares/setServerUrl.js:26:1
    at /var/task/src/webpack:/node_modules/fhir-works-on-aws-routing/lib/router/routes/routeHelper.js:16:1

To Reproduce
Steps to reproduce the behavior:
I am building fhirworks slightly differently than deployment package does by default.

couple callouts:

  • using npm install instead of yarn (lock files may be different that this repo)
  • still using serverless package to package the lambda code -- so hopefully no difference here.
  • I am using mainline branch for all packages except deployment. for deployment I am using smart-mainline.

After building this and deploying to AWS all requests to the fhirserver receive the above error
GET /tenant/{tenantId}/Patient a simple request should return the error.

Versions (please complete the following information):
Using mainline for all the packages except deployment. For deployment I am using smart-mainline

I plan to try building fhirworks with the default install.sh found in the deployment package to see if I get the same dependency issue. I am still trying to determine if this is caused by the way I am packaging the fhirServer or not.

change content-type to accept header

Hi!
I think that is better to check for de Accept header rather than the ContentType header. Accept header is about what the client expect.

req.headers['content-type'] === 'application/json' ? 'application/json' : 'application/fhir+json',

Particulary, i'm going throw ONC Certification, and the $export test expect to have an application/json response, not a application/fhir+josn response.

What do you think?

[Feature Request] Log cloudfront request headers for downstream (Goelocation) analytics

Is your feature request related to a problem? Please describe.

We have a need to perform downstream analytics on the requests made to fhirworks and as part of this analytics we need data around geolocation. API Gateway appears to have cloudfront headers available as part of the request and these cloudfront headers contain all the data we require.

Cloudfront request headers that we are interested in:
https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/using-cloudfront-headers.html

Describe the solution you'd like

  • Log request headers as part of routing package
  • Selectively log header values that are not sensitive in nature
  • Perhaps make this conditional logging based on an environment variable?

Describe alternatives you've considered

  • Using API gateway execution logs, but the 1024 byte limit truncated the request information
    This also logs the sensitive header attributes like JWT token
  • Using API gateway access logs, but these only appear to have access to the "context" object associated with the request coming to API gateway. The cloudfront headers do not appear to be accessible from this context object. See here: https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-logging-variables.html

[Bug] Resource Type in Reference Changed to Parent's Resource Type

Describe the bug
When a resource (in a bundle) with a reference that has a real id is saved to dynamodb, the resource type in the reference is replaced with the parent resource type. e.g. an EOB has a reference for Coverage with real id Coverage/195a13d1-2fdc-4c26-9fed-14993cffee6b. when the EOB is saved to ddb, the reference for the Coverage becomes ExplanationOfBenefit/195a13d1-2fdc-4c26-9fed-14993cffee6b

To Reproduce
Steps to reproduce the behavior:

  1. create a resource with a reference that has a real id
  2. save the resource through DynamoDbBundleService.transaction()

Expected behavior
the reference with a real id should not be changed

[Feature Request] Support resolving temporary bundle references in URI fields

#Is your feature request related to a problem? Please describe.
I would like to create FHIR resources via Bundle. There are two entries in the Bundle, and one entry references to another by uri type field. The problem is the uri type referencing is not supported.

Describe the solution you'd like
Support uri and url type field reference. Here is the PR link.

Describe alternatives you've considered
N/A

Additional context
This is a sample Bundle that contains uri type field - action.definitionUri.

{
    "resourceType": "Bundle",
    "type": "transaction",
    "entry": [
        {
        "resource": {
            "id": "1,
            "resourceType" : "PlanDefinition",
            "name" : "plan definition 1",
            "status" : "active",
            },
            "fullUrl": "https://us-west-2.amazonaws.com/dev/PlanDefinition/1",
            "request": {
                "method": "POST",
                "url": "PlanDefinition"
            }
        },
        {
            "resource": {
                "resourceType": "PlanDefinition",
                "name": "plan definition 2",
                "status": "active",
                "action": [
                    {
                        "definitionUri": "PlanDefinition/1"
                    }
                ],
                "id": "2"
            },
            "request": {
                "method": "POST",
                "url": "PlanDefinition"
            },
            "fullUrl": "https://us-west-2.amazonaws.com/dev/PlanDefinition/2"
        }
    ]
}

Adding custom logic, validation etc.

Hi,

Firstly, thanks so much for this project! Hoping I can get some advice on some custom logic scenarios.

We have some requirements that require some customization of the logic within the routing package (I think) and trying to work out how to do this. To give some examples:

  • Only allow one user to retrieve/view a resource at a time (only for certain types). Once a user "GET"s a resource that resource cannot be "GET" by any other user until the first user releases it or a timeout expires.
  • Support a different schema/profile (australian base profile +)
  • Validating that a resource referenced from a created resource contains certain data

Hope those cases make sense.

My thoughts for customising the logic we require include:

  • Extending the ResourceHandler class (CrudHandlerInterface)
  • Replacing the Validator class to add different schema
  • Replacement of GenericResourceRoute if there are instances where access to the express request/response is required?
  • Replace the generateServerlessRouter(), allows adding express middleware, customising the resourcehandler type etc.

Am I on the right track do you think?
How can I customize these without either replacing this entire package with my own version, or monkey patching this package? I guess writing our own version of generateServerlessRouter() would allow us to customize all this without modifying the package, but might add a headache of trying to keep the non-custom parts of the function in sync with the one in the package etc.

If it's not possible currently, are you open to PR's that allow, for example, passing a custom CrudHandlerInterface implementation via the FhirConfig?

Thanks for your help

Incorrect REST Security ValueSet in CapabilityStatement

According to Aegis Touchstone, the ValueSet in use in the CapabilityStatement to describe the system's rest security capabilities is incorrect. The ValueSet used in rest.security.service[].coding[].system should be http://hl7.org/fhir/ValueSet/restful-security-service.

Screen Shot 2021-02-22 at 12 18 35 AM

Support for PATCH

Hi,

We are looking at using PATCH functionality in our api and notice it's not fully supported in fhir-works yet. We have some idea's on how to implement this in fhir-works and will create a PR if you're happy with the solution.

First I note there is also an outstanding issue to add patch support in persistence-ddb awslabs/fhir-works-on-aws-persistence-ddb#6

Our idea is to add the patch functionality to the ResourceHandler. The patch function would become something like:

async patch(resourceType: string, id: string, resource: any) {
  const currentResource= await this.dataService.readResource({ resourceType, id });
  const patchedResource = jsonPatch.applyPatch(currentResponse.resource, resource).newDocument;
  
  return await update(resourceType, id, patchedResource);
}

Calling the existing update() function to update the resource ensures the validation rules are applied and should satisfy the fhir docs on patch

the server SHALL process its own copy of the resource in the format indicated, applying the operations specified in the document, following the relevant PATCH specification. When the operations have all been processed, the server processes the resulting document as an Update operation; all the version and error handling etc. apply as specified

If performing the patch in the persistence layer as per the above issue it would be more difficult to process validation etc. we think our solution above would be a better fit.

This would probably also result in the removal of patchResource() from the persistence interface as it would no longer be required, so this change may not be backward compatible.

Some changes would also be required in GenericResourceRoute for patch() where it performs some checks on the 'id' field in the body, which won't exist (at least not in a JSON patch spec document) so we'd fix this too, probably just replace it with a basic check that the body is an array.

What do you think?

Validation Errors on CapabilityStatement

Describe the bug
We use 'metadataRoute' to retrieve CapabilityStatement. The CapabilityStatement has these validation errors:

Validation of response body against profile 'http://hl7.org/fhir/StructureDefinition/CapabilityStatement' by FHIR specification's Validation Engine produced the following results: ERROR: The Coding references a value set, not a code system ("http://hl7.org/fhir/ValueSet/restful-security-service"). Location: CapabilityStatement.rest[0].security.service[0].coding[0] (line 1, col 1039). ERROR: Unknown Code System http://hl7.org/fhir/ValueSet/restful-security-service. Location: CapabilityStatement.rest[0].security.service[0].coding[0] (line 1, col 1039). ERROR: Search parameter names must be unique in the context of a resource. [searchParam.select(name).isDistinct()]. Location: CapabilityStatement.rest[0].resource[41] (line 1, col 350391). ERROR: Search parameter names must be unique in the context of a resource. [searchParam.select(name).isDistinct()]. Location: CapabilityStatement.rest[0].resource[43] (line 1, col 371006). ERROR: Search parameter names must be unique in the context of a resource. [searchParam.select(name).isDistinct()]. Location: CapabilityStatement.rest[0].resource[102] (line 1, col 841601).

Screenshots
Screen Shot 2021-07-27 at 3 56 03 PM

[Bug] When using $docref and having multiple documents in period it does not return the latest

Describe the bug
When using $docref with DocumentReference and having multiple documents with in the same period it does not return the latest, it will return the first with in that period.
Example Call: DocumentReference/$docref?patient=Patient/8aae785b-4228-45aa-b543-10dc79707ded

Expected behavior
It should return the latest document within that period for the DocumentReference.

Additional context
Document1 entered on 2021-09-16 for the period with a start of 2021-09-15.
Document2 entered on 2021-09-17 for the period with a start of 2021-09-15.

It will currently return Document1.

Currently the sort for the latest looks like
searchParams = { _sort: '-period', _count: '1', ...searchParams };

Bundle filtering for global operations

Hi AWS team,
In the current router implementation, the search-system & history-system operations don't make a call to this.authService.authorizeAndFilterReadResponse after the response Bundle has been formed. Is this by design or is it an omission?

Many thanks,
Allan

Support Bulk Upload

Is your feature request related to a problem? Please describe.
The Payer-to-Payer requirement allows a Member to authorize a Payer (the 'New' Payer) to access the user's data at another Payer (the 'Old' Payer). The most common use case is when a Member changes health plans, however, the Member changing plans is not a requirement. They could, for example, be part of two health plans.

The Payer-to-Payer requirement is vague on how this should work, particularly in how the Member would be able to grant the access, however, there are FHIR Server needs two capabilities we will need to implement this: Patient Everything, and Bulk Upload.

Describe the solution you'd like
Support Bulk Upload: Although the Patient Everything operation for an individual Patient is returned synchronously as a bundle, we are concerned that data accumulated over time for a Patient will grow large, and cause the API to time-out. For this reason, we are strongly considering the data be returned asynchronously for a bulk data upload. This would read newline-delimited records into the FHIR Server. Our preliminary design is to read the information from an S3 bucket using a signed URL with TTL.

Describe alternatives you've considered
Data could be extracted by calling all endpoints and combining the data.

Additional context
None.

Support for CORS headers

Hi AWS team,
For server integration with web services we need to supply CORS headers & support pre-flight requests. The HL7 spec says that FHIR servers SHOULD implement this see https://www.hl7.org/fhir/security.html#http

I've added a PR which adds this to the router (we've deployed this and tested with Postman & several web apps so we know it works!).

This is a basic implementation - the extension would be to add a cors config (e.g CorsOptions) into the server section in FhirConfig (https://github.com/awslabs/fhir-works-on-aws-interface) to allow middleware configuration if required.

For deployment purposes we also need to add an unauthorized OPTIONS route to the API gateway which routes to the deployment Lambda. So this is an update to the serverless template within https://github.com/awslabs/fhir-works-on-aws-deployment. We're not using the serverless framework so not sure how to do this.

Regards,
Allan

[Feature Request] MIME type application/fhir+json

Hi Robert & team,
One of our team members had a query today about the MIME type returned by the routing module, in that it is application/json rather than application/fhir+json as the specification suggests should be used (https://www.hl7.org/fhir/http.html#mime-type).

This is clearly not a show stopper as it's never been raised as an issue on here, or by any of our customers, but I'm wondering if you'd had any thoughts about this?

Many thanks,
Allan

Authorization errors should return OperationOutcome resources

HTTP 403 responses have a proprietary JSON body rather than a FHIR OperationOutcome resource.

Impacts

  • A FHIR client expecting a FHIR resource may not correctly interpret the response
  • This will force refactoring if content types other than JSON are used in the future (e.g. XML, RDF)

Source
Source: https://github.com/awslabs/fhir-works-on-aws-routing/blob/mainline/src/app.ts
Commit: d120da1

When the authorization.isAuthorized function returns false or throws an error (ln45) a response is provided directly (ln52, ln55)

A possible solution is to throw an http error which can be caught as an http error and wrapped in an OperationOutcome in the error handler: https://github.com/awslabs/fhir-works-on-aws-routing/blob/mainline/src/router/routes/errorHandling.ts.

Support Patient Everything

Is your feature request related to a problem? Please describe.
The Payer-to-Payer requirement allows a Member to authorize a Payer (the 'New' Payer) to access the user's data at another Payer (the 'Old' Payer). The most common use case is when a Member changes health plans, however, the Member changing plans is not a requirement. They could, for example, be part of two health plans.

The Payer-to-Payer requirement is vague on how this should work, particularly in how the Member would be able to grant the access, however, there are FHIR Server needs two capabilities we will need to implement this: Patient Everything, and Bulk Upload.

Describe the solution you'd like
Support Patient Everything: The Patient Everything operation extends the FHIR Patient Endpoint to allow requests for all patient data. The response is a bundle of type "searchset". At a minimum, the patient resource(s) itself is returned, along with any other resources that the server has that are related to the patient(s), and that are available for the given user.

When this operation is used to access multiple patient records at once, the return bundle could be rather a lot of data; servers may choose to require that such requests are made asynchronously, and associated with bulk data formats. The operation to access multiple patient records at once is not required for Payer to Payer.. The requirement states that a single patient should return data synchronously as a bundle, however, this may return thousands of records and potentially timeout -- an asynchronous operation should be strongly considered.

Our preliminary design is to write the information to an S3 bucket where it can be read using a signed URL with TTL.

Additionally, the OAUTH2 scopes must be used to determine which records will be returned. Typically, the scopes will provide access to the Clinical Records (e.g. Patient/Observation.read, etc) for the Patient and exclude Payment Records (Patient/ExplanationOfBenefit.read, etc.)

Describe alternatives you've considered
Data could be extracted by calling all endpoints and combining the data.

Additional context
None.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.