Merge remote-tracking branch 'remotes/origin/master' into ks-20191119-scheduler
This commit is contained in:
commit
f5c4c8e3e3
|
@ -46,7 +46,7 @@ import java.util.*;
|
||||||
public enum Pointcut {
|
public enum Pointcut {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <b>Registry Hook: </b>
|
* <b>Interceptor Framework Hook:</b>
|
||||||
* This pointcut will be called once when a given interceptor is registered
|
* This pointcut will be called once when a given interceptor is registered
|
||||||
*/
|
*/
|
||||||
INTERCEPTOR_REGISTERED(void.class),
|
INTERCEPTOR_REGISTERED(void.class),
|
||||||
|
@ -89,7 +89,7 @@ public enum Pointcut {
|
||||||
),
|
),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <b>Server Hook: </b>
|
* <b>Server Hook:</b>
|
||||||
* This hook is called before any other processing takes place for each incoming request. It may be used to provide
|
* This hook is called before any other processing takes place for each incoming request. It may be used to provide
|
||||||
* alternate handling for some requests, or to screen requests before they are handled, etc.
|
* alternate handling for some requests, or to screen requests before they are handled, etc.
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -117,10 +117,10 @@ public enum Pointcut {
|
||||||
),
|
),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <b>Server Hook: </b>
|
* <b>Server Hook:</b>
|
||||||
* This hook is invoked upon any exception being thrown within the server's request processing code. This includes
|
* This hook is invoked upon any exception being thrown within the server's request processing code. This includes
|
||||||
* any exceptions thrown within resource provider methods (e.g. {@link Search} and {@link Read} methods) as well as
|
* any exceptions thrown within resource provider methods (e.g. {@link Search} and {@link Read} methods) as well as
|
||||||
* any runtime exceptions thrown by the server itself. This also includes any {@link AuthenticationException}s
|
* any runtime exceptions thrown by the server itself. This also includes any {@link AuthenticationException}
|
||||||
* thrown.
|
* thrown.
|
||||||
* <p>
|
* <p>
|
||||||
* Hooks may accept the following parameters:
|
* Hooks may accept the following parameters:
|
||||||
|
@ -543,6 +543,7 @@ public enum Pointcut {
|
||||||
),
|
),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* <b>Subscription Hook:</b>
|
||||||
* Invoked whenever a persisted resource has been modified and is being submitted to the
|
* Invoked whenever a persisted resource has been modified and is being submitted to the
|
||||||
* subscription processing pipeline. This method is called before the resource is placed
|
* subscription processing pipeline. This method is called before the resource is placed
|
||||||
* on any queues for processing and executes synchronously during the resource modification
|
* on any queues for processing and executes synchronously during the resource modification
|
||||||
|
@ -563,6 +564,7 @@ public enum Pointcut {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* <b>Subscription Hook:</b>
|
||||||
* Invoked any time that a resource is matched by an individual subscription, and
|
* Invoked any time that a resource is matched by an individual subscription, and
|
||||||
* is about to be queued for delivery.
|
* is about to be queued for delivery.
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -585,6 +587,7 @@ public enum Pointcut {
|
||||||
SUBSCRIPTION_RESOURCE_MATCHED(boolean.class, "ca.uhn.fhir.jpa.subscription.module.CanonicalSubscription", "ca.uhn.fhir.jpa.subscription.module.subscriber.ResourceDeliveryMessage", "ca.uhn.fhir.jpa.searchparam.matcher.InMemoryMatchResult"),
|
SUBSCRIPTION_RESOURCE_MATCHED(boolean.class, "ca.uhn.fhir.jpa.subscription.module.CanonicalSubscription", "ca.uhn.fhir.jpa.subscription.module.subscriber.ResourceDeliveryMessage", "ca.uhn.fhir.jpa.searchparam.matcher.InMemoryMatchResult"),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* <b>Subscription Hook:</b>
|
||||||
* Invoked whenever a persisted resource was checked against all active subscriptions, and did not
|
* Invoked whenever a persisted resource was checked against all active subscriptions, and did not
|
||||||
* match any.
|
* match any.
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -600,6 +603,7 @@ public enum Pointcut {
|
||||||
SUBSCRIPTION_RESOURCE_DID_NOT_MATCH_ANY_SUBSCRIPTIONS(void.class, "ca.uhn.fhir.jpa.subscription.module.ResourceModifiedMessage"),
|
SUBSCRIPTION_RESOURCE_DID_NOT_MATCH_ANY_SUBSCRIPTIONS(void.class, "ca.uhn.fhir.jpa.subscription.module.ResourceModifiedMessage"),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* <b>Subscription Hook:</b>
|
||||||
* Invoked immediately before the delivery of a subscription, and right before any channel-specific
|
* Invoked immediately before the delivery of a subscription, and right before any channel-specific
|
||||||
* hooks are invoked (e.g. {@link #SUBSCRIPTION_BEFORE_REST_HOOK_DELIVERY}.
|
* hooks are invoked (e.g. {@link #SUBSCRIPTION_BEFORE_REST_HOOK_DELIVERY}.
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -621,6 +625,7 @@ public enum Pointcut {
|
||||||
SUBSCRIPTION_BEFORE_DELIVERY(boolean.class, "ca.uhn.fhir.jpa.subscription.module.CanonicalSubscription", "ca.uhn.fhir.jpa.subscription.module.subscriber.ResourceDeliveryMessage"),
|
SUBSCRIPTION_BEFORE_DELIVERY(boolean.class, "ca.uhn.fhir.jpa.subscription.module.CanonicalSubscription", "ca.uhn.fhir.jpa.subscription.module.subscriber.ResourceDeliveryMessage"),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* <b>Subscription Hook:</b>
|
||||||
* Invoked immediately after the delivery of a subscription, and right before any channel-specific
|
* Invoked immediately after the delivery of a subscription, and right before any channel-specific
|
||||||
* hooks are invoked (e.g. {@link #SUBSCRIPTION_AFTER_REST_HOOK_DELIVERY}.
|
* hooks are invoked (e.g. {@link #SUBSCRIPTION_AFTER_REST_HOOK_DELIVERY}.
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -638,6 +643,7 @@ public enum Pointcut {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* <b>Subscription Hook:</b>
|
||||||
* Invoked immediately after the attempted delivery of a subscription, if the delivery
|
* Invoked immediately after the attempted delivery of a subscription, if the delivery
|
||||||
* failed.
|
* failed.
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -660,6 +666,7 @@ public enum Pointcut {
|
||||||
SUBSCRIPTION_AFTER_DELIVERY_FAILED(boolean.class, "ca.uhn.fhir.jpa.subscription.module.subscriber.ResourceDeliveryMessage", "java.lang.Exception"),
|
SUBSCRIPTION_AFTER_DELIVERY_FAILED(boolean.class, "ca.uhn.fhir.jpa.subscription.module.subscriber.ResourceDeliveryMessage", "java.lang.Exception"),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* <b>Subscription Hook:</b>
|
||||||
* Invoked immediately after the delivery of a REST HOOK subscription.
|
* Invoked immediately after the delivery of a REST HOOK subscription.
|
||||||
* <p>
|
* <p>
|
||||||
* When this hook is called, all processing is complete so this hook should not
|
* When this hook is called, all processing is complete so this hook should not
|
||||||
|
@ -677,6 +684,7 @@ public enum Pointcut {
|
||||||
SUBSCRIPTION_AFTER_REST_HOOK_DELIVERY(void.class, "ca.uhn.fhir.jpa.subscription.module.CanonicalSubscription", "ca.uhn.fhir.jpa.subscription.module.subscriber.ResourceDeliveryMessage"),
|
SUBSCRIPTION_AFTER_REST_HOOK_DELIVERY(void.class, "ca.uhn.fhir.jpa.subscription.module.CanonicalSubscription", "ca.uhn.fhir.jpa.subscription.module.subscriber.ResourceDeliveryMessage"),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* <b>Subscription Hook:</b>
|
||||||
* Invoked immediately before the delivery of a REST HOOK subscription.
|
* Invoked immediately before the delivery of a REST HOOK subscription.
|
||||||
* <p>
|
* <p>
|
||||||
* Hooks may make changes to the delivery payload, or make changes to the
|
* Hooks may make changes to the delivery payload, or make changes to the
|
||||||
|
@ -697,6 +705,7 @@ public enum Pointcut {
|
||||||
SUBSCRIPTION_BEFORE_REST_HOOK_DELIVERY(boolean.class, "ca.uhn.fhir.jpa.subscription.module.CanonicalSubscription", "ca.uhn.fhir.jpa.subscription.module.subscriber.ResourceDeliveryMessage"),
|
SUBSCRIPTION_BEFORE_REST_HOOK_DELIVERY(boolean.class, "ca.uhn.fhir.jpa.subscription.module.CanonicalSubscription", "ca.uhn.fhir.jpa.subscription.module.subscriber.ResourceDeliveryMessage"),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* <b>Subscription Hook:</b>
|
||||||
* Invoked whenever a persisted resource (a resource that has just been stored in the
|
* Invoked whenever a persisted resource (a resource that has just been stored in the
|
||||||
* database via a create/update/patch/etc.) is about to be checked for whether any subscriptions
|
* database via a create/update/patch/etc.) is about to be checked for whether any subscriptions
|
||||||
* were triggered as a result of the operation.
|
* were triggered as a result of the operation.
|
||||||
|
@ -716,6 +725,7 @@ public enum Pointcut {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* <b>Subscription Hook:</b>
|
||||||
* Invoked whenever a persisted resource (a resource that has just been stored in the
|
* Invoked whenever a persisted resource (a resource that has just been stored in the
|
||||||
* database via a create/update/patch/etc.) has been checked for whether any subscriptions
|
* database via a create/update/patch/etc.) has been checked for whether any subscriptions
|
||||||
* were triggered as a result of the operation.
|
* were triggered as a result of the operation.
|
||||||
|
@ -733,6 +743,7 @@ public enum Pointcut {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* <b>Subscription Hook:</b>
|
||||||
* Invoked immediately after an active subscription is "registered". In HAPI FHIR, when
|
* Invoked immediately after an active subscription is "registered". In HAPI FHIR, when
|
||||||
* a subscription
|
* a subscription
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -752,6 +763,7 @@ public enum Pointcut {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* <b>Storage Hook:</b>
|
||||||
* Invoked when a resource is being deleted in a cascaded delete. This means that
|
* Invoked when a resource is being deleted in a cascaded delete. This means that
|
||||||
* some other resource is being deleted, but per use request or other
|
* some other resource is being deleted, but per use request or other
|
||||||
* policy, the given resource (the one supplied as a parameter to this hook)
|
* policy, the given resource (the one supplied as a parameter to this hook)
|
||||||
|
@ -797,6 +809,7 @@ public enum Pointcut {
|
||||||
),
|
),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* <b>Storage Hook:</b>
|
||||||
* Invoked when one or more resources may be returned to the user, whether as a part of a READ,
|
* Invoked when one or more resources may be returned to the user, whether as a part of a READ,
|
||||||
* a SEARCH, or even as the response to a CREATE/UPDATE, etc.
|
* a SEARCH, or even as the response to a CREATE/UPDATE, etc.
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -843,6 +856,7 @@ public enum Pointcut {
|
||||||
),
|
),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* <b>Storage Hook:</b>
|
||||||
* Invoked when the storage engine is about to check for the existence of a pre-cached search
|
* Invoked when the storage engine is about to check for the existence of a pre-cached search
|
||||||
* whose results match the given search parameters.
|
* whose results match the given search parameters.
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -880,6 +894,7 @@ public enum Pointcut {
|
||||||
),
|
),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* <b>Storage Hook:</b>
|
||||||
* Invoked when a search is starting, prior to creating a record for the search.
|
* Invoked when a search is starting, prior to creating a record for the search.
|
||||||
* <p>
|
* <p>
|
||||||
* Hooks may accept the following parameters:
|
* Hooks may accept the following parameters:
|
||||||
|
@ -915,6 +930,7 @@ public enum Pointcut {
|
||||||
),
|
),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* <b>Storage Hook:</b>
|
||||||
* Invoked when one or more resources may be returned to the user, whether as a part of a READ,
|
* Invoked when one or more resources may be returned to the user, whether as a part of a READ,
|
||||||
* a SEARCH, or even as the response to a CREATE/UPDATE, etc.
|
* a SEARCH, or even as the response to a CREATE/UPDATE, etc.
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -963,6 +979,7 @@ public enum Pointcut {
|
||||||
),
|
),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* <b>Storage Hook:</b>
|
||||||
* Invoked before a resource will be created, immediately before the resource
|
* Invoked before a resource will be created, immediately before the resource
|
||||||
* is persisted to the database.
|
* is persisted to the database.
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -998,6 +1015,7 @@ public enum Pointcut {
|
||||||
),
|
),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* <b>Storage Hook:</b>
|
||||||
* Invoked before a resource will be updated, immediately before the resource
|
* Invoked before a resource will be updated, immediately before the resource
|
||||||
* is persisted to the database.
|
* is persisted to the database.
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -1036,6 +1054,7 @@ public enum Pointcut {
|
||||||
),
|
),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* <b>Storage Hook:</b>
|
||||||
* Invoked before a resource will be created, immediately before the resource
|
* Invoked before a resource will be created, immediately before the resource
|
||||||
* is persisted to the database.
|
* is persisted to the database.
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -1072,6 +1091,7 @@ public enum Pointcut {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* <b>Storage Hook:</b>
|
||||||
* Invoked before a resource will be created, immediately before the transaction
|
* Invoked before a resource will be created, immediately before the transaction
|
||||||
* is committed (after all validation and other business rules have successfully
|
* is committed (after all validation and other business rules have successfully
|
||||||
* completed, and any other database activity is complete.
|
* completed, and any other database activity is complete.
|
||||||
|
@ -1109,6 +1129,7 @@ public enum Pointcut {
|
||||||
),
|
),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* <b>Storage Hook:</b>
|
||||||
* Invoked before a resource will be updated, immediately before the transaction
|
* Invoked before a resource will be updated, immediately before the transaction
|
||||||
* is committed (after all validation and other business rules have successfully
|
* is committed (after all validation and other business rules have successfully
|
||||||
* completed, and any other database activity is complete.
|
* completed, and any other database activity is complete.
|
||||||
|
@ -1149,6 +1170,7 @@ public enum Pointcut {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* <b>Storage Hook:</b>
|
||||||
* Invoked before a resource will be created
|
* Invoked before a resource will be created
|
||||||
* <p>
|
* <p>
|
||||||
* Hooks will have access to the contents of the resource being deleted
|
* Hooks will have access to the contents of the resource being deleted
|
||||||
|
@ -1182,6 +1204,7 @@ public enum Pointcut {
|
||||||
),
|
),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* <b>Storage Hook:</b>
|
||||||
* Invoked when a resource delete operation is about to fail due to referential integrity conflicts.
|
* Invoked when a resource delete operation is about to fail due to referential integrity conflicts.
|
||||||
* <p>
|
* <p>
|
||||||
* Hooks will have access to the list of resources that have references to the resource being deleted.
|
* Hooks will have access to the list of resources that have references to the resource being deleted.
|
||||||
|
@ -1219,6 +1242,7 @@ public enum Pointcut {
|
||||||
),
|
),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* <b>Storage Hook:</b>
|
||||||
* Invoked before a resource is about to be expunged via the <code>$expunge</code> operation.
|
* Invoked before a resource is about to be expunged via the <code>$expunge</code> operation.
|
||||||
* <p>
|
* <p>
|
||||||
* Hooks will be passed a reference to a counter containing the current number of records that have been deleted.
|
* Hooks will be passed a reference to a counter containing the current number of records that have been deleted.
|
||||||
|
@ -1261,7 +1285,8 @@ public enum Pointcut {
|
||||||
),
|
),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoked before expungeEverything is called.
|
* <b>Storage Hook:</b>
|
||||||
|
* Invoked before an <code>$expunge</code> operation on all data (expungeEverything) is called.
|
||||||
* <p>
|
* <p>
|
||||||
* Hooks will be passed a reference to a counter containing the current number of records that have been deleted.
|
* Hooks will be passed a reference to a counter containing the current number of records that have been deleted.
|
||||||
* If the hook deletes any records, the hook is expected to increment this counter by the number of records deleted.
|
* If the hook deletes any records, the hook is expected to increment this counter by the number of records deleted.
|
||||||
|
@ -1297,12 +1322,13 @@ public enum Pointcut {
|
||||||
),
|
),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Note that this is a performance tracing hook. Use with caution in production
|
* <b>Performance Tracing Hook:</b>
|
||||||
* systems, since calling it may (or may not) carry a cost.
|
|
||||||
* <p>
|
|
||||||
* This hook is invoked when any informational messages generated by the
|
* This hook is invoked when any informational messages generated by the
|
||||||
* SearchCoordinator are created. It is typically used to provide logging
|
* SearchCoordinator are created. It is typically used to provide logging
|
||||||
* or capture details related to a specific request.
|
* or capture details related to a specific request.
|
||||||
|
* <p>
|
||||||
|
* Note that this is a performance tracing hook. Use with caution in production
|
||||||
|
* systems, since calling it may (or may not) carry a cost.
|
||||||
* </p>
|
* </p>
|
||||||
* Hooks may accept the following parameters:
|
* Hooks may accept the following parameters:
|
||||||
* <ul>
|
* <ul>
|
||||||
|
@ -1334,12 +1360,13 @@ public enum Pointcut {
|
||||||
),
|
),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Note that this is a performance tracing hook. Use with caution in production
|
* <b>Performance Tracing Hook:</b>
|
||||||
* systems, since calling it may (or may not) carry a cost.
|
|
||||||
* <p>
|
|
||||||
* This hook is invoked when any warning messages generated by the
|
* This hook is invoked when any warning messages generated by the
|
||||||
* SearchCoordinator are created. It is typically used to provide logging
|
* SearchCoordinator are created. It is typically used to provide logging
|
||||||
* or capture details related to a specific request.
|
* or capture details related to a specific request.
|
||||||
|
* <p>
|
||||||
|
* Note that this is a performance tracing hook. Use with caution in production
|
||||||
|
* systems, since calling it may (or may not) carry a cost.
|
||||||
* </p>
|
* </p>
|
||||||
* Hooks may accept the following parameters:
|
* Hooks may accept the following parameters:
|
||||||
* <ul>
|
* <ul>
|
||||||
|
@ -1371,12 +1398,13 @@ public enum Pointcut {
|
||||||
),
|
),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Note that this is a performance tracing hook. Use with caution in production
|
* <b>Performance Tracing Hook:</b>
|
||||||
* systems, since calling it may (or may not) carry a cost.
|
|
||||||
* <p>
|
|
||||||
* This hook is invoked when a search has returned the very first result
|
* This hook is invoked when a search has returned the very first result
|
||||||
* from the database. The timing on this call can be a good indicator of how
|
* from the database. The timing on this call can be a good indicator of how
|
||||||
* performant a query is in general.
|
* performant a query is in general.
|
||||||
|
* <p>
|
||||||
|
* Note that this is a performance tracing hook. Use with caution in production
|
||||||
|
* systems, since calling it may (or may not) carry a cost.
|
||||||
* </p>
|
* </p>
|
||||||
* Hooks may accept the following parameters:
|
* Hooks may accept the following parameters:
|
||||||
* <ul>
|
* <ul>
|
||||||
|
@ -1409,14 +1437,15 @@ public enum Pointcut {
|
||||||
),
|
),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Note that this is a performance tracing hook. Use with caution in production
|
* <b>Performance Tracing Hook:</b>
|
||||||
* systems, since calling it may (or may not) carry a cost.
|
|
||||||
* <p>
|
|
||||||
* This hook is invoked when an individual search query SQL SELECT statement
|
* This hook is invoked when an individual search query SQL SELECT statement
|
||||||
* has completed and no more results are available from that query. Note that this
|
* has completed and no more results are available from that query. Note that this
|
||||||
* doesn't necessarily mean that no more matching results exist in the database,
|
* doesn't necessarily mean that no more matching results exist in the database,
|
||||||
* since HAPI FHIR JPA batch loads results in to the query cache in chunks in order
|
* since HAPI FHIR JPA batch loads results in to the query cache in chunks in order
|
||||||
* to provide predicable results without overloading memory or the database.
|
* to provide predicable results without overloading memory or the database.
|
||||||
|
* <p>
|
||||||
|
* Note that this is a performance tracing hook. Use with caution in production
|
||||||
|
* systems, since calling it may (or may not) carry a cost.
|
||||||
* </p>
|
* </p>
|
||||||
* Hooks may accept the following parameters:
|
* Hooks may accept the following parameters:
|
||||||
* <ul>
|
* <ul>
|
||||||
|
@ -1450,11 +1479,12 @@ public enum Pointcut {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Note that this is a performance tracing hook. Use with caution in production
|
* <b>Performance Tracing Hook:</b>
|
||||||
* systems, since calling it may (or may not) carry a cost.
|
|
||||||
* <p>
|
|
||||||
* This hook is invoked when a search has failed for any reason. When this pointcut
|
* This hook is invoked when a search has failed for any reason. When this pointcut
|
||||||
* is invoked, the search has completed unsuccessfully and will not be continued.
|
* is invoked, the search has completed unsuccessfully and will not be continued.
|
||||||
|
* <p>
|
||||||
|
* Note that this is a performance tracing hook. Use with caution in production
|
||||||
|
* systems, since calling it may (or may not) carry a cost.
|
||||||
* </p>
|
* </p>
|
||||||
* Hooks may accept the following parameters:
|
* Hooks may accept the following parameters:
|
||||||
* <ul>
|
* <ul>
|
||||||
|
@ -1487,13 +1517,14 @@ public enum Pointcut {
|
||||||
),
|
),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Note that this is a performance tracing hook. Use with caution in production
|
* <b>Performance Tracing Hook:</b>
|
||||||
* systems, since calling it may (or may not) carry a cost.
|
|
||||||
* <p>
|
|
||||||
* This hook is invoked when a search has failed for any reason. When this pointcut
|
* This hook is invoked when a search has failed for any reason. When this pointcut
|
||||||
* is invoked, a pass in the Search Coordinator has completed successfully, but
|
* is invoked, a pass in the Search Coordinator has completed successfully, but
|
||||||
* not all possible resources have been loaded yet so a future paging request
|
* not all possible resources have been loaded yet so a future paging request
|
||||||
* may trigger a new task that will load further resources.
|
* may trigger a new task that will load further resources.
|
||||||
|
* <p>
|
||||||
|
* Note that this is a performance tracing hook. Use with caution in production
|
||||||
|
* systems, since calling it may (or may not) carry a cost.
|
||||||
* </p>
|
* </p>
|
||||||
* Hooks may accept the following parameters:
|
* Hooks may accept the following parameters:
|
||||||
* <ul>
|
* <ul>
|
||||||
|
@ -1526,9 +1557,14 @@ public enum Pointcut {
|
||||||
),
|
),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* <b>Performance Tracing Hook:</b>
|
||||||
* Invoked when the storage engine is about to reuse the results of
|
* Invoked when the storage engine is about to reuse the results of
|
||||||
* a previously cached search.
|
* a previously cached search.
|
||||||
* <p>
|
* <p>
|
||||||
|
* Note that this is a performance tracing hook. Use with caution in production
|
||||||
|
* systems, since calling it may (or may not) carry a cost.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
* Hooks may accept the following parameters:
|
* Hooks may accept the following parameters:
|
||||||
* </p>
|
* </p>
|
||||||
* <ul>
|
* <ul>
|
||||||
|
@ -1561,12 +1597,13 @@ public enum Pointcut {
|
||||||
),
|
),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Note that this is a performance tracing hook. Use with caution in production
|
* <b>Performance Tracing Hook:</b>
|
||||||
* systems, since calling it may (or may not) carry a cost.
|
|
||||||
* <p>
|
|
||||||
* This hook is invoked when a search has failed for any reason. When this pointcut
|
* This hook is invoked when a search has failed for any reason. When this pointcut
|
||||||
* is invoked, a pass in the Search Coordinator has completed successfully, and all
|
* is invoked, a pass in the Search Coordinator has completed successfully, and all
|
||||||
* possible results have been fetched and loaded into the query cache.
|
* possible results have been fetched and loaded into the query cache.
|
||||||
|
* <p>
|
||||||
|
* Note that this is a performance tracing hook. Use with caution in production
|
||||||
|
* systems, since calling it may (or may not) carry a cost.
|
||||||
* </p>
|
* </p>
|
||||||
* Hooks may accept the following parameters:
|
* Hooks may accept the following parameters:
|
||||||
* <ul>
|
* <ul>
|
||||||
|
@ -1600,14 +1637,20 @@ public enum Pointcut {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* THIS IS AN EXPERIMENTAL HOOK AND MAY BE REMOVED OR CHANGED WITHOUT WARNING.
|
* <b>Performance Tracing Hook:</b>
|
||||||
*
|
|
||||||
* Note that this is a performance tracing hook. Use with caution in production
|
|
||||||
* systems, since calling it may (or may not) carry a cost.
|
|
||||||
* <p>
|
* <p>
|
||||||
* This hook is invoked when a search has found an individual ID.
|
* This hook is invoked when a search has found an individual ID.
|
||||||
* </p>
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* THIS IS AN EXPERIMENTAL HOOK AND MAY BE REMOVED OR CHANGED WITHOUT WARNING.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* Note that this is a performance tracing hook. Use with caution in production
|
||||||
|
* systems, since calling it may (or may not) carry a cost.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
* Hooks may accept the following parameters:
|
* Hooks may accept the following parameters:
|
||||||
|
* </p>
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>
|
* <li>
|
||||||
* java.lang.Integer - The query ID
|
* java.lang.Integer - The query ID
|
||||||
|
@ -1627,13 +1670,16 @@ public enum Pointcut {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Note that this is a performance tracing hook. Use with caution in production
|
* <b>Performance Tracing Hook:</b>
|
||||||
* systems, since calling it may (or may not) carry a cost.
|
|
||||||
* <p>
|
|
||||||
* This hook is invoked when a query has executed, and includes the raw SQL
|
* This hook is invoked when a query has executed, and includes the raw SQL
|
||||||
* statements that were executed against the database.
|
* statements that were executed against the database.
|
||||||
|
* <p>
|
||||||
|
* Note that this is a performance tracing hook. Use with caution in production
|
||||||
|
* systems, since calling it may (or may not) carry a cost.
|
||||||
* </p>
|
* </p>
|
||||||
|
* <p>
|
||||||
* Hooks may accept the following parameters:
|
* Hooks may accept the following parameters:
|
||||||
|
* </p>
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>
|
* <li>
|
||||||
* ca.uhn.fhir.rest.api.server.RequestDetails - A bean containing details about the request that is about to be processed, including details such as the
|
* ca.uhn.fhir.rest.api.server.RequestDetails - A bean containing details about the request that is about to be processed, including details such as the
|
||||||
|
|
|
@ -139,7 +139,7 @@ public interface IGenericClient extends IRestfulClient {
|
||||||
* Register a new interceptor for this client. An interceptor can be used to add additional logging, or add security headers, or pre-process responses, etc.
|
* Register a new interceptor for this client. An interceptor can be used to add additional logging, or add security headers, or pre-process responses, etc.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
void registerInterceptor(IClientInterceptor theInterceptor);
|
void registerInterceptor(Object theInterceptor);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Search for resources matching a given set of criteria. Searching is a very powerful
|
* Search for resources matching a given set of criteria. Searching is a very powerful
|
||||||
|
@ -168,10 +168,10 @@ public interface IGenericClient extends IRestfulClient {
|
||||||
ITransaction transaction();
|
ITransaction transaction();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove an intercaptor that was previously registered using {@link IRestfulClient#registerInterceptor(IClientInterceptor)}
|
* Remove an intercaptor that was previously registered using {@link IRestfulClient#registerInterceptor(Object)}
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
void unregisterInterceptor(IClientInterceptor theInterceptor);
|
void unregisterInterceptor(Object theInterceptor);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fluent method for the "update" operation, which performs a logical delete on a server resource
|
* Fluent method for the "update" operation, which performs a logical delete on a server resource
|
||||||
|
|
|
@ -97,7 +97,7 @@ public interface IRestfulClient {
|
||||||
* <code>getInterceptorService().registerInterceptor(theInterceptor)</code>
|
* <code>getInterceptorService().registerInterceptor(theInterceptor)</code>
|
||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
void registerInterceptor(IClientInterceptor theInterceptor);
|
void registerInterceptor(Object theInterceptor);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies that the client should request that the server respond with "pretty printing"
|
* Specifies that the client should request that the server respond with "pretty printing"
|
||||||
|
@ -115,13 +115,13 @@ public interface IRestfulClient {
|
||||||
void setSummary(SummaryEnum theSummary);
|
void setSummary(SummaryEnum theSummary);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove an interceptor that was previously registered using {@link IRestfulClient#registerInterceptor(IClientInterceptor)}.
|
* Remove an interceptor that was previously registered using {@link IRestfulClient#registerInterceptor(Object)}.
|
||||||
* <p>
|
* <p>
|
||||||
* This is a convenience method for performing the following call:
|
* This is a convenience method for performing the following call:
|
||||||
* <code>getInterceptorService().unregisterInterceptor(theInterceptor)</code>
|
* <code>getInterceptorService().unregisterInterceptor(theInterceptor)</code>
|
||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
void unregisterInterceptor(IClientInterceptor theInterceptor);
|
void unregisterInterceptor(Object theInterceptor);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures what style of _format parameter should be used in requests
|
* Configures what style of _format parameter should be used in requests
|
||||||
|
|
|
@ -32,6 +32,7 @@ import ca.uhn.fhir.rest.client.api.*;
|
||||||
import ca.uhn.fhir.rest.client.exceptions.FhirClientConnectionException;
|
import ca.uhn.fhir.rest.client.exceptions.FhirClientConnectionException;
|
||||||
import ca.uhn.fhir.rest.client.exceptions.InvalidResponseException;
|
import ca.uhn.fhir.rest.client.exceptions.InvalidResponseException;
|
||||||
import ca.uhn.fhir.rest.client.exceptions.NonFhirResponseException;
|
import ca.uhn.fhir.rest.client.exceptions.NonFhirResponseException;
|
||||||
|
import ca.uhn.fhir.rest.client.interceptor.AdditionalRequestHeadersInterceptor;
|
||||||
import ca.uhn.fhir.rest.client.method.HttpGetClientInvocation;
|
import ca.uhn.fhir.rest.client.method.HttpGetClientInvocation;
|
||||||
import ca.uhn.fhir.rest.client.method.IClientResponseHandler;
|
import ca.uhn.fhir.rest.client.method.IClientResponseHandler;
|
||||||
import ca.uhn.fhir.rest.client.method.IClientResponseHandlerHandlesBinary;
|
import ca.uhn.fhir.rest.client.method.IClientResponseHandlerHandlesBinary;
|
||||||
|
@ -137,7 +138,7 @@ public abstract class BaseClient implements IRestfulClient {
|
||||||
@Override
|
@Override
|
||||||
public <T extends IBaseResource> T fetchResourceFromUrl(Class<T> theResourceType, String theUrl) {
|
public <T extends IBaseResource> T fetchResourceFromUrl(Class<T> theResourceType, String theUrl) {
|
||||||
BaseHttpClientInvocation clientInvocation = new HttpGetClientInvocation(getFhirContext(), theUrl);
|
BaseHttpClientInvocation clientInvocation = new HttpGetClientInvocation(getFhirContext(), theUrl);
|
||||||
ResourceResponseHandler<T> binding = new ResourceResponseHandler<T>(theResourceType);
|
ResourceResponseHandler<T> binding = new ResourceResponseHandler<>(theResourceType);
|
||||||
return invokeClient(getFhirContext(), binding, clientInvocation, null, false, false, null, null, null, null, null);
|
return invokeClient(getFhirContext(), binding, clientInvocation, null, false, false, null, null, null, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -274,21 +275,13 @@ public abstract class BaseClient implements IRestfulClient {
|
||||||
addToCacheControlHeader(b, Constants.CACHE_CONTROL_NO_CACHE, theCacheControlDirective.isNoCache());
|
addToCacheControlHeader(b, Constants.CACHE_CONTROL_NO_CACHE, theCacheControlDirective.isNoCache());
|
||||||
addToCacheControlHeader(b, Constants.CACHE_CONTROL_NO_STORE, theCacheControlDirective.isNoStore());
|
addToCacheControlHeader(b, Constants.CACHE_CONTROL_NO_STORE, theCacheControlDirective.isNoStore());
|
||||||
if (theCacheControlDirective.getMaxResults() != null) {
|
if (theCacheControlDirective.getMaxResults() != null) {
|
||||||
addToCacheControlHeader(b, Constants.CACHE_CONTROL_MAX_RESULTS + "=" + Integer.toString(theCacheControlDirective.getMaxResults().intValue()), true);
|
addToCacheControlHeader(b, Constants.CACHE_CONTROL_MAX_RESULTS + "=" + theCacheControlDirective.getMaxResults().intValue(), true);
|
||||||
}
|
}
|
||||||
if (b.length() > 0) {
|
if (b.length() > 0) {
|
||||||
httpRequest.addHeader(Constants.HEADER_CACHE_CONTROL, b.toString());
|
httpRequest.addHeader(Constants.HEADER_CACHE_CONTROL, b.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (theCustomHeaders != null) {
|
|
||||||
for (Map.Entry<String, List<String>> customHeader: theCustomHeaders.entrySet()) {
|
|
||||||
for (String value: customHeader.getValue()) {
|
|
||||||
httpRequest.addHeader(customHeader.getKey(), value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (theLogRequestAndResponse) {
|
if (theLogRequestAndResponse) {
|
||||||
ourLog.info("Client invoking: {}", httpRequest);
|
ourLog.info("Client invoking: {}", httpRequest);
|
||||||
String body = httpRequest.getRequestBodyFromStream();
|
String body = httpRequest.getRequestBodyFromStream();
|
||||||
|
@ -297,6 +290,11 @@ public abstract class BaseClient implements IRestfulClient {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (theCustomHeaders != null) {
|
||||||
|
AdditionalRequestHeadersInterceptor interceptor = new AdditionalRequestHeadersInterceptor(theCustomHeaders);
|
||||||
|
interceptor.interceptRequest(httpRequest);
|
||||||
|
}
|
||||||
|
|
||||||
HookParams requestParams = new HookParams();
|
HookParams requestParams = new HookParams();
|
||||||
requestParams.add(IHttpRequest.class, httpRequest);
|
requestParams.add(IHttpRequest.class, httpRequest);
|
||||||
getInterceptorService().callHooks(Pointcut.CLIENT_REQUEST, requestParams);
|
getInterceptorService().callHooks(Pointcut.CLIENT_REQUEST, requestParams);
|
||||||
|
@ -458,7 +456,7 @@ public abstract class BaseClient implements IRestfulClient {
|
||||||
if (StringUtils.isNotBlank(responseString)) {
|
if (StringUtils.isNotBlank(responseString)) {
|
||||||
ourLog.info("Client response: {}\n{}", message, responseString);
|
ourLog.info("Client response: {}\n{}", message, responseString);
|
||||||
} else {
|
} else {
|
||||||
ourLog.info("Client response: {}", message, responseString);
|
ourLog.info("Client response: {}", message);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ourLog.trace("FHIR response:\n{}\n{}", response, responseString);
|
ourLog.trace("FHIR response:\n{}\n{}", response, responseString);
|
||||||
|
@ -466,7 +464,7 @@ public abstract class BaseClient implements IRestfulClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void registerInterceptor(IClientInterceptor theInterceptor) {
|
public void registerInterceptor(Object theInterceptor) {
|
||||||
Validate.notNull(theInterceptor, "Interceptor can not be null");
|
Validate.notNull(theInterceptor, "Interceptor can not be null");
|
||||||
getInterceptorService().registerInterceptor(theInterceptor);
|
getInterceptorService().registerInterceptor(theInterceptor);
|
||||||
}
|
}
|
||||||
|
@ -474,14 +472,14 @@ public abstract class BaseClient implements IRestfulClient {
|
||||||
/**
|
/**
|
||||||
* This method is an internal part of the HAPI API and may change, use with caution. If you want to disable the
|
* This method is an internal part of the HAPI API and may change, use with caution. If you want to disable the
|
||||||
* loading of conformance statements, use
|
* loading of conformance statements, use
|
||||||
* {@link IRestfulClientFactory#setServerValidationModeEnum(ServerValidationModeEnum)}
|
* {@link IRestfulClientFactory#setServerValidationMode(ServerValidationModeEnum)}
|
||||||
*/
|
*/
|
||||||
public void setDontValidateConformance(boolean theDontValidateConformance) {
|
public void setDontValidateConformance(boolean theDontValidateConformance) {
|
||||||
myDontValidateConformance = theDontValidateConformance;
|
myDontValidateConformance = theDontValidateConformance;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void unregisterInterceptor(IClientInterceptor theInterceptor) {
|
public void unregisterInterceptor(Object theInterceptor) {
|
||||||
Validate.notNull(theInterceptor, "Interceptor can not be null");
|
Validate.notNull(theInterceptor, "Interceptor can not be null");
|
||||||
getInterceptorService().unregisterInterceptor(theInterceptor);
|
getInterceptorService().unregisterInterceptor(theInterceptor);
|
||||||
}
|
}
|
||||||
|
@ -612,7 +610,7 @@ public abstract class BaseClient implements IRestfulClient {
|
||||||
static ArrayList<Class<? extends IBaseResource>> toTypeList(Class<? extends IBaseResource> thePreferResponseType) {
|
static ArrayList<Class<? extends IBaseResource>> toTypeList(Class<? extends IBaseResource> thePreferResponseType) {
|
||||||
ArrayList<Class<? extends IBaseResource>> preferResponseTypes = null;
|
ArrayList<Class<? extends IBaseResource>> preferResponseTypes = null;
|
||||||
if (thePreferResponseType != null) {
|
if (thePreferResponseType != null) {
|
||||||
preferResponseTypes = new ArrayList<Class<? extends IBaseResource>>(1);
|
preferResponseTypes = new ArrayList<>(1);
|
||||||
preferResponseTypes.add(thePreferResponseType);
|
preferResponseTypes.add(thePreferResponseType);
|
||||||
}
|
}
|
||||||
return preferResponseTypes;
|
return preferResponseTypes;
|
||||||
|
|
|
@ -20,11 +20,10 @@ package ca.uhn.fhir.rest.client.interceptor;
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import ca.uhn.fhir.rest.client.api.IClientInterceptor;
|
import ca.uhn.fhir.interceptor.api.Hook;
|
||||||
|
import ca.uhn.fhir.interceptor.api.Pointcut;
|
||||||
import ca.uhn.fhir.rest.client.api.IHttpRequest;
|
import ca.uhn.fhir.rest.client.api.IHttpRequest;
|
||||||
import ca.uhn.fhir.rest.client.api.IHttpResponse;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -37,17 +36,25 @@ import java.util.Objects;
|
||||||
* This is now also possible directly on the Fluent Client API by calling
|
* This is now also possible directly on the Fluent Client API by calling
|
||||||
* {@link ca.uhn.fhir.rest.gclient.IClientExecutable#withAdditionalHeader(String, String)}
|
* {@link ca.uhn.fhir.rest.gclient.IClientExecutable#withAdditionalHeader(String, String)}
|
||||||
*/
|
*/
|
||||||
public class AdditionalRequestHeadersInterceptor implements IClientInterceptor {
|
public class AdditionalRequestHeadersInterceptor {
|
||||||
private final Map<String, List<String>> additionalHttpHeaders = new HashMap<>();
|
private final Map<String, List<String>> myAdditionalHttpHeaders;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
public AdditionalRequestHeadersInterceptor() {
|
public AdditionalRequestHeadersInterceptor() {
|
||||||
this(new HashMap<>());
|
myAdditionalHttpHeaders = new HashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public AdditionalRequestHeadersInterceptor(Map<String, List<String>> additionalHttpHeaders) {
|
/**
|
||||||
super();
|
* Constructor
|
||||||
if (additionalHttpHeaders != null) {
|
*
|
||||||
this.additionalHttpHeaders.putAll(additionalHttpHeaders);
|
* @param theHeaders The additional headers to add to every request
|
||||||
|
*/
|
||||||
|
public AdditionalRequestHeadersInterceptor(Map<String, List<String>> theHeaders) {
|
||||||
|
this();
|
||||||
|
if (theHeaders != null) {
|
||||||
|
myAdditionalHttpHeaders.putAll(theHeaders);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,19 +93,19 @@ public class AdditionalRequestHeadersInterceptor implements IClientInterceptor {
|
||||||
* @return the list of values for the header
|
* @return the list of values for the header
|
||||||
*/
|
*/
|
||||||
private List<String> getHeaderValues(String headerName) {
|
private List<String> getHeaderValues(String headerName) {
|
||||||
if (additionalHttpHeaders.get(headerName) == null) {
|
if (myAdditionalHttpHeaders.get(headerName) == null) {
|
||||||
additionalHttpHeaders.put(headerName, new ArrayList<>());
|
myAdditionalHttpHeaders.put(headerName, new ArrayList<>());
|
||||||
}
|
}
|
||||||
return additionalHttpHeaders.get(headerName);
|
return myAdditionalHttpHeaders.get(headerName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds the additional header values to the HTTP request.
|
* Adds the additional header values to the HTTP request.
|
||||||
* @param theRequest the HTTP request
|
* @param theRequest the HTTP request
|
||||||
*/
|
*/
|
||||||
@Override
|
@Hook(Pointcut.CLIENT_REQUEST)
|
||||||
public void interceptRequest(IHttpRequest theRequest) {
|
public void interceptRequest(IHttpRequest theRequest) {
|
||||||
for (Map.Entry<String, List<String>> header : additionalHttpHeaders.entrySet()) {
|
for (Map.Entry<String, List<String>> header : myAdditionalHttpHeaders.entrySet()) {
|
||||||
for (String headerValue : header.getValue()) {
|
for (String headerValue : header.getValue()) {
|
||||||
if (headerValue != null) {
|
if (headerValue != null) {
|
||||||
theRequest.addHeader(header.getKey(), headerValue);
|
theRequest.addHeader(header.getKey(), headerValue);
|
||||||
|
@ -107,13 +114,4 @@ public class AdditionalRequestHeadersInterceptor implements IClientInterceptor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Does nothing since this interceptor is not concerned with the response.
|
|
||||||
* @param theResponse the HTTP response
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void interceptResponse(IHttpResponse theResponse) throws IOException {
|
|
||||||
// Do nothing. This interceptor is not concerned with the response.
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,6 +94,16 @@
|
||||||
<version>4.2.0-SNAPSHOT</version>
|
<version>4.2.0-SNAPSHOT</version>
|
||||||
<classifier>classes</classifier>
|
<classifier>classes</classifier>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.yaml</groupId>
|
||||||
|
<artifactId>snakeyaml</artifactId>
|
||||||
|
<version>1.25</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>ch.qos.logback</groupId>
|
||||||
|
<artifactId>logback-classic</artifactId>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|
|
@ -57,6 +57,7 @@ public class ChangelogMigrator {
|
||||||
int releaseCount = 0;
|
int releaseCount = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Element docElement = document.getRootElement();
|
Element docElement = document.getRootElement();
|
||||||
Element bodyElement = docElement.getChild("body", NS);
|
Element bodyElement = docElement.getChild("body", NS);
|
||||||
List<Element> releases = bodyElement.getChildren("release", NS);
|
List<Element> releases = bodyElement.getChildren("release", NS);
|
||||||
|
@ -68,6 +69,8 @@ public class ChangelogMigrator {
|
||||||
releaseCount++;
|
releaseCount++;
|
||||||
|
|
||||||
for (Element nextAction : nextRelease.getChildren("action", NS)) {
|
for (Element nextAction : nextRelease.getChildren("action", NS)) {
|
||||||
|
String type = nextAction.getAttribute("type").getValue();
|
||||||
|
String issue = nextAction.getAttribute("issue") != null ? nextAction.getAttribute("issue").getValue() : null;
|
||||||
StringBuilder contentBuilder = new StringBuilder();
|
StringBuilder contentBuilder = new StringBuilder();
|
||||||
for (Content nextContents : nextAction.getContent()) {
|
for (Content nextContents : nextAction.getContent()) {
|
||||||
if (nextContents instanceof Text) {
|
if (nextContents instanceof Text) {
|
||||||
|
|
|
@ -29,6 +29,7 @@ import ca.uhn.fhir.rest.client.api.IBasicClient;
|
||||||
import ca.uhn.fhir.rest.client.api.IClientInterceptor;
|
import ca.uhn.fhir.rest.client.api.IClientInterceptor;
|
||||||
import ca.uhn.fhir.rest.client.api.IGenericClient;
|
import ca.uhn.fhir.rest.client.api.IGenericClient;
|
||||||
import ca.uhn.fhir.rest.client.api.IRestfulClientFactory;
|
import ca.uhn.fhir.rest.client.api.IRestfulClientFactory;
|
||||||
|
import ca.uhn.fhir.rest.client.interceptor.AdditionalRequestHeadersInterceptor;
|
||||||
import ca.uhn.fhir.rest.client.interceptor.BasicAuthInterceptor;
|
import ca.uhn.fhir.rest.client.interceptor.BasicAuthInterceptor;
|
||||||
import ca.uhn.fhir.rest.client.interceptor.BearerTokenAuthInterceptor;
|
import ca.uhn.fhir.rest.client.interceptor.BearerTokenAuthInterceptor;
|
||||||
import ca.uhn.fhir.rest.client.interceptor.CookieInterceptor;
|
import ca.uhn.fhir.rest.client.interceptor.CookieInterceptor;
|
||||||
|
@ -45,7 +46,7 @@ public class ClientExamples {
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public void createProxy() {
|
public void createProxy() {
|
||||||
// START SNIPPET: proxy
|
// START SNIPPET: proxy
|
||||||
FhirContext ctx = FhirContext.forDstu2();
|
FhirContext ctx = FhirContext.forR4();
|
||||||
|
|
||||||
// Set connections to access the network via the HTTP proxy at
|
// Set connections to access the network via the HTTP proxy at
|
||||||
// example.com : 8888
|
// example.com : 8888
|
||||||
|
@ -115,7 +116,7 @@ public class ClientExamples {
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public void createTimeouts() {
|
public void createTimeouts() {
|
||||||
// START SNIPPET: timeouts
|
// START SNIPPET: timeouts
|
||||||
FhirContext ctx = FhirContext.forDstu2();
|
FhirContext ctx = FhirContext.forR4();
|
||||||
|
|
||||||
// Set how long to try and establish the initial TCP connection (in ms)
|
// Set how long to try and establish the initial TCP connection (in ms)
|
||||||
ctx.getRestfulClientFactory().setConnectTimeout(20 * 1000);
|
ctx.getRestfulClientFactory().setConnectTimeout(20 * 1000);
|
||||||
|
@ -132,7 +133,7 @@ public class ClientExamples {
|
||||||
public void createSecurity() {
|
public void createSecurity() {
|
||||||
// START SNIPPET: security
|
// START SNIPPET: security
|
||||||
// Create a context and get the client factory so it can be configured
|
// Create a context and get the client factory so it can be configured
|
||||||
FhirContext ctx = FhirContext.forDstu2();
|
FhirContext ctx = FhirContext.forR4();
|
||||||
IRestfulClientFactory clientFactory = ctx.getRestfulClientFactory();
|
IRestfulClientFactory clientFactory = ctx.getRestfulClientFactory();
|
||||||
|
|
||||||
// Create an HTTP basic auth interceptor
|
// Create an HTTP basic auth interceptor
|
||||||
|
@ -155,7 +156,7 @@ public class ClientExamples {
|
||||||
public void createCookie() {
|
public void createCookie() {
|
||||||
// START SNIPPET: cookie
|
// START SNIPPET: cookie
|
||||||
// Create a context and get the client factory so it can be configured
|
// Create a context and get the client factory so it can be configured
|
||||||
FhirContext ctx = FhirContext.forDstu2();
|
FhirContext ctx = FhirContext.forR4();
|
||||||
IRestfulClientFactory clientFactory = ctx.getRestfulClientFactory();
|
IRestfulClientFactory clientFactory = ctx.getRestfulClientFactory();
|
||||||
|
|
||||||
// Create a cookie interceptor. This cookie will have the name "mycookie" and
|
// Create a cookie interceptor. This cookie will have the name "mycookie" and
|
||||||
|
@ -171,11 +172,40 @@ public class ClientExamples {
|
||||||
// END SNIPPET: cookie
|
// END SNIPPET: cookie
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public void addHeaders() {
|
||||||
|
// START SNIPPET: addHeaders
|
||||||
|
// Create a context and get the client factory so it can be configured
|
||||||
|
FhirContext ctx = FhirContext.forR4();
|
||||||
|
IRestfulClientFactory clientFactory = ctx.getRestfulClientFactory();
|
||||||
|
|
||||||
|
// Create a client
|
||||||
|
IGenericClient client = ctx.newRestfulGenericClient( "http://localhost:9999/fhir");
|
||||||
|
|
||||||
|
// Register an additional headers interceptor and add one header to it
|
||||||
|
AdditionalRequestHeadersInterceptor interceptor = new AdditionalRequestHeadersInterceptor();
|
||||||
|
interceptor.addHeaderValue("X-Message", "Help I'm a Bug");
|
||||||
|
client.registerInterceptor(interceptor);
|
||||||
|
|
||||||
|
IGenericClient genericClient = ctx.newRestfulGenericClient("http://localhost:9999/fhir");
|
||||||
|
client.registerInterceptor(interceptor);
|
||||||
|
// END SNIPPET: addHeaders
|
||||||
|
|
||||||
|
// START SNIPPET: addHeadersNoInterceptor
|
||||||
|
Patient p = client
|
||||||
|
.read()
|
||||||
|
.resource(Patient.class)
|
||||||
|
.withId(123L)
|
||||||
|
.withAdditionalHeader("X-Message", "Help I'm a Bug")
|
||||||
|
.execute();
|
||||||
|
// END SNIPPET: addHeadersNoInterceptor
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public void gzip() {
|
public void gzip() {
|
||||||
// START SNIPPET: gzip
|
// START SNIPPET: gzip
|
||||||
// Create a context and get the client factory so it can be configured
|
// Create a context and get the client factory so it can be configured
|
||||||
FhirContext ctx = FhirContext.forDstu2();
|
FhirContext ctx = FhirContext.forR4();
|
||||||
IRestfulClientFactory clientFactory = ctx.getRestfulClientFactory();
|
IRestfulClientFactory clientFactory = ctx.getRestfulClientFactory();
|
||||||
|
|
||||||
// Register the interceptor with your client (either style)
|
// Register the interceptor with your client (either style)
|
||||||
|
@ -188,7 +218,7 @@ public class ClientExamples {
|
||||||
public void createSecurityBearer() {
|
public void createSecurityBearer() {
|
||||||
// START SNIPPET: securityBearer
|
// START SNIPPET: securityBearer
|
||||||
// Create a context and get the client factory so it can be configured
|
// Create a context and get the client factory so it can be configured
|
||||||
FhirContext ctx = FhirContext.forDstu2();
|
FhirContext ctx = FhirContext.forR4();
|
||||||
IRestfulClientFactory clientFactory = ctx.getRestfulClientFactory();
|
IRestfulClientFactory clientFactory = ctx.getRestfulClientFactory();
|
||||||
|
|
||||||
// In reality the token would have come from an authorization server
|
// In reality the token would have come from an authorization server
|
||||||
|
@ -210,7 +240,7 @@ public class ClientExamples {
|
||||||
{
|
{
|
||||||
// START SNIPPET: logging
|
// START SNIPPET: logging
|
||||||
// Create a context and get the client factory so it can be configured
|
// Create a context and get the client factory so it can be configured
|
||||||
FhirContext ctx = FhirContext.forDstu2();
|
FhirContext ctx = FhirContext.forR4();
|
||||||
IRestfulClientFactory clientFactory = ctx.getRestfulClientFactory();
|
IRestfulClientFactory clientFactory = ctx.getRestfulClientFactory();
|
||||||
|
|
||||||
// Create a logging interceptor
|
// Create a logging interceptor
|
||||||
|
@ -234,7 +264,7 @@ public class ClientExamples {
|
||||||
{
|
{
|
||||||
// START SNIPPET: clientConfig
|
// START SNIPPET: clientConfig
|
||||||
// Create a client
|
// Create a client
|
||||||
FhirContext ctx = FhirContext.forDstu2();
|
FhirContext ctx = FhirContext.forR4();
|
||||||
IPatientClient client = ctx.newRestfulClient(IPatientClient.class, "http://localhost:9999/");
|
IPatientClient client = ctx.newRestfulClient(IPatientClient.class, "http://localhost:9999/");
|
||||||
|
|
||||||
// Request JSON encoding from the server (_format=json)
|
// Request JSON encoding from the server (_format=json)
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
package ca.uhn.hapi.fhir.docs;
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* #%L
|
||||||
|
* HAPI FHIR - Docs
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2014 - 2019 University Health Network
|
||||||
|
* %%
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.interceptor.api.Hook;
|
||||||
|
import ca.uhn.fhir.interceptor.api.Interceptor;
|
||||||
|
import ca.uhn.fhir.interceptor.api.Pointcut;
|
||||||
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
|
import ca.uhn.fhir.rest.client.api.IGenericClient;
|
||||||
|
import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor;
|
||||||
|
import org.hl7.fhir.r4.model.Patient;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class Interceptors {
|
||||||
|
|
||||||
|
|
||||||
|
// START SNIPPET: sampleClass
|
||||||
|
@Interceptor
|
||||||
|
public class SimpleServerLoggingInterceptor {
|
||||||
|
|
||||||
|
private final Logger ourLog = LoggerFactory.getLogger(SimpleServerLoggingInterceptor.class);
|
||||||
|
|
||||||
|
@Hook(Pointcut.SERVER_INCOMING_REQUEST_PRE_HANDLED)
|
||||||
|
public void logRequests(RequestDetails theRequest) {
|
||||||
|
ourLog.info("Request of type {} with request ID: {}", theRequest.getOperation(), theRequest.getRequestId());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
// END SNIPPET: sampleClass
|
||||||
|
|
||||||
|
|
||||||
|
public void registerClient() {
|
||||||
|
|
||||||
|
// START SNIPPET: registerClient
|
||||||
|
FhirContext ctx = FhirContext.forR4();
|
||||||
|
|
||||||
|
// Create a new client instance
|
||||||
|
IGenericClient client = ctx.newRestfulGenericClient("http://hapi.fhir.org/baseR4");
|
||||||
|
|
||||||
|
// Register an interceptor against the client
|
||||||
|
client.registerInterceptor(new LoggingInterceptor());
|
||||||
|
|
||||||
|
// Perform client actions...
|
||||||
|
Patient pt = client.read().resource(Patient.class).withId("example").execute();
|
||||||
|
// END SNIPPET: registerClient
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,43 +0,0 @@
|
||||||
package ca.uhn.hapi.fhir.docs;
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* #%L
|
|
||||||
* HAPI FHIR - Docs
|
|
||||||
* %%
|
|
||||||
* Copyright (C) 2014 - 2019 University Health Network
|
|
||||||
* %%
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
* #L%
|
|
||||||
*/
|
|
||||||
|
|
||||||
import ca.uhn.fhir.interceptor.api.Hook;
|
|
||||||
import ca.uhn.fhir.interceptor.api.Interceptor;
|
|
||||||
import ca.uhn.fhir.interceptor.api.Pointcut;
|
|
||||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
|
|
||||||
// START SNIPPET: sampleClass
|
|
||||||
@Interceptor
|
|
||||||
public class MyInterceptor {
|
|
||||||
|
|
||||||
private static final Logger ourLog = LoggerFactory.getLogger(MyInterceptor.class);
|
|
||||||
|
|
||||||
@Hook(Pointcut.SERVER_INCOMING_REQUEST_PRE_HANDLED)
|
|
||||||
public void logRequests(RequestDetails theRequest) {
|
|
||||||
ourLog.info("Request of type {} with request ID: {}", theRequest.getOperation(), theRequest.getRequestId());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
// END SNIPPET: sampleClass
|
|
|
@ -23,6 +23,7 @@ package ca.uhn.hapi.fhir.docs;
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.parser.DataFormatException;
|
import ca.uhn.fhir.parser.DataFormatException;
|
||||||
import ca.uhn.fhir.parser.IParser;
|
import ca.uhn.fhir.parser.IParser;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
import org.hl7.fhir.r4.model.Patient;
|
import org.hl7.fhir.r4.model.Patient;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -30,8 +31,30 @@ import java.io.IOException;
|
||||||
public class Parser {
|
public class Parser {
|
||||||
|
|
||||||
public static void main(String[] args) throws DataFormatException, IOException {
|
public static void main(String[] args) throws DataFormatException, IOException {
|
||||||
|
|
||||||
{
|
{
|
||||||
//START SNIPPET: createParser
|
//START SNIPPET: parsing
|
||||||
|
// Create a FHIR context
|
||||||
|
FhirContext ctx = FhirContext.forR4();
|
||||||
|
|
||||||
|
// The following example is a simple serialized Patient resource to parse
|
||||||
|
String input = "{" +
|
||||||
|
"\"resourceType\" : \"Patient\"," +
|
||||||
|
" \"name\" : [{" +
|
||||||
|
" \"family\": \"Simpson\"" +
|
||||||
|
" }]" +
|
||||||
|
"}";
|
||||||
|
|
||||||
|
// Instantiate a new parser
|
||||||
|
IParser parser = ctx.newJsonParser();
|
||||||
|
|
||||||
|
// Parse it
|
||||||
|
Patient parsed = parser.parseResource(Patient.class, input);
|
||||||
|
System.out.println(parsed.getName().get(0).getFamily());
|
||||||
|
//END SNIPPET: parsing
|
||||||
|
}
|
||||||
|
{
|
||||||
|
//START SNIPPET: encoding
|
||||||
// Create a FHIR context
|
// Create a FHIR context
|
||||||
FhirContext ctx = FhirContext.forR4();
|
FhirContext ctx = FhirContext.forR4();
|
||||||
|
|
||||||
|
@ -39,13 +62,62 @@ public class Parser {
|
||||||
Patient patient = new Patient();
|
Patient patient = new Patient();
|
||||||
patient.addName().setFamily("Simpson").addGiven("James");
|
patient.addName().setFamily("Simpson").addGiven("James");
|
||||||
|
|
||||||
// Instantiate a new parser
|
// Instantiate a new JSON parser
|
||||||
IParser parser = ctx.newJsonParser();
|
IParser parser = ctx.newJsonParser();
|
||||||
|
|
||||||
// Serialize it
|
// Serialize it
|
||||||
String serialized = parser.encodeResourceToString(patient);
|
String serialized = parser.encodeResourceToString(patient);
|
||||||
System.out.println(serialized);
|
System.out.println(serialized);
|
||||||
//END SNIPPET: createParser
|
|
||||||
|
// Using XML instead
|
||||||
|
serialized = ctx.newXmlParser().encodeResourceToString(patient);
|
||||||
|
System.out.println(serialized);
|
||||||
|
//END SNIPPET: encoding
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// Create a FHIR context
|
||||||
|
FhirContext ctx = FhirContext.forR4();
|
||||||
|
Patient patient = new Patient();
|
||||||
|
patient.addName().setFamily("Simpson").addGiven("James");
|
||||||
|
|
||||||
|
//START SNIPPET: encodingPretty
|
||||||
|
// Create a parser
|
||||||
|
IParser parser = ctx.newJsonParser();
|
||||||
|
|
||||||
|
// Indent the output
|
||||||
|
parser.setPrettyPrint(true);
|
||||||
|
|
||||||
|
// Serialize it
|
||||||
|
String serialized = parser.encodeResourceToString(patient);
|
||||||
|
System.out.println(serialized);
|
||||||
|
|
||||||
|
// You can also chain these statements together
|
||||||
|
ctx.newJsonParser().setPrettyPrint(true).encodeResourceToString(patient);
|
||||||
|
//END SNIPPET: encodingPretty
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// Create a FHIR context
|
||||||
|
FhirContext ctx = FhirContext.forR4();
|
||||||
|
Patient patient = new Patient();
|
||||||
|
patient.addName().setFamily("Simpson").addGiven("James");
|
||||||
|
|
||||||
|
//START SNIPPET: encodingConfig
|
||||||
|
// Create a parser
|
||||||
|
IParser parser = ctx.newJsonParser();
|
||||||
|
|
||||||
|
// Blacklist certain fields from being encoded
|
||||||
|
parser.setDontEncodeElements(Sets.newHashSet("Patient.identifier", "Patient.active"));
|
||||||
|
|
||||||
|
// Don't include resource narratives
|
||||||
|
parser.setSuppressNarratives(true);
|
||||||
|
|
||||||
|
// Use versioned references for these reference elements
|
||||||
|
parser.setDontStripVersionsFromReferencesAtPaths("Patient.organization");
|
||||||
|
|
||||||
|
// Serialize it
|
||||||
|
String serialized = parser.encodeResourceToString(patient);
|
||||||
|
System.out.println(serialized);
|
||||||
|
//END SNIPPET: encodingConfig
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
//START SNIPPET: disableStripVersions
|
//START SNIPPET: disableStripVersions
|
||||||
|
|
|
@ -20,13 +20,17 @@ package ca.uhn.hapi.fhir.docs;
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import ca.uhn.fhir.interceptor.api.Hook;
|
||||||
|
import ca.uhn.fhir.interceptor.api.Interceptor;
|
||||||
|
import ca.uhn.fhir.interceptor.api.Pointcut;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.InterceptorAdapter;
|
import ca.uhn.fhir.rest.server.interceptor.InterceptorAdapter;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
//START SNIPPET: interceptor
|
//START SNIPPET: interceptor
|
||||||
public class RequestCounterInterceptor extends InterceptorAdapter
|
@Interceptor
|
||||||
|
public class RequestCounterInterceptor
|
||||||
{
|
{
|
||||||
|
|
||||||
private int myRequestCount;
|
private int myRequestCount;
|
||||||
|
@ -39,7 +43,7 @@ public class RequestCounterInterceptor extends InterceptorAdapter
|
||||||
* Override the incomingRequestPreProcessed method, which is called
|
* Override the incomingRequestPreProcessed method, which is called
|
||||||
* for each incoming request before any processing is done
|
* for each incoming request before any processing is done
|
||||||
*/
|
*/
|
||||||
@Override
|
@Hook(Pointcut.SERVER_INCOMING_REQUEST_PRE_PROCESSED)
|
||||||
public boolean incomingRequestPreProcessed(HttpServletRequest theRequest, HttpServletResponse theResponse) {
|
public boolean incomingRequestPreProcessed(HttpServletRequest theRequest, HttpServletResponse theResponse) {
|
||||||
myRequestCount++;
|
myRequestCount++;
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -20,36 +20,37 @@ package ca.uhn.hapi.fhir.docs;
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import ca.uhn.fhir.interceptor.api.Hook;
|
||||||
|
import ca.uhn.fhir.interceptor.api.Pointcut;
|
||||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.InterceptorAdapter;
|
|
||||||
|
|
||||||
import javax.servlet.ServletException;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
//START SNIPPET: interceptor
|
//START SNIPPET: interceptor
|
||||||
public class RequestExceptionInterceptor extends InterceptorAdapter
|
public class RequestExceptionInterceptor {
|
||||||
{
|
|
||||||
|
|
||||||
@Override
|
@Hook(Pointcut.SERVER_HANDLE_EXCEPTION)
|
||||||
public boolean handleException(RequestDetails theRequestDetails, BaseServerResponseException theException, HttpServletRequest theServletRequest,
|
public boolean handleException(
|
||||||
HttpServletResponse theServletResponse) throws ServletException, IOException {
|
RequestDetails theRequestDetails,
|
||||||
|
BaseServerResponseException theException,
|
||||||
// HAPI's server exceptions know what the appropriate HTTP status code is
|
HttpServletRequest theServletRequest,
|
||||||
theServletResponse.setStatus(theException.getStatusCode());
|
HttpServletResponse theServletResponse) throws IOException {
|
||||||
|
|
||||||
// Provide a response ourself
|
|
||||||
theServletResponse.setContentType("text/plain");
|
|
||||||
theServletResponse.getWriter().append("Failed to process!");
|
|
||||||
theServletResponse.getWriter().close();
|
|
||||||
|
|
||||||
// Since we handled this response in the interceptor, we must return false
|
|
||||||
// to stop processing immediately
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// HAPI's server exceptions know what the appropriate HTTP status code is
|
||||||
|
theServletResponse.setStatus(theException.getStatusCode());
|
||||||
|
|
||||||
|
// Provide a response ourself
|
||||||
|
theServletResponse.setContentType("text/plain");
|
||||||
|
theServletResponse.getWriter().append("Failed to process!");
|
||||||
|
theServletResponse.getWriter().close();
|
||||||
|
|
||||||
|
// Since we handled this response in the interceptor, we must return false
|
||||||
|
// to stop processing immediately
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
//END SNIPPET: interceptor
|
//END SNIPPET: interceptor
|
||||||
|
|
|
@ -20,9 +20,11 @@ package ca.uhn.hapi.fhir.docs;
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import ca.uhn.fhir.interceptor.api.Hook;
|
||||||
|
import ca.uhn.fhir.interceptor.api.Interceptor;
|
||||||
|
import ca.uhn.fhir.interceptor.api.Pointcut;
|
||||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
|
import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.InterceptorAdapter;
|
|
||||||
import org.apache.commons.codec.binary.Base64;
|
import org.apache.commons.codec.binary.Base64;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
@ -30,56 +32,54 @@ import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
public class SecurityInterceptors {
|
public class SecurityInterceptors {
|
||||||
|
|
||||||
// START SNIPPET: basicAuthInterceptor
|
public void basicAuthInterceptorRealm() {
|
||||||
public class BasicSecurityInterceptor extends InterceptorAdapter
|
//START SNIPPET: basicAuthInterceptorRealm
|
||||||
{
|
AuthenticationException ex = new AuthenticationException();
|
||||||
|
ex.addAuthenticateHeaderForRealm("myRealm");
|
||||||
|
throw ex;
|
||||||
|
//END SNIPPET: basicAuthInterceptorRealm
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
// START SNIPPET: basicAuthInterceptor
|
||||||
* This interceptor implements HTTP Basic Auth, which specifies that
|
@Interceptor
|
||||||
* a username and password are provided in a header called Authorization.
|
public class BasicSecurityInterceptor {
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean incomingRequestPostProcessed(RequestDetails theRequestDetails, HttpServletRequest theRequest, HttpServletResponse theResponse) throws AuthenticationException {
|
|
||||||
String authHeader = theRequest.getHeader("Authorization");
|
|
||||||
|
|
||||||
// The format of the header must be:
|
|
||||||
// Authorization: Basic [base64 of username:password]
|
|
||||||
if (authHeader == null || authHeader.startsWith("Basic ") == false) {
|
|
||||||
throw new AuthenticationException("Missing or invalid Authorization header");
|
|
||||||
}
|
|
||||||
|
|
||||||
String base64 = authHeader.substring("Basic ".length());
|
|
||||||
String base64decoded = new String(Base64.decodeBase64(base64));
|
|
||||||
String[] parts = base64decoded.split("\\:");
|
|
||||||
|
|
||||||
String username = parts[0];
|
|
||||||
String password = parts[1];
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Here we test for a hardcoded username & password. This is
|
|
||||||
* not typically how you would implement this in a production
|
|
||||||
* system of course..
|
|
||||||
*/
|
|
||||||
if (!username.equals("someuser") || !password.equals("thepassword")) {
|
|
||||||
throw new AuthenticationException("Invalid username or password");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return true to allow the request to proceed
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/**
|
||||||
}
|
* This interceptor implements HTTP Basic Auth, which specifies that
|
||||||
//END SNIPPET: basicAuthInterceptor
|
* a username and password are provided in a header called Authorization.
|
||||||
|
*/
|
||||||
|
@Hook(Pointcut.SERVER_INCOMING_REQUEST_POST_PROCESSED)
|
||||||
|
public boolean incomingRequestPostProcessed(RequestDetails theRequestDetails, HttpServletRequest theRequest, HttpServletResponse theResponse) throws AuthenticationException {
|
||||||
|
String authHeader = theRequest.getHeader("Authorization");
|
||||||
|
|
||||||
|
// The format of the header must be:
|
||||||
|
// Authorization: Basic [base64 of username:password]
|
||||||
|
if (authHeader == null || authHeader.startsWith("Basic ") == false) {
|
||||||
|
throw new AuthenticationException("Missing or invalid Authorization header");
|
||||||
|
}
|
||||||
|
|
||||||
|
String base64 = authHeader.substring("Basic ".length());
|
||||||
|
String base64decoded = new String(Base64.decodeBase64(base64));
|
||||||
|
String[] parts = base64decoded.split(":");
|
||||||
|
|
||||||
|
String username = parts[0];
|
||||||
|
String password = parts[1];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Here we test for a hardcoded username & password. This is
|
||||||
|
* not typically how you would implement this in a production
|
||||||
|
* system of course..
|
||||||
|
*/
|
||||||
|
if (!username.equals("someuser") || !password.equals("thepassword")) {
|
||||||
|
throw new AuthenticationException("Invalid username or password");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return true to allow the request to proceed
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void basicAuthInterceptorRealm() {
|
}
|
||||||
//START SNIPPET: basicAuthInterceptorRealm
|
//END SNIPPET: basicAuthInterceptor
|
||||||
AuthenticationException ex = new AuthenticationException();
|
|
||||||
ex.addAuthenticateHeaderForRealm("myRealm");
|
|
||||||
throw ex;
|
|
||||||
//END SNIPPET: basicAuthInterceptorRealm
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -275,6 +275,36 @@
|
||||||
"lat": 14.6914,
|
"lat": 14.6914,
|
||||||
"lon": 120.9686,
|
"lon": 120.9686,
|
||||||
"added": "2019-11-25"
|
"added": "2019-11-25"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Software Interoperability Lab for Asia",
|
||||||
|
"description": "SIL-A maintains a suite of tools used to promote interoperability and medical informatics across Asia.",
|
||||||
|
"link": "http://sil-asia.org/",
|
||||||
|
"city": "Manila, Philippines",
|
||||||
|
"lat": 14.6914,
|
||||||
|
"lon": 120.9686,
|
||||||
|
"added": "2019-11-25"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Lifen",
|
||||||
|
"description": "Lifen is a messaging platform to simplify data exchange between medical professionals, patients and EHRs systems",
|
||||||
|
"link": "https://www.lifen.fr",
|
||||||
|
"city": "Paris",
|
||||||
|
"lat": 48.8647,
|
||||||
|
"lon": 2.349014,
|
||||||
|
"added": "2019-11-22"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Aksara Digital Indonesia, PT.",
|
||||||
|
"description": "SaaS ERP for Healthcare Services",
|
||||||
|
"link": "https://ehealth.co.id",
|
||||||
|
"contactName": "Ibrohim Kholilul Islam",
|
||||||
|
"contactEmail": "ibrohim@ehealth.co.id",
|
||||||
|
"city": "Bandung, Indonesia",
|
||||||
|
"lat": -6.914744,
|
||||||
|
"lon": 107.609810,
|
||||||
|
"added": "2019-11-22"
|
||||||
}
|
}
|
||||||
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
# JavaDocs
|
||||||
|
|
||||||
|
See the [Modules Page](/docs/introduction/modules.html) for more information on the various modules in HAPI FHIR.
|
||||||
|
|
||||||
|
* [Core API](/apidocs/hapi-fhir-base/) - hapi-fhir-base
|
||||||
|
* [Model API (DSTU2)](/apidocs/hapi-fhir-structures-dstu2/) - hapi-fhir-structures-dstu2
|
||||||
|
* [Model API (DSTU2)](/apidocs/hapi-fhir-structures-dstu3/) - hapi-fhir-structures-dstu3
|
||||||
|
* [Model API (R4)](/apidocs/hapi-fhir-structures-r4/) - hapi-fhir-structures-r4
|
||||||
|
* [Model API (R5)](/apidocs/hapi-fhir-structures-r5/) - hapi-fhir-structures-r5
|
||||||
|
* [Client API](/apidocs/hapi-fhir-client/) - hapi-fhir-client
|
||||||
|
* [Server API (Plain)](/apidocs/hapi-fhir-server/) - hapi-fhir-server
|
||||||
|
* [Server API (JPA)](/apidocs/hapi-fhir-jpaserver-base/) - hapi-fhir-jpaserver-base
|
||||||
|
* [Version Converter API](/apidocs/hapi-fhir-converter/) - hapi-fhir-converter
|
||||||
|
* [Server API (JAX-RS)](/apidocs/hapi-fhir-jaxrsserver-base/) - hapi-fhir-jaxrsserver-base
|
|
@ -58,9 +58,9 @@ Note that some popular libraries (e.g. Spring Framework) also use commons-loggin
|
||||||
|
|
||||||
# Client Payload Logging
|
# Client Payload Logging
|
||||||
|
|
||||||
To enable detailed logging of client requests and responses (what URL is being requested, what headers and payload are being received, etc.), an interceptor may be added to the client which logs each transaction. See [Logging Requests and Responses](/docs/interceptors/built_in_client_interceptors.html#req_resp_logging) for more information.
|
To enable detailed logging of client requests and responses (what URL is being requested, what headers and payload are being received, etc.), an interceptor may be added to the client which logs each transaction. See [Logging Requests and Responses](/docs/interceptors/built_in_client_interceptors.html#logging_interceptor) for more information.
|
||||||
|
|
||||||
# Server Request Logging
|
# Server Request Logging
|
||||||
|
|
||||||
To enable detailed logging of server requests and responses, an interceptor may be added to the server which logs each transaction. See [Logging Server Requests](/docs/interceptors/built_in_server_interceptors.html#logging_server_requests) for more information.
|
To enable detailed logging of server requests and responses, an interceptor may be added to the server which logs each transaction. See [Logging Interceptr](/docs/interceptors/built_in_server_interceptors.html#logging_interceptor) for more information.
|
||||||
|
|
||||||
|
|
|
@ -26,13 +26,13 @@ HAPI is built primary using [Apache Maven](http://maven.apache.org/). Even if yo
|
||||||
|
|
||||||
Execute the build with the following command:
|
Execute the build with the following command:
|
||||||
|
|
||||||
```
|
```bash
|
||||||
mvn install
|
mvn install
|
||||||
```
|
```
|
||||||
|
|
||||||
Note that this complete build takes a long time because of all of the unit tests being executed. At the end you should expect to see a screen resembling:
|
Note that this complete build takes a long time because of all of the unit tests being executed. At the end you should expect to see a screen resembling:
|
||||||
|
|
||||||
```
|
```bash
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
[INFO] Reactor Summary:
|
[INFO] Reactor Summary:
|
||||||
[INFO]
|
[INFO]
|
||||||
|
@ -57,7 +57,7 @@ If the build fails to execute successfully, try the following:
|
||||||
|
|
||||||
* The first thing to try is always a fresh clean build when things aren't working:
|
* The first thing to try is always a fresh clean build when things aren't working:
|
||||||
|
|
||||||
```
|
```bash
|
||||||
mvn clean install
|
mvn clean install
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ If the build fails to execute successfully, try the following:
|
||||||
|
|
||||||
* If the build fails with memory issues (or mysteriously dies during unit tests), your build environment may be running out of memory. By default, the HAPI build executes unit tests in multiple parallel JVMs in order to save time. This can consume a lot of RAM and sometimes causes issues. Try executing with the following command to disable this behaviour:
|
* If the build fails with memory issues (or mysteriously dies during unit tests), your build environment may be running out of memory. By default, the HAPI build executes unit tests in multiple parallel JVMs in order to save time. This can consume a lot of RAM and sometimes causes issues. Try executing with the following command to disable this behaviour:
|
||||||
|
|
||||||
```
|
```bash
|
||||||
mvn -P ALLMODULES,NOPARALLEL install
|
mvn -P ALLMODULES,NOPARALLEL install
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -18,44 +18,46 @@ page.model.narrative_generation=Narrative Generation
|
||||||
|
|
||||||
section.client.title=Client
|
section.client.title=Client
|
||||||
page.client.introduction=Introduction
|
page.client.introduction=Introduction
|
||||||
|
page.client.get_started=Get Started ⚡
|
||||||
page.client.generic_client=Generic (Fluent) Client
|
page.client.generic_client=Generic (Fluent) Client
|
||||||
page.client.annotation_client=Annotation Client
|
page.client.annotation_client=Annotation Client
|
||||||
page.client.client_configuration=Client Configuration
|
page.client.client_configuration=Client Configuration
|
||||||
page.client.get_started=Get Started
|
|
||||||
page.client.examples=Client Examples
|
page.client.examples=Client Examples
|
||||||
|
|
||||||
section.server_plain.title=Plain Server
|
section.server_plain.title=Plain Server
|
||||||
page.server_plain.server_types=REST Server Types
|
page.server_plain.server_types=REST Server Types
|
||||||
page.server_plain.introduction=Plain Server Introduction
|
page.server_plain.introduction=Plain Server Introduction
|
||||||
page.server_plain.get_started=Getting Started with Plain Server
|
page.server_plain.get_started=Get Started ⚡
|
||||||
page.server_plain.resource_providers=Resource Providers and Plan Providers
|
page.server_plain.resource_providers=Resource Providers and Plan Providers
|
||||||
page.server_plain.rest_operations=REST Operations: Overview
|
page.server_plain.rest_operations=REST Operations: Overview
|
||||||
page.server_plain.rest_operations_search=REST Operations: Search
|
page.server_plain.rest_operations_search=REST Operations: Search
|
||||||
page.server_plain.rest_operations_operations=REST Operations: Extended Operations
|
page.server_plain.rest_operations_operations=REST Operations: Extended Operations
|
||||||
page.server_plain.paging=Paging Search Results
|
page.server_plain.paging=Paging Search Results
|
||||||
page.server_plain.cors=CORS
|
|
||||||
page.server_plain.web_testpage_overlay=Web Testpage Overlay
|
page.server_plain.web_testpage_overlay=Web Testpage Overlay
|
||||||
page.server_plain.multitenency=Multitenency
|
page.server_plain.multitenency=Multitenency
|
||||||
page.server_plain.jax_rs=JAX-RS Support
|
page.server_plain.jax_rs=JAX-RS Support
|
||||||
|
|
||||||
section.server_jpa.title=JPA Server
|
section.server_jpa.title=JPA Server
|
||||||
page.server_jpa.introduction=Introduction
|
page.server_jpa.introduction=Introduction
|
||||||
page.server_jpa.get_started=Get Started
|
page.server_jpa.get_started=Get Started ⚡
|
||||||
page.server_jpa.architecture=Architecture
|
page.server_jpa.architecture=Architecture
|
||||||
page.server_jpa.upgrading=Upgrade Guide
|
page.server_jpa.upgrading=Upgrade Guide
|
||||||
|
|
||||||
section.interceptors.title=Interceptors
|
section.interceptors.title=Interceptors
|
||||||
page.interceptors.interceptors=Interceptors Overview
|
page.interceptors.interceptors=Interceptors Overview
|
||||||
page.interceptors.client_interceptors=Client Interceptors
|
page.interceptors.client_interceptors=Client Interceptors
|
||||||
|
page.interceptors.client_pointcuts=Client Pointcuts
|
||||||
page.interceptors.built_in_client_interceptors=Built-In Client Interceptors
|
page.interceptors.built_in_client_interceptors=Built-In Client Interceptors
|
||||||
page.interceptors.server_interceptors=Server Interceptors
|
page.interceptors.server_interceptors=Server Interceptors
|
||||||
|
page.interceptors.server_pointcuts=Server Pointcuts
|
||||||
page.interceptors.built_in_server_interceptors=Built-In Server Interceptors
|
page.interceptors.built_in_server_interceptors=Built-In Server Interceptors
|
||||||
|
|
||||||
section.security.title=Security
|
section.security.title=Security
|
||||||
page.security.introduction=Introduction
|
page.security.introduction=Introduction
|
||||||
page.security.authorization_interceptor=Authorization Interceptor
|
page.security.authorization_interceptor=Authorization Interceptor
|
||||||
page.security.consent_interceptor=Consent Interceptor
|
page.security.consent_interceptor=Consent Interceptor
|
||||||
page.security.narrowing_interceptor=Narrowing Interceptor
|
page.security.search_narrowing_interceptor=Search Narrowing Interceptor
|
||||||
|
page.security.cors=CORS
|
||||||
|
|
||||||
section.validation.title=Validation
|
section.validation.title=Validation
|
||||||
page.validation.introduction=Introduction
|
page.validation.introduction=Introduction
|
||||||
|
@ -76,3 +78,4 @@ page.contributing.hacking_guide=Hacking Guide
|
||||||
section.appendix.title=Appendix
|
section.appendix.title=Appendix
|
||||||
page.appendix.logging=Logging
|
page.appendix.logging=Logging
|
||||||
page.appendix.faq=FAQ
|
page.appendix.faq=FAQ
|
||||||
|
page.appendix.javadocs=JavaDocs
|
||||||
|
|
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 58 KiB |
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 209 KiB |
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 254 KiB |
|
@ -1,3 +1,101 @@
|
||||||
# Built-In Client Interceptors
|
# Built-In Client Interceptors
|
||||||
|
|
||||||
<a name="req_resp_logging"/>
|
This page describes some client interceptors that are shipped with HAPI FHIR out of the box. Of course, you are also welcome to create your own.
|
||||||
|
|
||||||
|
<a name="logging_interceptor"/>
|
||||||
|
|
||||||
|
# Logging: Logging Interceptor
|
||||||
|
|
||||||
|
The LoggingInterceptor logs details about each request and/or response that is performed using the client. All logging is performed using SLF4j.
|
||||||
|
|
||||||
|
* [LoggingInterceptor JavaDoc](/apidocs/hapi-fhir-client/ca/uhn/fhir/rest/client/interceptor/LoggingInterceptor.html)
|
||||||
|
* [LoggingInterceptor Source](https://github.com/jamesagnew/hapi-fhir/blob/master/hapi-fhir-client/src/main/java/ca/uhn/fhir/rest/client/interceptor/LoggingInterceptor.java)
|
||||||
|
|
||||||
|
LoggingInterceptor is highly configurable in terms of its output. It can be configured to log simple details about requests, or detailed output including payload bodies and header contents. The following example shows how to enable LoggingInterceptor.
|
||||||
|
|
||||||
|
```java
|
||||||
|
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/ClientExamples.java|logging}}
|
||||||
|
```
|
||||||
|
|
||||||
|
# Security: HTTP Basic Authorization
|
||||||
|
|
||||||
|
The BasicAuthInterceptor adds an `Authorization` header containing an HTTP Basic Auth (username+password) token in every outgoing request.
|
||||||
|
|
||||||
|
* [BasicAuthInterceptor JavaDoc](/apidocs/hapi-fhir-client/ca/uhn/fhir/rest/client/interceptor/BasicAuthInterceptor.html)
|
||||||
|
* [BasicAuthInterceptor Source](https://github.com/jamesagnew/hapi-fhir/blob/master/hapi-fhir-client/src/main/java/ca/uhn/fhir/rest/client/interceptor/BasicAuthInterceptor.java)
|
||||||
|
|
||||||
|
The following example shows how to configure your client to use a specific username and password in every request.
|
||||||
|
|
||||||
|
```java
|
||||||
|
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/ClientExamples.java|security}}
|
||||||
|
```
|
||||||
|
|
||||||
|
# Security: HTTP Bearer Token Authorization
|
||||||
|
|
||||||
|
The BearerTokenAuthInterceptor can be used to add an `Authorization` header containing a bearer token (typically used for OIDC/OAuth2/SMART security flows) to every outgoing request.
|
||||||
|
|
||||||
|
* [BearerTokenAuthInterceptor JavaDoc](/apidocs/hapi-fhir-client/ca/uhn/fhir/rest/client/interceptor/BearerTokenAuthInterceptor.html)
|
||||||
|
* [BearerTokenAuthInterceptor Source](https://github.com/jamesagnew/hapi-fhir/blob/master/hapi-fhir-client/src/main/java/ca/uhn/fhir/rest/client/interceptor/BearerTokenAuthInterceptor.java)
|
||||||
|
|
||||||
|
The following example shows how to configure your client to inject a bearer token authorization header into every request.
|
||||||
|
|
||||||
|
```java
|
||||||
|
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/ClientExamples.java|securityBearer}}
|
||||||
|
```
|
||||||
|
|
||||||
|
# Misc: Add Headers to Request
|
||||||
|
|
||||||
|
The AdditionlRequestHeadersInterceptor can be used to add arbitrary headers to each request created by the client.
|
||||||
|
|
||||||
|
* [AdditionalRequestHeadersInterceptor JavaDoc](/apidocs/hapi-fhir-client/ca/uhn/fhir/rest/client/interceptor/AdditionalRequestHeadersInterceptor.html)
|
||||||
|
* [AdditionalRequestHeadersInterceptor Source](https://github.com/jamesagnew/hapi-fhir/blob/master/hapi-fhir-client/src/main/java/ca/uhn/fhir/rest/client/interceptor/AdditionalRequestHeadersInterceptor.java)
|
||||||
|
|
||||||
|
The following example shows how to configure your client to inject a bearer token authorization header into every request.
|
||||||
|
|
||||||
|
```java
|
||||||
|
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/ClientExamples.java|addHeaders}}
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that headers can also be added to individual [Generic Client](/docs/client/generic_client.html) invocations inline. The example below will produce the same additional request header as the example above, although it applies only to the one request.
|
||||||
|
|
||||||
|
```java
|
||||||
|
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/ClientExamples.java|addHeadersNoInterceptor}}
|
||||||
|
```
|
||||||
|
|
||||||
|
# Misc: Add Cookies to Request
|
||||||
|
|
||||||
|
The CookieInterceptor can be used to add an HTTP Cookie header to each request created by the client.
|
||||||
|
|
||||||
|
* [CookieInterceptor JavaDoc](/apidocs/hapi-fhir-client/ca/uhn/fhir/rest/client/interceptor/CookieInterceptor.html)
|
||||||
|
* [CookieInterceptor Source](https://github.com/jamesagnew/hapi-fhir/blob/master/hapi-fhir-client/src/main/java/ca/uhn/fhir/rest/client/interceptor/CookieInterceptor.java)
|
||||||
|
|
||||||
|
The following example shows how to configure your client to inject a bearer token authorization header into every request.
|
||||||
|
|
||||||
|
```java
|
||||||
|
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/ClientExamples.java|cookie}}
|
||||||
|
```
|
||||||
|
|
||||||
|
# Performance: GZip Outgoing Request Bodies
|
||||||
|
|
||||||
|
The GZipContentInterceptor compresses outgoing contents. With this interceptor, if the client is transmitting resources to the server (e.g. for a create, update, transaction, etc.) the content will be GZipped before transmission to the server.
|
||||||
|
|
||||||
|
* [GZipContentInterceptor JavaDoc](/apidocs/hapi-fhir-client/ca/uhn/fhir/rest/client/apache/GZipContentInterceptor.html)
|
||||||
|
* [GZipContentInterceptor Source](https://github.com/jamesagnew/hapi-fhir/blob/master/hapi-fhir-client/src/main/java/ca/uhn/fhir/rest/client/apache/GZipContentInterceptor.java)
|
||||||
|
|
||||||
|
The following example shows how to enable the GZipContentInterceptor.
|
||||||
|
|
||||||
|
```java
|
||||||
|
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/ClientExamples.java|gzip}}
|
||||||
|
```
|
||||||
|
|
||||||
|
# Capture: Programmatically Capturing Request/Response Details
|
||||||
|
|
||||||
|
The CapturingInterceptor can be used to capture the details of the last request that was sent by the client, as well as the corresponding response that was received.
|
||||||
|
|
||||||
|
* [CapturingInterceptor JavaDoc](/apidocs/hapi-fhir-client/ca/uhn/fhir/rest/client/interceptor/CapturingInterceptor.html)
|
||||||
|
* [CapturingInterceptor Source](https://github.com/jamesagnew/hapi-fhir/blob/master/hapi-fhir-client/src/main/java/ca/uhn/fhir/rest/client/interceptor/CapturingInterceptor.java)
|
||||||
|
|
||||||
|
A separate but related interceptor called ThreadLocalCapturingInterceptor also captures request/response pairs but stores these in a Java ThreadLocal so it is suitable for use in multithreaded environments.
|
||||||
|
|
||||||
|
* [ThreadLocalCapturingInterceptor JavaDoc](/apidocs/hapi-fhir-client/ca/uhn/fhir/rest/client/interceptor/ThreadLocalCapturingInterceptor.html)
|
||||||
|
* [ThreadLocalCapturingInterceptor Source](https://github.com/jamesagnew/hapi-fhir/blob/master/hapi-fhir-client/src/main/java/ca/uhn/fhir/rest/client/interceptor/ThreadLocalCapturingInterceptor.java)
|
||||||
|
|
|
@ -1,3 +1,110 @@
|
||||||
# Built-In Server Interceptors
|
# Built-In Server Interceptors
|
||||||
|
|
||||||
<a name="logging_server_requests"/>
|
This page describes some server interceptors that are shipped with HAPI FHIR out of the box. Of course, you are also welcome to create your own.
|
||||||
|
|
||||||
|
<a name="logging_interceptor"/>
|
||||||
|
|
||||||
|
# Logging: Logging Interceptor
|
||||||
|
|
||||||
|
The LoggingInterceptor can be used to generate a new log line (via SLF4j) for each incoming request. LoggingInterceptor provides a flexible message format that can be used to provide a customized level detail about each incoming request.
|
||||||
|
|
||||||
|
* [LoggingInterceptor JavaDoc](/apidocs/hapi-fhir-server/ca/uhn/fhir/rest/server/interceptor/LoggingInterceptor.html)
|
||||||
|
* [LoggingInterceptor Source](https://github.com/jamesagnew/hapi-fhir/blob/master/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/LoggingInterceptor.java)
|
||||||
|
|
||||||
|
The following example shows how to register a logging interceptor within a FHIR RESTful server.
|
||||||
|
|
||||||
|
```java
|
||||||
|
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/ServletExamples.java|loggingInterceptor}}
|
||||||
|
```
|
||||||
|
|
||||||
|
This interceptor will then produce output similar to the following:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
2014-09-04 02:37:30.030 Source[127.0.0.1] Operation[vread Patient/1667/_history/1] UA[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.94 Safari/537.36] Params[?_format=json]
|
||||||
|
2014-09-04 03:30:00.443 Source[127.0.0.1] Operation[search-type Organization] UA[Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)] Params[]
|
||||||
|
```
|
||||||
|
|
||||||
|
# Response Customizing: Syntax Highlighting
|
||||||
|
|
||||||
|
The ResponseHighlighterInterceptor detects when a request is coming from a browser and returns HTML with syntax highlighted XML/JSON instead of just the raw text. In other words, if a user uses a browser to request `http://foo/Patient/1` by typing this address into their URL bar, they will get nice formatted HTML back with a human readable version of the content. This is particularly helpful for testers and public/development APIs where users are likely to invoke the API directly to see how it works.
|
||||||
|
|
||||||
|
* [ResponseHighlighterInterceptor JavaDoc](/apidocs/hapi-fhir-server/ca/uhn/fhir/rest/server/interceptor/ResponseHighlighterInterceptor.html)
|
||||||
|
* [ResponseHighlighterInterceptor Source](https://github.com/jamesagnew/hapi-fhir/blob/master/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/ResponseHighlighterInterceptor.java)
|
||||||
|
|
||||||
|
To see an example of how the output of this interceptor looks, see our demo server using the following example query: [http://hapi.fhir.org/baseR4/Patient](http://hapi.fhir.org/baseR4/Patient). The HTML view you see no that page with colour and indenting is provided by ResponseHighlighterInterceptor. Without this interceptor the respnose will simply by raw JSON/XML (as it will also be with this interceptor if the request is not coming from a browser, or is invoked by JavaScript).
|
||||||
|
|
||||||
|
```java
|
||||||
|
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/ServletExamples.java|responseHighlighterInterceptor}}
|
||||||
|
```
|
||||||
|
|
||||||
|
# Response Customizing: Exception Handling
|
||||||
|
|
||||||
|
The ExceptionHandlingInterceptor can be used to customize what is returned to the client and what is logged when the server throws an exception for any reason (including routine things like UnprocessableEntityExceptions thrown as a matter of normal processing in a create method, but also including unexpected exceptions thrown by client code).
|
||||||
|
|
||||||
|
* [ExceptionHandlingInterceptor JavaDoc](/apidocs/hapi-fhir-server/ca/uhn/fhir/rest/server/interceptor/ExceptionHandlingInterceptor.html)
|
||||||
|
* [ExceptionHandlingInterceptor Source](https://github.com/jamesagnew/hapi-fhir/blob/master/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/ExceptionHandlingInterceptor.java)
|
||||||
|
|
||||||
|
The following example shows how to register the ExceptionHandlingInterceptor.
|
||||||
|
|
||||||
|
```java
|
||||||
|
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/ServletExamples.java|exceptionInterceptor}}
|
||||||
|
```
|
||||||
|
|
||||||
|
# Validation: Request and Response Validation
|
||||||
|
|
||||||
|
HAPI FHIR provides a pair of interceptors that can be used to validate incoming requests received by the server, as well as outgoing responses generated by the server.
|
||||||
|
|
||||||
|
The RequestValidatingInterceptor and ResponseValidatingInterceptor can be used to perform validation of resources on their way into and out of the server respectively.
|
||||||
|
|
||||||
|
* [RequestValidatingInterceptor JavaDoc](/apidocs/hapi-fhir-server/ca/uhn/fhir/rest/server/interceptor/RequestValidatingInterceptor.html)
|
||||||
|
* [RequestValidatingInterceptor Source](https://github.com/jamesagnew/hapi-fhir/blob/master/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/RequestValidatingInterceptor.java)
|
||||||
|
* [ResponseValidatingInterceptor JavaDoc](/apidocs/hapi-fhir-server/ca/uhn/fhir/rest/server/interceptor/ResponseValidatingInterceptor.html)
|
||||||
|
* [ResponseValidatingInterceptor Source](https://github.com/jamesagnew/hapi-fhir/blob/master/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/ResponseValidatingInterceptor.java)
|
||||||
|
|
||||||
|
The RequestValidatingInterceptor looks at resources coming into the server (e.g. for create, update, $operations, transactions, etc.) and validates them. The ResponseValidatingInterceptor looks at resources being returned by the server (e.g. for read, search, $operations, etc.) and validates them.
|
||||||
|
|
||||||
|
These interceptors can be configured to add headers to the response, fail the response (returning an HTTP 422 and throwing an exception in the process), or to add to the OperationOutcome returned by the server.
|
||||||
|
|
||||||
|
See [Profile Validator](/docs/validation/profile_validator.html) for information on how validation works in HAPI FHIR.
|
||||||
|
|
||||||
|
The following example shows how to register this interceptor within a HAPI FHIR REST server.
|
||||||
|
|
||||||
|
```java
|
||||||
|
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/ServletExamples.java|validatingInterceptor}}
|
||||||
|
```
|
||||||
|
|
||||||
|
# Security: CORS
|
||||||
|
|
||||||
|
HAPI FHIR includes an interceptor which can be used to implement CORS support on your server. See [Server CORS Documentation](/docs/security/cors.html#cors_interceptor) for information on how to use this interceptor.
|
||||||
|
|
||||||
|
|
||||||
|
# Security: Authorization
|
||||||
|
|
||||||
|
HAPI FHIR provides a powerful interceptor that can be used to implement user- and system-level authorization rules that are aware of FHIR semantics. See [Authorization](/docs/security/authorization_interceptor.html) for more information.
|
||||||
|
|
||||||
|
|
||||||
|
# Security: Consent
|
||||||
|
|
||||||
|
HAPI FHIR provides an interceptor that can be used to implement consent rules and directives. See [Consent Interceptor](/docs/security/consent_interceptor.html) for more information.
|
||||||
|
|
||||||
|
|
||||||
|
# Security: Search Narrowing
|
||||||
|
|
||||||
|
HAPI FHIR provides an interceptor that can be used to implement consent rules and directives. See [Consent Interceptor](/docs/security/consent_interceptor.html) for more information.
|
||||||
|
|
||||||
|
|
||||||
|
# Security: Rejecting Unsupported HTTP Verbs
|
||||||
|
|
||||||
|
Some security audit tools require that servers return an HTTP 405 if an unsupported HTTP verb is received (e.g. TRACE). The BanUnsupportedHttpMethodsInterceptor can be used to accomplish this.
|
||||||
|
|
||||||
|
* [BanUnsupportedHttpMethodsInterceptor JavaDoc](/apidocs/hapi-fhir-server/ca/uhn/fhir/rest/server/interceptor/BanUnsupportedHttpMethodsInterceptor.html)
|
||||||
|
* [BanUnsupportedHttpMethodsInterceptor Source](https://github.com/jamesagnew/hapi-fhir/blob/master/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/BanUnsupportedHttpMethodsInterceptor.java)
|
||||||
|
|
||||||
|
|
||||||
|
# Request Pre-Processing: Override Meta.source
|
||||||
|
|
||||||
|
If you wish to override the value of `Resource.meta.source` using the value supplied in an HTTP header, you can use the CaptureResourceSourceFromHeaderInterceptor to accomplish this.
|
||||||
|
|
||||||
|
* [CaptureResourceSourceFromHeaderInterceptor JavaDoc](/apidocs/hapi-fhir-server/ca/uhn/fhir/rest/server/interceptor/CaptureResourceSourceFromHeaderInterceptor.html)
|
||||||
|
* [CaptureResourceSourceFromHeaderInterceptor Source](https://github.com/jamesagnew/hapi-fhir/blob/master/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/CaptureResourceSourceFromHeaderInterceptor.java)
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
# Client Interceptors
|
# Client Interceptors
|
||||||
|
|
||||||
<a name="req_resp_logging"/>
|
Client interceptors may be used to examine requests and responses before and after they are sent to the remote server.
|
||||||
|
|
||||||
|
# Registering Client Interceptors
|
||||||
|
|
||||||
|
Interceptors for the client are registered against individual client instances, as shown in the example below.
|
||||||
|
|
||||||
|
```java
|
||||||
|
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/Interceptors.java|registerClient}}
|
||||||
|
```
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
# Client Pointcuts
|
||||||
|
|
||||||
|
The following diagram shows the request processing pipeline for processing a client request.
|
||||||
|
|
||||||
|
<a href="/hapi-fhir/docs/images/interceptors-client-pipeline.svg" target="_blank">Expand</a>
|
||||||
|
<img src="/hapi-fhir/docs/images/interceptors-client-pipeline.svg" alt="Client Pipeline"/>
|
||||||
|
|
||||||
|
See the [Pointcut](/apidocs/hapi-fhir-base/ca/uhn/fhir/interceptor/api/Pointcut.html) JavaDoc for details about these pointcuts, what arguments are allowed etc.
|
||||||
|
|
|
@ -1,10 +1,46 @@
|
||||||
# Interceptors: Overview
|
# Interceptors: Overview
|
||||||
|
|
||||||
HAPI FHIR 3.8.0 introduced a new interceptor framework that is used across the entire library. In previous versions of HAPI FHIR, a "Server Interceptor" framework existed and a separate "Client Interceptor" framework existed. These have now been combined into a single unified (and very powerful) framework.
|
HAPI FHIR 3.8.0 introduced a new interceptor framework that is used across the entire library. In previous versions of HAPI FHIR, a "Server Interceptor" framework existed and a separate "Client Interceptor" framework existed. These have now been combined into a single unified (and much more powerful) framework.
|
||||||
|
|
||||||
Interceptor classes may "hook into" various points in the processing chain in both the client and the server.
|
Interceptor classes may "hook into" various points in the processing chain in both the client and the server. The interceptor framework has been designed do be flexible enough to hook into almost every part of the library. When trying to figure out "how would I make HAPI FHIR do X", the answer is very often to create an interceptor.
|
||||||
|
|
||||||
|
The following example shows a very simple interceptor example.
|
||||||
|
|
||||||
```java
|
```java
|
||||||
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/MyInterceptor.java|sampleClass}}
|
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/Interceptors.java|sampleClass}}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Interceptors Glossary
|
||||||
|
|
||||||
|
The HAPI FHIR interceptor framework uses a couple of key terms that are important to understand as you read the rest of this documentation:
|
||||||
|
|
||||||
|
* **Interceptor** – A class such as the example above that has one or more *Hook* methods on it. An optional marker annotation called [@Interceptor](/apidocs/hapi-fhir-base/ca/uhn/fhir/interceptor/api/Interceptor.html) exists and can be used, but is not required.
|
||||||
|
|
||||||
|
* **Hook** – An individual interceptor method that is invoked in response to a specific action taking place in the HAPI FHIR framework. Hook methods must be annotated with the [@Hook](/apidocs/hapi-fhir-base/ca/uhn/fhir/interceptor/api/Hook.html) annotation.
|
||||||
|
|
||||||
|
* **Pointcut** – A pointcut is a specific point in the HAPI FHIR processing pipeline that is being intercepted. Each Hook Method must declare which pointcut it is intercepting. All available pointcuts are defined by HAPI FHIR in the [Pointcut](/apidocs/hapi-fhir-base/ca/uhn/fhir/interceptor/api/Pointcut.html) enum.
|
||||||
|
|
||||||
|
* **Hook Params** – Every Pointcut defines a list of parameters that may be passed to a Hook Method for a given Pointcut. For example, the definition of the [SERVER_INCOMING_REQUEST_PRE_HANDLED](/apidocs/hapi-fhir-base/ca/uhn/fhir/interceptor/api/Pointcut.html#SERVER_INCOMING_REQUEST_PRE_HANDLED) pointcut used in the example above defines 4 parameter types. A hook method for that parameter type can include any/all of these parameter types in its parameter list. The example above is only using one.
|
||||||
|
|
||||||
|
# Creating Interceptors
|
||||||
|
|
||||||
|
Creating your own interceptors is easy. Custom interceptor classes do not need to extend any other class or implement any particular interface.
|
||||||
|
|
||||||
|
* They must have at least one method annotated with the [@Hook](/apidocs/hapi-fhir-base/ca/uhn/fhir/interceptor/api/Pointcut.html) annotation.
|
||||||
|
|
||||||
|
* The method must have an appropriate return value for the chosen [Pointcut](/apidocs/hapi-fhir-base/ca/uhn/fhir/interceptor/api/Pointcut.html).
|
||||||
|
|
||||||
|
* The method may have any of the parameters specified for the given [Pointcut](/apidocs/hapi-fhir-base/ca/uhn/fhir/interceptor/api/Pointcut.html).
|
||||||
|
|
||||||
|
The following example shows a simple request counter interceptor.
|
||||||
|
|
||||||
|
```java
|
||||||
|
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RequestCounterInterceptor.java|interceptor}}
|
||||||
|
```
|
||||||
|
|
||||||
|
The following example shows an exception handling interceptor which overrides the built-in exception handling by providing a custom response.
|
||||||
|
|
||||||
|
```java
|
||||||
|
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RequestExceptionInterceptor.java|interceptor}}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -1 +1,8 @@
|
||||||
# Server Interceptors
|
# Server Interceptors
|
||||||
|
|
||||||
|
There are many different Pointcuts available to server developers. In general, a server can be thought of as playing two roles: Server and Storage.
|
||||||
|
|
||||||
|
In the case of a Plain Server, HAPI FHIR itself performs the role of the Server and your [Resource Provider](/docs/server_plain/resource_providers.html) classes perform the role of Storage.
|
||||||
|
|
||||||
|
In the case of a JPA Server, HAPI FHIR itself performs both roles. This means that **SERVER_xxx** Pointcuts may be intercepted by interceptors on any HAPI FHIR server. However, if you want to intercept **STORAGE_xxx** Pointcuts on a plain server, you will need to trigger them yourself.
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
# Plain Server Pointcuts
|
||||||
|
|
||||||
|
The following diagram shows the request processing pipeline for processing a server request. You may click on the diagram to enlarge it.
|
||||||
|
|
||||||
|
<a href="/hapi-fhir/docs/images/interceptors-server-pipeline.svg" target="_blank">Expand</a>
|
||||||
|
<img src="/hapi-fhir/docs/images/interceptors-server-pipeline.svg" alt="Server Pipeline"/>
|
||||||
|
|
||||||
|
# Storage / JPA Server Pointcuts
|
||||||
|
|
||||||
|
The following diagram shows the request processing pipeline for processing a server request. You may click on the diagram to enlarge it.
|
||||||
|
|
||||||
|
<a href="/hapi-fhir/docs/images/interceptors-server-jpa-pipeline.svg" target="_blank">Expand</a>
|
||||||
|
<img src="/hapi-fhir/docs/images/interceptors-server-jpa-pipeline.svg" alt="Server Pipeline"/>
|
||||||
|
|
|
@ -2,17 +2,18 @@
|
||||||
|
|
||||||
The following table shows the modules that make up the HAPI FHIR library.
|
The following table shows the modules that make up the HAPI FHIR library.
|
||||||
|
|
||||||
<table class="table table-condensed">
|
<table class="modules-table">
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="3" style="text-align: center; font-size: 1.2em; background: #DDE; padding: 3px;">
|
<td colspan="3" class="modules-section-row">
|
||||||
Core Libraries
|
Core Libraries
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-base</td>
|
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-base</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="/hapi-fhir/apidocs/hapi-fhir-base/">JavaDoc</a>
|
<a href="/hapi-fhir/apidocs/hapi-fhir-base/">JavaDoc ›</a>
|
||||||
|
<a href="https://github.com/jamesagnew/hapi-fhir/tree/master/hapi-fhir-base">Sources ›</a>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
This is the core HAPI FHIR library and is always required in order to use
|
This is the core HAPI FHIR library and is always required in order to use
|
||||||
|
@ -20,22 +21,14 @@ The following table shows the modules that make up the HAPI FHIR library.
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td style="text-align: center; font-size: 1.2em; background: #DDE; padding: 3px;" colspan="3">
|
<td class="modules-section-row" colspan="3">
|
||||||
Structures
|
Structures
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
|
||||||
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-structures-dstu (retired)</td>
|
|
||||||
<td>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
This module contained FHIR DSTU1 model classes. It was retired in HAPI FHIR 3.0.0.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
<tr>
|
||||||
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-structures-dstu2</td>
|
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-structures-dstu2</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="/hapi-fhir/apidocs/hapi-fhir-structures-dstu2/">JavaDoc</a>
|
<a href="/hapi-fhir/apidocs/hapi-fhir-structures-dstu2/">JavaDoc ›</a>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
This module contains FHIR DSTU2 model classes.
|
This module contains FHIR DSTU2 model classes.
|
||||||
|
@ -44,7 +37,7 @@ The following table shows the modules that make up the HAPI FHIR library.
|
||||||
<tr>
|
<tr>
|
||||||
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-structures-hl7org-dstu2</td>
|
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-structures-hl7org-dstu2</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="/hapi-fhir/apidocs/hapi-fhir-structures-hl7org-dstu2/">JavaDoc</a>
|
<a href="/hapi-fhir/apidocs/hapi-fhir-structures-hl7org-dstu2/">JavaDoc ›</a>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
This module contains alternate FHIR DSTU2 model classes. The HAPI FHIR and FHIR "Java Reference
|
This module contains alternate FHIR DSTU2 model classes. The HAPI FHIR and FHIR "Java Reference
|
||||||
|
@ -58,7 +51,7 @@ The following table shows the modules that make up the HAPI FHIR library.
|
||||||
<tr>
|
<tr>
|
||||||
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-structures-dstu3</td>
|
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-structures-dstu3</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="/hapi-fhir/apidocs/hapi-fhir-structures-dstu3/">JavaDoc</a>
|
<a href="/hapi-fhir/apidocs/hapi-fhir-structures-dstu3/">JavaDoc ›</a>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
This module contains FHIR DSTU3 model classes.
|
This module contains FHIR DSTU3 model classes.
|
||||||
|
@ -67,7 +60,7 @@ The following table shows the modules that make up the HAPI FHIR library.
|
||||||
<tr>
|
<tr>
|
||||||
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-structures-r4</td>
|
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-structures-r4</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="/hapi-fhir/apidocs/hapi-fhir-structures-r4/">JavaDoc</a>
|
<a href="/hapi-fhir/apidocs/hapi-fhir-structures-r4/">JavaDoc ›</a>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
This module contains FHIR R4 model classes.
|
This module contains FHIR R4 model classes.
|
||||||
|
@ -76,7 +69,7 @@ The following table shows the modules that make up the HAPI FHIR library.
|
||||||
<tr>
|
<tr>
|
||||||
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-structures-r5</td>
|
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-structures-r5</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="/hapi-fhir/apidocs/hapi-fhir-structures-r5/">JavaDoc</a>
|
<a href="/hapi-fhir/apidocs/hapi-fhir-structures-r5/">JavaDoc ›</a>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
This module contains FHIR R5 model classes.
|
This module contains FHIR R5 model classes.
|
||||||
|
@ -85,21 +78,32 @@ The following table shows the modules that make up the HAPI FHIR library.
|
||||||
<tr>
|
<tr>
|
||||||
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-converter</td>
|
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-converter</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="/hapi-fhir/apidocs/hapi-fhir-converter/">JavaDoc</a>
|
<a href="/hapi-fhir/docs/model/converter.html">Documentation ›</a><br/>
|
||||||
|
<a href="/hapi-fhir/apidocs/hapi-fhir-converter/">JavaDoc ›</a>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
This module contains converters for converting between FHIR versions.
|
This module contains converters for converting between FHIR versions.
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td style="text-align: center; font-size: 1.2em; background: #DDE; padding: 3px;" colspan="3">Client
|
<td style="font-weight: bold; white-space: nowrap;"><i>hapi-fhir-structures-dstu (retired)</i></td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
This module contained FHIR DSTU1 model classes. It was retired in HAPI FHIR 3.0.0.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="modules-section-row" colspan="3">Client
|
||||||
Framework
|
Framework
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-client</td>
|
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-client</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="/hapi-fhir/apidocs/hapi-fhir-client/">JavaDoc</a>
|
<a href="/hapi-fhir/docs/client/">Documentation ›</a><br/>
|
||||||
|
<a href="/hapi-fhir/apidocs/hapi-fhir-client/">JavaDoc ›</a>
|
||||||
|
<a href="https://github.com/jamesagnew/hapi-fhir/tree/master/hapi-fhir-client">Sources ›</a>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
This module contains the core FHIR client framework, including an
|
This module contains the core FHIR client framework, including an
|
||||||
|
@ -111,6 +115,7 @@ The following table shows the modules that make up the HAPI FHIR library.
|
||||||
<tr>
|
<tr>
|
||||||
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-client-okhttp</td>
|
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-client-okhttp</td>
|
||||||
<td>
|
<td>
|
||||||
|
<a href="https://github.com/jamesagnew/hapi-fhir/tree/master/hapi-fhir-client-okhttp">Sources ›</a>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
This module contains an alternate HTTP implementation based on
|
This module contains an alternate HTTP implementation based on
|
||||||
|
@ -120,6 +125,8 @@ The following table shows the modules that make up the HAPI FHIR library.
|
||||||
<tr>
|
<tr>
|
||||||
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-android</td>
|
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-android</td>
|
||||||
<td>
|
<td>
|
||||||
|
<a href="/hapi-fhir/docs/android/">Documentation ›</a>
|
||||||
|
<a href="https://github.com/jamesagnew/hapi-fhir/tree/master/hapi-fhir-android/">Sources ›</a>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
This module contains the Android HAPI FHIR framework, which is a FHIR
|
This module contains the Android HAPI FHIR framework, which is a FHIR
|
||||||
|
@ -127,13 +134,14 @@ The following table shows the modules that make up the HAPI FHIR library.
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td style="text-align: center; font-size: 1.2em; background: #DDE; padding: 3px;" colspan="3">
|
<td class="modules-section-row" colspan="3">
|
||||||
Validation
|
Validation
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-validation</td>
|
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-validation</td>
|
||||||
<td>
|
<td>
|
||||||
|
<a href="/hapi-fhir/docs/validation/">Documentation ›</a>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
This module contains the FHIR Profile Validator, which is used to
|
This module contains the FHIR Profile Validator, which is used to
|
||||||
|
@ -187,12 +195,14 @@ The following table shows the modules that make up the HAPI FHIR library.
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td style="text-align: center; font-size: 1.2em; background: #DDE; padding: 3px;" colspan="3">Server</td>
|
<td class="modules-section-row" colspan="3">Server</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-server</td>
|
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-server</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="/hapi-fhir/apidocs/hapi-fhir-server/">JavaDoc</a>
|
<a href="/hapi-fhir/docs/server_plain/">Documentation ›</a><br/>
|
||||||
|
<a href="/hapi-fhir/apidocs/hapi-fhir-server/">JavaDoc ›</a>
|
||||||
|
<a href="https://github.com/jamesagnew/hapi-fhir/tree/master/hapi-fhir-server/">Sources ›</a>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
This module contains the HAPI FHIR Server framework, which can be used to
|
This module contains the HAPI FHIR Server framework, which can be used to
|
||||||
|
@ -202,7 +212,9 @@ The following table shows the modules that make up the HAPI FHIR library.
|
||||||
<tr>
|
<tr>
|
||||||
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-jpaserver-base</td>
|
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-jpaserver-base</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="/hapi-fhir/apidocs/hapi-fhir-jpaserver-base/">JavaDoc</a>
|
<a href="/hapi-fhir/docs/server_jpa/">Documentation ›</a><br/>
|
||||||
|
<a href="/hapi-fhir/apidocs/hapi-fhir-jpaserver-base/">JavaDoc ›</a>
|
||||||
|
<a href="https://github.com/jamesagnew/hapi-fhir/tree/master/hapi-fhir-jpaserver-base/">Sources ›</a>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
This module contains the HAPI FHIR "JPA Server", which is a complete
|
This module contains the HAPI FHIR "JPA Server", which is a complete
|
||||||
|
@ -213,6 +225,8 @@ The following table shows the modules that make up the HAPI FHIR library.
|
||||||
<tr>
|
<tr>
|
||||||
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-testpage-overlay</td>
|
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-testpage-overlay</td>
|
||||||
<td>
|
<td>
|
||||||
|
<a href="/hapi-fhir/docs/server_plain/web_testpage_overlay.html">Documentation ›</a><br/>
|
||||||
|
<a href="https://github.com/jamesagnew/hapi-fhir/tree/master/hapi-fhir-testpage-overlay/">Sources ›</a>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
This module contains the web based "testpage overlay", which is the
|
This module contains the web based "testpage overlay", which is the
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
# HL7 FHIR Converter
|
# HL7 FHIR Converter
|
||||||
|
|
||||||
Beginning in HAPI FHIR 2.3, a new module called `hapi-fhir-converter` has been added to the project. This is an <b>experimental feature</b> so use it with caution!
|
Beginning in HAPI FHIR 2.3, a new module called `hapi-fhir-converter` has been added to the project. This is an <b>experimental feature</b> so use it with caution!
|
||||||
|
|
|
@ -4,14 +4,38 @@ HAPI FHIR has built-in support for the FHIR [JSON](http://hl7.org/fhir/json.html
|
||||||
|
|
||||||
A built in parser can be used to convert HAPI FHIR Java objects into a serialized form, and to parse serialized data into Java objects. Note that unlike some other frameworks, HAPI FHIR does not have separate parsers and serializers. Both of these functions are handled by a single object called the **Parser**.
|
A built in parser can be used to convert HAPI FHIR Java objects into a serialized form, and to parse serialized data into Java objects. Note that unlike some other frameworks, HAPI FHIR does not have separate parsers and serializers. Both of these functions are handled by a single object called the **Parser**.
|
||||||
|
|
||||||
# Serializing
|
# Parsing (aka Deserializing)
|
||||||
|
|
||||||
As with many parts of the HAPI FHIR API, parsing beginis with a [FhirContext](/apidocs/hapi-fhr-base/ca/uhn/fhir/context/FhirContext.html) object. The FhirContext can be used to request an [IParser](/apidocs/hapi-fhir-base/ca/uhn/fhir/parser/IParser.html) for your chosen encodng style that is then used to serialize.
|
As with many parts of the HAPI FHIR API, parsing begins with a [FhirContext](/apidocs/hapi-fhir-base/ca/uhn/fhir/context/FhirContext.html) object. The FhirContext can be used to request an [IParser](/apidocs/hapi-fhir-base/ca/uhn/fhir/parser/IParser.html) for your chosen encodng style that is then used to parse.
|
||||||
|
|
||||||
|
```java
|
||||||
|
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/Parser.java|parsing}}
|
||||||
|
```
|
||||||
|
|
||||||
|
# Encoding (aka Serializing)
|
||||||
|
|
||||||
|
As with many parts of the HAPI FHIR API, parsing begins with a [FhirContext](/apidocs/hapi-fhir-base/ca/uhn/fhir/context/FhirContext.html) object. The FhirContext can be used to request an [IParser](/apidocs/hapi-fhir-base/ca/uhn/fhir/parser/IParser.html) for your chosen encodng style that is then used to serialize.
|
||||||
|
|
||||||
The following example shows a JSON Parser being used to serialize a FHIR resource.
|
The following example shows a JSON Parser being used to serialize a FHIR resource.
|
||||||
|
|
||||||
```java
|
```java
|
||||||
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/Parser.java|createParser}}
|
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/Parser.java|encoding}}
|
||||||
```
|
```
|
||||||
|
|
||||||
HapiWorkerContext
|
## Pretty Printing
|
||||||
|
|
||||||
|
By default, the parser will output in condensed form, with no newlines or indenting. This is good for machine-to-machine communication since it reduces the amount of data to be transferred but it is harder to read. To enable pretty printed outout:
|
||||||
|
|
||||||
|
```java
|
||||||
|
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/Parser.java|encodingPretty}}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Encoding Configuration
|
||||||
|
|
||||||
|
There are plenty of other options too that can be used to control the output by the parser. A few examples are shown below. See the [IParser](/apidocs/hapi-fhir-base/ca/uhn/fhir/parser/IParser.html) JavaDoc for more information.
|
||||||
|
|
||||||
|
```java
|
||||||
|
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/Parser.java|encodingConfig}}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
# Authorization Interceptor
|
# Authorization Interceptor
|
||||||
|
|
||||||
HAPI FHIR 1.5 introduced a new interceptor: [AuthorizationInterceptor](/hapi-fhir/apidocs/hapi-fhir-server/ca/uhn/fhir/rest/server/interceptor/auth/AuthorizationInterceptor.html).
|
HAPI FHIR 1.5 introduced a new interceptor: [AuthorizationInterceptor](/apidocs/hapi-fhir-server/ca/uhn/fhir/rest/server/interceptor/auth/AuthorizationInterceptor.html).
|
||||||
|
|
||||||
This interceptor can help with the complicated task of determining whether a user has the appropriate permission to perform a given task on a FHIR server. This is done by declaring a set of rules that can selectively allow (whitelist) and/or selectively block (blacklist) requests.
|
This interceptor can help with the complicated task of determining whether a user has the appropriate permission to perform a given task on a FHIR server. This is done by declaring a set of rules that can selectively allow (whitelist) and/or selectively block (blacklist) requests.
|
||||||
|
|
||||||
|
* [AuthorizationInterceptor JavaDoc](/apidocs/hapi-fhir-server/ca/uhn/fhir/rest/server/interceptor/auth/AuthorizationInterceptor.html)
|
||||||
|
* [AuthorizationInterceptor Source](https://github.com/jamesagnew/hapi-fhir/blob/master/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/auth/AuthorizationInterceptor.java)
|
||||||
|
|
||||||
<p class="helpInfoCalloutBox">
|
<p class="helpInfoCalloutBox">
|
||||||
AuthorizationInterceptor has been well tested, but it is impossible to predict every scenario and environment in which HAPI FHIR will be used. Use with caution, and do lots of testing! We welcome feedback and suggestions on this feature. Please get in touch if you'd like to help test, have suggestions, etc.
|
AuthorizationInterceptor has been well tested, but it is impossible to predict every scenario and environment in which HAPI FHIR will be used. Use with caution, and do lots of testing! We welcome feedback and suggestions on this feature. Please get in touch if you'd like to help test, have suggestions, etc.
|
||||||
</p>
|
</p>
|
||||||
|
|
|
@ -4,6 +4,9 @@ HAPI FHIR 4.0.0 introduced a new interceptor, the [ConsentInterceptor](/hapi-fhi
|
||||||
|
|
||||||
The consent interceptor may be used to examine client requests to apply consent directives and create audit trail events. Like the AuthorizationInterceptor above, this interceptor is not a complete working solution, but instead is a framework designed to make it easier to implement local policies.
|
The consent interceptor may be used to examine client requests to apply consent directives and create audit trail events. Like the AuthorizationInterceptor above, this interceptor is not a complete working solution, but instead is a framework designed to make it easier to implement local policies.
|
||||||
|
|
||||||
|
* [ConsentInterceptor JavaDoc](/apidocs/hapi-fhir-server/ca/uhn/fhir/rest/server/interceptor/consent/ConsentInterceptor.html)
|
||||||
|
* [ConsentInterceptor Source](https://github.com/jamesagnew/hapi-fhir/blob/master/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/consent/ConsentInterceptor.java)
|
||||||
|
|
||||||
The consent interceptor has several primary purposes:
|
The consent interceptor has several primary purposes:
|
||||||
|
|
||||||
** It can reject a resource from being disclosed to the user by examining it while calculating search results. This calculation is performed very early in the process of building search results, in order to ensure that in many cases the user is unaware that results have been removed.
|
** It can reject a resource from being disclosed to the user by examining it while calculating search results. This calculation is performed very early in the process of building search results, in order to ensure that in many cases the user is unaware that results have been removed.
|
||||||
|
|
|
@ -1,20 +1,21 @@
|
||||||
# CORS
|
# CORS (Cross-Origin Resource Sharing)
|
||||||
|
|
||||||
<p class="doc_info_bubble">
|
|
||||||
Note that in previous revisions of this document we recommended using the <a href="https://github.com/ebay/cors-filter">eBay CORS Filter</a>, but as of 2016 the eBay filter is no longer being maintained and contains known bugs. We now recommend against using this filter.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
If you are intending to support JavaScript clients in your server application, you will generally need to enable Cross Origin Resource Sharing (CORS). There are a number of ways of supporting this, so two are shown here:
|
If you are intending to support JavaScript clients in your server application, you will generally need to enable Cross Origin Resource Sharing (CORS). There are a number of ways of supporting this, so two are shown here:
|
||||||
|
|
||||||
* An approach using a HAPI FHIR Server Interceptor (Requires SpringFramework)
|
* An approach using a HAPI FHIR Server Interceptor (Requires SpringFramework)
|
||||||
* An approach using a servlet Filter (Container Specific)
|
* An approach using a servlet Filter (Container Specific)
|
||||||
|
|
||||||
## HAPI FHIR Server Interceptor
|
<a name="cors_interceptor"/>
|
||||||
|
|
||||||
|
# HAPI FHIR CORS Interceptor
|
||||||
|
|
||||||
The HAPI FHIR server framework includes an interceptor that can be used to provide CORS functionality on your server. This mechanism is nice because it relies purely on Java configuration (no messing around with web.xml files). HAPI's interceptor is a thin wrapper around Spring Framework's CorsProcessor class, so it requires Spring to be present on your classpath.
|
The HAPI FHIR server framework includes an interceptor that can be used to provide CORS functionality on your server. This mechanism is nice because it relies purely on Java configuration (no messing around with web.xml files). HAPI's interceptor is a thin wrapper around Spring Framework's CorsProcessor class, so it requires Spring to be present on your classpath.
|
||||||
|
|
||||||
Spring is generally unlikely to conflict with other libraries so it is usually safe to add it to your classpath, but it is a fairly large library so if size is a concern you might opt to use a filter instead.
|
Spring is generally unlikely to conflict with other libraries so it is usually safe to add it to your classpath, but it is a fairly large library so if size is a concern you might opt to use a filter instead.
|
||||||
|
|
||||||
|
* [CorsInterceptor JavaDoc](/apidocs/hapi-fhir-server/ca/uhn/fhir/rest/server/interceptor/CorsInterceptor.html)
|
||||||
|
* [CorsInterceptor Source](https://github.com/jamesagnew/hapi-fhir/blob/master/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/CorsInterceptor.java)
|
||||||
|
|
||||||
The following steps outline how to enable HAPI's CorsInterceptor:
|
The following steps outline how to enable HAPI's CorsInterceptor:
|
||||||
|
|
||||||
Add the following dependency to your POM. Note the exclusion of commons-logging, as we are using SLF4j without commons-logging in most of our examples. If your application uses commons-logging you don't need to exclude that dependency.
|
Add the following dependency to your POM. Note the exclusion of commons-logging, as we are using SLF4j without commons-logging in most of our examples. If your application uses commons-logging you don't need to exclude that dependency.
|
||||||
|
@ -39,7 +40,11 @@ In your server's initialization method, create and register a CorsInterceptor:
|
||||||
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/ServletExamples.java|corsInterceptor}}
|
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/ServletExamples.java|corsInterceptor}}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Add the Dependency
|
# CORS Servlet Filter
|
||||||
|
|
||||||
|
<p class="doc_info_bubble">
|
||||||
|
Note that in previous revisions of HAPI FHIR documentation we recommended using the <a href="https://github.com/ebay/cors-filter">eBay CORS Filter</a>, but as of 2016 the eBay filter is no longer being maintained and contains known bugs. We now recommend against using this filter.
|
||||||
|
</p>
|
||||||
|
|
||||||
The following examples show how to use the Apache Tomcat CorsFilter to enable CORS support. The filter being used (`org.apache.catalina.filters.CorsFilter`) is bundled with Apache Tomcat so if you are deploying to that server you can use the filter.
|
The following examples show how to use the Apache Tomcat CorsFilter to enable CORS support. The filter being used (`org.apache.catalina.filters.CorsFilter`) is bundled with Apache Tomcat so if you are deploying to that server you can use the filter.
|
||||||
|
|
|
@ -2,6 +2,9 @@
|
||||||
|
|
||||||
HAPI FHIR 3.7.0 introduced a new interceptor, the [SearchNarrowingInterceptor](/hapi-fhir/apidocs/hapi-fhir-server/ca/uhn/fhir/rest/server/interceptor/auth/SearchNarrowingInterceptor.html).
|
HAPI FHIR 3.7.0 introduced a new interceptor, the [SearchNarrowingInterceptor](/hapi-fhir/apidocs/hapi-fhir-server/ca/uhn/fhir/rest/server/interceptor/auth/SearchNarrowingInterceptor.html).
|
||||||
|
|
||||||
|
* [SearchNarrowingInterceptor JavaDoc](/apidocs/hapi-fhir-server/ca/uhn/fhir/rest/server/interceptor/auth/SearchNarrowingInterceptor.html)
|
||||||
|
* [SearchNarrowingInterceptor Source](https://github.com/jamesagnew/hapi-fhir/blob/master/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/auth/SearchNarrowingInterceptor.java)
|
||||||
|
|
||||||
This interceptor is designed to be used in conjunction with AuthorizationInterceptor. It uses a similar strategy where a dynamic list is built up for each request, but the purpose of this interceptor is to modify client searches that are received (after HAPI FHIR received the HTTP request, but before the search is actually performed) to restrict the search to only search for specific resources or compartments that the user has access to.
|
This interceptor is designed to be used in conjunction with AuthorizationInterceptor. It uses a similar strategy where a dynamic list is built up for each request, but the purpose of this interceptor is to modify client searches that are received (after HAPI FHIR received the HTTP request, but before the search is actually performed) to restrict the search to only search for specific resources or compartments that the user has access to.
|
||||||
|
|
||||||
This could be used, for example, to allow the user to perform a search for:
|
This could be used, for example, to allow the user to perform a search for:
|
||||||
|
@ -13,7 +16,7 @@ http://baseurl/Observation?category=laboratory
|
||||||
...and then receive results as though they had requested:
|
...and then receive results as though they had requested:
|
||||||
|
|
||||||
```url
|
```url
|
||||||
http://baseurl/Observation?subject=Patient/123&category=laboratory
|
http://baseurl/Observation?subject=Patient/123&category=laboratory
|
||||||
```
|
```
|
||||||
|
|
||||||
An example of this interceptor follows:
|
An example of this interceptor follows:
|
|
@ -1,3 +1,6 @@
|
||||||
# Getting Started with HAPI FHIR JPA Server
|
# Getting Started with HAPI FHIR JPA Server
|
||||||
|
|
||||||
The recommended way to get started with the JPA Server is to use the [hapi-fhir-jpaserver-starter](https://github.com/hapifhir/hapi-fhir-jpaserver-starter
|
The recommended way to get started with the HAPI FHIR JPA server module is
|
||||||
|
to begin with the starter project. This project can be found at the following link: [https://github.com/hapifhir/hapi-fhir-jpaserver-starter](https://github.com/hapifhir/hapi-fhir-jpaserver-starter)
|
||||||
|
|
||||||
|
This project is a fully contained FHIR server, supporting all standard operations (read/create/delete/etc). It bundles an embedded instance of the [H2 Java Database](http://h2database.com) so that the server can run without depending on any external database, but it can also be configured to use an installation of Oracle, Postgres, etc.
|
||||||
|
|
|
@ -4,13 +4,6 @@ The HAPI FHIR [Plain Server](/hapi-fhir/docs/server_plain/introduction.html) mod
|
||||||
|
|
||||||
HAPI also provides a persistence module which can be used to provide a complete RESTful server implementation, backed by a database of your choosing. This module uses the [JPA 2.0](http://en.wikipedia.org/wiki/Java_Persistence_API) API to store data in a database without depending on any specific database technology.
|
HAPI also provides a persistence module which can be used to provide a complete RESTful server implementation, backed by a database of your choosing. This module uses the [JPA 2.0](http://en.wikipedia.org/wiki/Java_Persistence_API) API to store data in a database without depending on any specific database technology.
|
||||||
|
|
||||||
# Getting Started
|
|
||||||
|
|
||||||
The recommended way to get started with HAPI's JPA server module is
|
|
||||||
to begin with the starter project. This project can be found at the following link: [https://github.com/hapifhir/hapi-fhir-jpaserver-starter](https://github.com/hapifhir/hapi-fhir-jpaserver-starter)
|
|
||||||
|
|
||||||
This project is a fully contained FHIR server, supporting all standard operations (read/create/delete/etc). It bundles an embedded instance of the <a href="http://h2database.com">H2 Java Database</a> so that the server can run without depending on any external database, but it can also be configured to use an installation of Oracle, Postgres, etc.
|
|
||||||
|
|
||||||
# Configuration Options
|
# Configuration Options
|
||||||
|
|
||||||
## External/Absolute Resource References
|
## External/Absolute Resource References
|
||||||
|
|
|
@ -32,6 +32,9 @@ import javax.servlet.ServletException;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.interceptor.api.Hook;
|
||||||
|
import ca.uhn.fhir.interceptor.api.Interceptor;
|
||||||
|
import ca.uhn.fhir.interceptor.api.Pointcut;
|
||||||
import ca.uhn.fhir.parser.DataFormatException;
|
import ca.uhn.fhir.parser.DataFormatException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
import ca.uhn.fhir.rest.server.method.BaseResourceReturningMethodBinding;
|
import ca.uhn.fhir.rest.server.method.BaseResourceReturningMethodBinding;
|
||||||
|
@ -48,13 +51,14 @@ import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.UnclassifiedServerFailureException;
|
import ca.uhn.fhir.rest.server.exceptions.UnclassifiedServerFailureException;
|
||||||
import ca.uhn.fhir.util.OperationOutcomeUtil;
|
import ca.uhn.fhir.util.OperationOutcomeUtil;
|
||||||
|
|
||||||
public class ExceptionHandlingInterceptor extends InterceptorAdapter {
|
@Interceptor
|
||||||
|
public class ExceptionHandlingInterceptor {
|
||||||
|
|
||||||
public static final String PROCESSING = Constants.OO_INFOSTATUS_PROCESSING;
|
public static final String PROCESSING = Constants.OO_INFOSTATUS_PROCESSING;
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ExceptionHandlingInterceptor.class);
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ExceptionHandlingInterceptor.class);
|
||||||
private Class<?>[] myReturnStackTracesForExceptionTypes;
|
private Class<?>[] myReturnStackTracesForExceptionTypes;
|
||||||
|
|
||||||
@Override
|
@Hook(Pointcut.SERVER_HANDLE_EXCEPTION)
|
||||||
public boolean handleException(RequestDetails theRequestDetails, BaseServerResponseException theException, HttpServletRequest theRequest, HttpServletResponse theResponse) throws ServletException, IOException {
|
public boolean handleException(RequestDetails theRequestDetails, BaseServerResponseException theException, HttpServletRequest theRequest, HttpServletResponse theResponse) throws ServletException, IOException {
|
||||||
Closeable writer = (Closeable) handleException(theRequestDetails, theException);
|
Closeable writer = (Closeable) handleException(theRequestDetails, theException);
|
||||||
writer.close();
|
writer.close();
|
||||||
|
@ -100,7 +104,7 @@ public class ExceptionHandlingInterceptor extends InterceptorAdapter {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Hook(Pointcut.SERVER_PRE_PROCESS_OUTGOING_EXCEPTION)
|
||||||
public BaseServerResponseException preProcessOutgoingException(RequestDetails theRequestDetails, Throwable theException, HttpServletRequest theServletRequest) throws ServletException {
|
public BaseServerResponseException preProcessOutgoingException(RequestDetails theRequestDetails, Throwable theException, HttpServletRequest theServletRequest) throws ServletException {
|
||||||
BaseServerResponseException retVal;
|
BaseServerResponseException retVal;
|
||||||
if (theException instanceof DataFormatException) {
|
if (theException instanceof DataFormatException) {
|
||||||
|
|
|
@ -41,7 +41,7 @@ public class CompressOutgoingContentInterceptorTest {
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreate() throws Exception {
|
public void testCreate() {
|
||||||
ourClient.registerInterceptor(new GZipContentInterceptor());
|
ourClient.registerInterceptor(new GZipContentInterceptor());
|
||||||
|
|
||||||
Patient p = new Patient();
|
Patient p = new Patient();
|
||||||
|
|
|
@ -0,0 +1,116 @@
|
||||||
|
package ca.uhn.fhir.rest.client.interceptor;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.rest.api.Constants;
|
||||||
|
import ca.uhn.fhir.rest.client.api.IGenericClient;
|
||||||
|
import ca.uhn.fhir.rest.client.api.ServerValidationModeEnum;
|
||||||
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import org.apache.commons.io.input.ReaderInputStream;
|
||||||
|
import org.apache.http.HttpResponse;
|
||||||
|
import org.apache.http.ProtocolVersion;
|
||||||
|
import org.apache.http.client.HttpClient;
|
||||||
|
import org.apache.http.client.methods.HttpGet;
|
||||||
|
import org.apache.http.client.methods.HttpUriRequest;
|
||||||
|
import org.apache.http.message.BasicHeader;
|
||||||
|
import org.apache.http.message.BasicStatusLine;
|
||||||
|
import org.hamcrest.Matchers;
|
||||||
|
import org.hl7.fhir.r4.model.Bundle;
|
||||||
|
import org.junit.AfterClass;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
|
import org.mockito.internal.stubbing.defaultanswers.ReturnsDeepStubs;
|
||||||
|
|
||||||
|
import java.io.StringReader;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
public class AdditionalHeadersInterceptorTest {
|
||||||
|
|
||||||
|
private FhirContext ctx;
|
||||||
|
private HttpClient httpClient;
|
||||||
|
private HttpResponse httpResponse;
|
||||||
|
|
||||||
|
// atom-document-large.xml
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void before() {
|
||||||
|
ctx = FhirContext.forR4();
|
||||||
|
|
||||||
|
httpClient = mock(HttpClient.class, new ReturnsDeepStubs());
|
||||||
|
ctx.getRestfulClientFactory().setHttpClient(httpClient);
|
||||||
|
ctx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER);
|
||||||
|
|
||||||
|
httpResponse = mock(HttpResponse.class, new ReturnsDeepStubs());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNoHeaders() throws Exception {
|
||||||
|
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||||
|
when(httpClient.execute(capt.capture())).thenReturn(httpResponse);
|
||||||
|
when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||||
|
when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML_NEW + "; charset=UTF-8"));
|
||||||
|
when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(createBundle()), StandardCharsets.UTF_8));
|
||||||
|
|
||||||
|
IGenericClient client = ctx.newRestfulGenericClient("http://foo");
|
||||||
|
|
||||||
|
client.registerInterceptor(new AdditionalRequestHeadersInterceptor());
|
||||||
|
|
||||||
|
client.search().forResource("Patient").returnBundle(Bundle.class).execute();
|
||||||
|
|
||||||
|
assertEquals(HttpGet.class, capt.getValue().getClass());
|
||||||
|
HttpGet get = (HttpGet) capt.getValue();
|
||||||
|
assertEquals("http://foo/Patient", get.getURI().toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testManyHeaders() throws Exception {
|
||||||
|
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||||
|
when(httpClient.execute(capt.capture())).thenReturn(httpResponse);
|
||||||
|
when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||||
|
when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML_NEW + "; charset=UTF-8"));
|
||||||
|
when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(createBundle()), StandardCharsets.UTF_8));
|
||||||
|
|
||||||
|
IGenericClient client = ctx.newRestfulGenericClient("http://foo");
|
||||||
|
|
||||||
|
Map<String, List<String>> map = new HashMap<>();
|
||||||
|
map.put("X-0", Lists.newArrayList("X-0-VAL"));
|
||||||
|
|
||||||
|
AdditionalRequestHeadersInterceptor interceptor = new AdditionalRequestHeadersInterceptor(map);
|
||||||
|
client.registerInterceptor(interceptor);
|
||||||
|
|
||||||
|
interceptor.addHeaderValue("X-1", "X-1-VAL");
|
||||||
|
interceptor.addAllHeaderValues("X-2", Lists.newArrayList("X-2-VAL1", "X-2-VAL2"));
|
||||||
|
|
||||||
|
client.search().forResource("Patient").returnBundle(Bundle.class).execute();
|
||||||
|
|
||||||
|
assertEquals(HttpGet.class, capt.getValue().getClass());
|
||||||
|
HttpGet get = (HttpGet) capt.getValue();
|
||||||
|
assertEquals("http://foo/Patient", get.getURI().toString());
|
||||||
|
|
||||||
|
assertThat(Arrays.asList(get.getHeaders("X-0")), Matchers.contains("X-0-VAL"));
|
||||||
|
assertThat(Arrays.asList(get.getHeaders("X-1")), Matchers.contains("X-1-VAL"));
|
||||||
|
assertThat(Arrays.asList(get.getHeaders("X-2")), Matchers.contains("X-2-VAL1", "X-2-VAL2"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String createBundle() {
|
||||||
|
return ctx.newXmlParser().encodeResourceToString(new Bundle().setTotal(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void afterClassClearContext() {
|
||||||
|
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -58,6 +58,17 @@
|
||||||
The constructor for Verdict.java was inadvertantly made private, preventing custom
|
The constructor for Verdict.java was inadvertantly made private, preventing custom
|
||||||
rules from being written. Thanks to Jafer Khan for the pull request!
|
rules from being written. Thanks to Jafer Khan for the pull request!
|
||||||
</action>
|
</action>
|
||||||
|
<action type="change">
|
||||||
|
The
|
||||||
|
<![CDATA[
|
||||||
|
<code>IRestfulClient#registerInterceptor</code>
|
||||||
|
and
|
||||||
|
<code>IRestfulClient#unregisterInterceptor</code>
|
||||||
|
]]>
|
||||||
|
methods now take Object as an argument instead of IClientInterceptor, allowing
|
||||||
|
client interceptors to now be migrated to the new interceptor
|
||||||
|
framework.
|
||||||
|
</action>
|
||||||
</release>
|
</release>
|
||||||
<release version="4.1.0" date="2019-11-13" description="Jitterbug">
|
<release version="4.1.0" date="2019-11-13" description="Jitterbug">
|
||||||
<action type="add">
|
<action type="add">
|
||||||
|
|
|
@ -1,105 +1,107 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<document xmlns="http://maven.apache.org/XDOC/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
<document xmlns="http://maven.apache.org/XDOC/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
|
xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
|
||||||
|
|
||||||
<properties>
|
<!-- this content has been migrated -->
|
||||||
<title>RESTful Client</title>
|
|
||||||
<author email="jamesagnew@users.sourceforge.net">James Agnew</author>
|
<properties>
|
||||||
</properties>
|
<title>RESTful Client</title>
|
||||||
|
<author email="jamesagnew@users.sourceforge.net">James Agnew</author>
|
||||||
<body>
|
</properties>
|
||||||
|
|
||||||
<section name="Client Interceptors">
|
<body>
|
||||||
|
|
||||||
<p>
|
<section name="Client Interceptors">
|
||||||
Both generic clients and annotation-driven clients support
|
|
||||||
<a href="./apidocs/ca/uhn/fhir/rest/client/IClientInterceptor.html">Client Interceptors</a>,
|
<p>
|
||||||
which may be registered in order to provide specific behaviour to each
|
Both generic clients and annotation-driven clients support
|
||||||
client request.
|
<a href="./apidocs/ca/uhn/fhir/rest/client/IClientInterceptor.html">Client Interceptors</a>,
|
||||||
</p>
|
which may be registered in order to provide specific behaviour to each
|
||||||
|
client request.
|
||||||
<p>
|
</p>
|
||||||
The following section shows some sample interceptors which may be used.
|
|
||||||
</p>
|
<p>
|
||||||
|
The following section shows some sample interceptors which may be used.
|
||||||
<subsection name="Security: HTTP Basic Authorization">
|
</p>
|
||||||
|
|
||||||
<p>
|
<subsection name="Security: HTTP Basic Authorization">
|
||||||
The following example shows how to configure your client to
|
|
||||||
use a specific username and password in every request.
|
<p>
|
||||||
</p>
|
The following example shows how to configure your client to
|
||||||
|
use a specific username and password in every request.
|
||||||
<macro name="snippet">
|
</p>
|
||||||
<param name="id" value="security" />
|
|
||||||
<param name="file" value="examples/src/main/java/example/ClientExamples.java" />
|
<macro name="snippet">
|
||||||
</macro>
|
<param name="id" value="security" />
|
||||||
|
<param name="file" value="examples/src/main/java/example/ClientExamples.java" />
|
||||||
</subsection>
|
</macro>
|
||||||
|
|
||||||
<subsection name="Security: HTTP Bearer Token Authorization">
|
</subsection>
|
||||||
|
|
||||||
<p>
|
<subsection name="Security: HTTP Bearer Token Authorization">
|
||||||
The following example shows how to configure your client to
|
|
||||||
inject a bearer token authorization header into every request. This
|
<p>
|
||||||
is used to satisfy servers which are protected using OAUTH2.
|
The following example shows how to configure your client to
|
||||||
</p>
|
inject a bearer token authorization header into every request. This
|
||||||
|
is used to satisfy servers which are protected using OAUTH2.
|
||||||
<macro name="snippet">
|
</p>
|
||||||
<param name="id" value="securityBearer" />
|
|
||||||
<param name="file" value="examples/src/main/java/example/ClientExamples.java" />
|
<macro name="snippet">
|
||||||
</macro>
|
<param name="id" value="securityBearer" />
|
||||||
|
<param name="file" value="examples/src/main/java/example/ClientExamples.java" />
|
||||||
</subsection>
|
</macro>
|
||||||
|
|
||||||
<a name="req_resp_logging"/>
|
</subsection>
|
||||||
<subsection name="Logging: Log Requests and Responses">
|
|
||||||
|
<a name="req_resp_logging"/>
|
||||||
<p>
|
<subsection name="Logging: Log Requests and Responses">
|
||||||
The <code>LoggingInterceptor</code> can be used to
|
|
||||||
log every transaction. The interceptor is flexible and can be configured to be extremely
|
<p>
|
||||||
verbose (logging entire transactions including HTTP headers and payload bodies)
|
The <code>LoggingInterceptor</code> can be used to
|
||||||
or simply to log request URLs, or some combination in between.
|
log every transaction. The interceptor is flexible and can be configured to be extremely
|
||||||
</p>
|
verbose (logging entire transactions including HTTP headers and payload bodies)
|
||||||
|
or simply to log request URLs, or some combination in between.
|
||||||
<macro name="snippet">
|
</p>
|
||||||
<param name="id" value="logging" />
|
|
||||||
<param name="file" value="examples/src/main/java/example/ClientExamples.java" />
|
<macro name="snippet">
|
||||||
</macro>
|
<param name="id" value="logging" />
|
||||||
|
<param name="file" value="examples/src/main/java/example/ClientExamples.java" />
|
||||||
</subsection>
|
</macro>
|
||||||
|
|
||||||
<subsection name="Cookies: Add an HTTP Cookie Header to Client Requests">
|
</subsection>
|
||||||
|
|
||||||
<p>
|
<subsection name="Cookies: Add an HTTP Cookie Header to Client Requests">
|
||||||
The <code>CookieInterceptor</code> can be used to
|
|
||||||
add an HTTP Cookie header to each request created by the client.
|
<p>
|
||||||
</p>
|
The <code>CookieInterceptor</code> can be used to
|
||||||
|
add an HTTP Cookie header to each request created by the client.
|
||||||
<macro name="snippet">
|
</p>
|
||||||
<param name="id" value="cookie" />
|
|
||||||
<param name="file" value="examples/src/main/java/example/ClientExamples.java" />
|
<macro name="snippet">
|
||||||
</macro>
|
<param name="id" value="cookie" />
|
||||||
|
<param name="file" value="examples/src/main/java/example/ClientExamples.java" />
|
||||||
</subsection>
|
</macro>
|
||||||
|
|
||||||
<subsection name="Performance: GZip Outgoing Request Bodies">
|
</subsection>
|
||||||
|
|
||||||
<p>
|
<subsection name="Performance: GZip Outgoing Request Bodies">
|
||||||
The <code>GZipContentInterceptor</code> compresses outgoing contents.
|
|
||||||
With this interceptor, if the client is transmitting resources to the server
|
<p>
|
||||||
(e.g. for a create, update, transaction, etc.) the content will be GZipped
|
The <code>GZipContentInterceptor</code> compresses outgoing contents.
|
||||||
before transmission to the server.
|
With this interceptor, if the client is transmitting resources to the server
|
||||||
</p>
|
(e.g. for a create, update, transaction, etc.) the content will be GZipped
|
||||||
|
before transmission to the server.
|
||||||
<macro name="snippet">
|
</p>
|
||||||
<param name="id" value="gzip" />
|
|
||||||
<param name="file" value="examples/src/main/java/example/ClientExamples.java" />
|
<macro name="snippet">
|
||||||
</macro>
|
<param name="id" value="gzip" />
|
||||||
|
<param name="file" value="examples/src/main/java/example/ClientExamples.java" />
|
||||||
</subsection>
|
</macro>
|
||||||
|
|
||||||
</section>
|
</subsection>
|
||||||
|
|
||||||
</body>
|
</section>
|
||||||
|
|
||||||
</document>
|
</body>
|
||||||
|
|
||||||
|
</document>
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<document xmlns="http://maven.apache.org/XDOC/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
|
<document xmlns="http://maven.apache.org/XDOC/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
|
||||||
|
|
||||||
|
<!-- This content is migrated -->
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<title>Server Interceptors</title>
|
<title>Server Interceptors</title>
|
||||||
<author email="jamesagnew@users.sourceforge.net">James Agnew</author>
|
<author email="jamesagnew@users.sourceforge.net">James Agnew</author>
|
||||||
|
|
|
@ -94,7 +94,7 @@
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
HAPI FHIR 1.5 introduced a new interceptor, the
|
HAPI FHIR 1.5 introduced a new interceptor, the
|
||||||
<a href="./apidocs-server/ca/uhn/fhir/rest/server/interceptor/auth/AuthorizationInterceptor.html">AuthorizationInterceptor</a>.
|
<a href="/apidocs/hapi-fhir-server/ca/uhn/fhir/rest/server/interceptor/auth/AuthorizationInterceptor.html">AuthorizationInterceptor</a>.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
This interceptor can help with the complicated task of determining whether a user
|
This interceptor can help with the complicated task of determining whether a user
|
||||||
|
|
Loading…
Reference in New Issue