FHIR Patch
FHIR Patch
背景介绍
在 HTTP 协议中,除了常见的请求方法GET、POST、PUT、DELETE,还有一些不常见的方法,例如:PATCH、HEAD等。它们各自具有不同的语义,有着不同的应用场景。我们今天要说的就是PATCH方法,用于部分更新,而非完整更新。在经过设计权衡之后还坚定的选择使用PATCH方法,无非就是基于性能和安全这两个业务场景。
PATCH 的工作原理是创建一个“补丁文档”,该文档指定客户端希望对资源进行的更改,并将其提交给服务器。然后,服务器将这些更改应用于指定的资源;或者,如果更改不合适,就拒绝更改。每个“补丁文档”要声明:
- 要执行的动作(add、remove)
- 资源中要执行动作的位置,也就是路径表达式。
- 新值(要添加的,或者要更改的)
在标准方面,RFC 5261: XML Patch Operations Framework Utilizing XPath Selectors 提供了XML格式的补丁文档定义,而RFC 6902: JSON Patch提供了JSON格式的补丁文档定义。
FHIR中的Patch应用
拿来主义
所以在FHIR规范之初,采用拿来主义,沿用了已有的RFC定义的补丁操作标准,存在两种Patch方式:
- JSON Patch
- XML Patch
PATCH操作虽然是部分更新,但也是属于更新操作。所以,在FHIR资源的版本管理上,PATCH操作和PUT操作是一致的,都会导致版本的增加。
兼容性问题
这两种Patch方式其实是与FHIR规范不兼容的。为什么这么说呢?从设计理念来讲,FHIR规范的实现应该是格式无关的,也就是说,无论是采用XML还是JSON格式,都应不影响处理逻辑实现。但是在Patch操作上,因为两种不同的补丁文档格式标准采用的路径表达式的不同,造成在实现时要按照不同格式标准分别进行路径的解析。其中,XML Patch中使用了XPath规范,而JSON Patch中使用了JSON Pointer规范。这种不同导致了实现时要根据不同路径表达方式给出不同实现方法。
FHIRPath的出现
2019年,HL7 发布了FHIR STU3版本,FHIRPath 正式进入FHIR规范体系,并且达到了标准化程度。既然FHIRPath 统一了路径的表达方式,那么增加一种Patch方法也就理所应当,实现无关性也就水到渠成。
我认为,在FHIRPath Patch出现之后,以上两种Patch方式终将退出历史舞台,如同早期使用Atom格式来表示资源的集合,现在也已经被Bundle类型所代替。
FHIR Patch 示例
下面是使用了JSON Patch格式的示例:
PATCH http://hapi.fhir.org/baseR5/Patient/95575
Content-Type: application/json-patch+json; charset=UTF-8
[{
"op": "add",
"path": "/birthDate",
"value": "2020-10-10"
}]
下面是使用了XML Patch格式的示例:
PATCH http://hapi.fhir.org/baseR5/Patient/95575
Content-Type: application/xml-patch+xml; charset=UTF-8
<patch xmlns:f="http://hl7.org/fhir">
<remove sel="f:Patient/f:birthDate"/>
</patch>
下面是使用了FHIRPath Patch格式的示例:
PATCH http://hapi.fhir.org/baseR5/Patient/95575
Content-Type: application/fhir+xml; charset=UTF-8
<Parameters xmlns="http://hl7.org/fhir">
<parameter>
<name value="operation"/>
<part>
<name value="type"/>
<valueCode value="replace"/>
</part>
<part>
<name value="path"/>
<valueString value="Patient.birthDate"/>
</part>
<part>
<name value="value"/>
<valueDate value="1930-01-01"/>
</part>
</parameter>x
</Parameters>
从上面的示例可以看到,行11-14记录的就是路径,遵循着FHIRPath规范。 这时格式是XML和JSON已经无关紧要,都不会对路径解析产生影响,也就达到了实现无关性。
写在后面的话
其实在FHIR规范中,进行资源的部分更新,除了使用Patch方法之外,还有很多使用Operation的例子。例如:$meta-add
和$meta-delete
。我认为如果使用Patch方法的主要因素是性能,那还可以。如果是基于安全考量,想得到更好的安全访问控制,那么我认为使用Operation方式才是最优解,因为可以在服务访问层级进行更细粒度访问权限的控制。
如果一定要使用FHIR的Patch方案,为了向后的兼容性,应尽量采用FHIRPath Patch方式。