当某个客户端尝试POST数据库中的重复实体时,Spring Data REST返回409状态代码和JSON异常体。
JpaRepository
@RepositoryRestResource
@PreAuthorize(whoCanPostAndUpdateTheirMessages)
public interface MessageRepository extends JpaRepository<Message, Long> {
}
请求
curl -u $AUTH -X POST -H "Content-Type:application/json" -d '{ "patient": "'$PATIENT_URL'", "date": "2014-01-01T00:00:0", "device": "00:00:00:00:00", "body": "this is a message" }' $SERVER/messages
响应
HTTP/1.1 409 Conflict
{
"cause" : {
"cause" : {
"cause" : null,
"message" : "ERROR: duplicate key value violates unique constraint \"uk_ofdr0s8f4x6q22veekngtwifd\"\n Detail: Key (date, device)=(2014-01-01 00:00:00, 00:00:00:00:00) already exists."
},
"message" : "could not execute statement"
},
"message" : "could not execute statement; SQL [n/a]; constraint [uk_ofdr0s8f4x6q22veekngtwifd]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement"
是否可以在响应正文中包含冲突实体(ID / URI),以便客户端知道稍后在该资源上执行PUT / PATCH的位置?
答案 0 :(得分:1)
我建议传回资源uri
位置标题
@RequestMapping(value="/create",method=RequestMethod.GET)
public ResponseEntity<?> create(@Valid Entity purchase ,BindingResult result){
boolean exits= false;
// you checks here
if(exits){
return ResponseEntity.status(HttpStatus.CONFLICT).header(HttpHeaders.LOCATION, "http://resource/id").build();
}
return ResponseEntity.created(new URI("http://resource/id")).build();
}
答案 1 :(得分:1)
使用服务器端验证手段来检测潜在的冲突(例如重复的用户名或电子邮件地址),并抛出一个有意义的异常,转换为体面的状态代码和消息。
一般情况下,如果没有必要,请不要向客户透露相关信息,因为这可能会成为攻击者利用的安全风险。
我不认为在此处返回POST
请求的其他信息是个好主意,因为您可能会在尝试创建实体时泄露有关现有实体的敏感信息。
在创建时,所有可能存在冲突的属性都应该通过服务器上的专用方式进行验证(即,如果它是使用相应事件和/或验证器的Spring Data REST),那么您实际上可以抛出适当的异常。如果您将无效数据流入您的数据库,您基本上无法获得有关哪个其他实体导致冲突的任何进一步信息。这基本上是将无效数据传递到整个应用程序堆栈的副作用,这不应该首先发生。
如果调用返回了有关现有实体的信息,则可以使用它来窥探其标识符(例如,尝试通过创建具有已知用户名的实体来查找已存在实体的ID)。对于PUT
和PATCH
请求,这略有不同,因为客户端已经知道首先发出请求的标识符。