在我的开发环境中,我正在为前端和后端使用两个独立的技术堆栈:
localhost:8081
localhost:7080
为基础提供HTTP端点,有两种方式:
http:inbound-channel-adapter
开始(请参阅以下XML配置)@RestController
- 带注释的类实现)前端仅使用fetch()
次调用与后端进行互动。
在不同的端口上,浏览器在没有正确的CORS配置的情况下阻止对HTTP端点的任何请求。由于这将是暂时的,我试图提出最简单/最快的解决方案,我设法使REST API调用工作,但入站适配器仍然在OPTIONS请求期间出现问题。
webapp有两个部分:
这是当前的Spring Integration配置(我使用的是5.0.3版):
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ctx="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-file="http://www.springframework.org/schema/integration/file"
xmlns:int-jdbc="http://www.springframework.org/schema/integration/jdbc"
xmlns:int-sftp="http://www.springframework.org/schema/integration/sftp"
xmlns:int-http="http://www.springframework.org/schema/integration/http"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="...">
<!-- ... -->
<int-http:inbound-channel-adapter id="httpInboundAdapter"
channel="httpRequestsChannel"
path="/services/requests"
supported-methods="POST">
<int-http:cross-origin allow-credentials="false" allowed-headers="*" origin="*" />
</int-http:inbound-channel-adapter>
<int:channel id="httpRequestsChannel" />
<int:chain input-channel="httpRequestsChannel" id="httpRequestsChain">
<int:transformer method="transform">
<bean class="transformers.RequestToMessageFile" />
</int:transformer>
<!-- ... -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" />
<!-- ... -->
</beans>
这就是其中一个REST端点的完成方式:
package api;
// imports
@CrossOrigin(origins = "*", maxAge = 3600)
@RestController
@RequestMapping(path="/api/requests", produces="application/json")
public class RequestController {
// ...
这是应该处理POSTed文件的转换器:
package transformers;
// imports
public class RequestToMessageFile {
private static final String ALLOW_DUPES = "allowDuplicateFilenames";
public Message<?> transform(LinkedMultiValueMap<String, Object> multipartRequest) {
File file = null;
int tx = -1;
String localFilename = null;
for (String elementName : multipartRequest.keySet()) {
if (RequestFields.TRANSACTION_TYPE.equals(elementName)) {
tx = Integer.valueOf(((String[]) multipartRequest.getFirst(RequestFields.TRANSACTION_TYPE))[0]);
} else if (RequestFields.FILE.equals(elementName)){
try {
UploadedMultipartFile uploadedFile = (UploadedMultipartFile) multipartRequest.getFirst(RequestFields.FILE);
// file handling
file = new File(/* ... */);
uploadedFile.transferTo(file);
} catch (IllegalStateException e) {
LogManager.getLogger(getClass()).error(e, e);
} catch (IOException e) {
LogManager.getLogger(getClass()).error(e, e);
}
}
}
if(file != null) {
MessageBuilder<File> builder = MessageBuilder.withPayload(file);
// ...
Message<?> m = builder.build();
return m;
} else {
return MessageBuilder.withPayload(new Object()).build();
}
}
}
这就是我从浏览器调用端点的方式:
var data = new FormData();
data.append('transaction-type', this.state.transactionType);
data.append('file', this.state.file);
fetch('http://localhost:7080/services/requests?allowDuplicateFilenames=true', {
method: 'POST',
body: data,
mode: 'cors',
headers:{
'Accept': 'application/json',
},
}
)
.then(/* ... */)
.catch(/* ... */)
我所遇到的是在OPTIONS
请求期间调用变换器(我没想到),当然不携带任何主体,因此只有allowDuplicateFilenames
url参数存在。< / p>
由于无法确定文件,变换器正在返回消息withPayload(new Object())
,但请求在配置的通道和端点上继续前进,最终在空数据传递到最后时出现错误端点 - jdbc:outbound-channel-adapter
。
错误最终以HTTP 500错误的形式返回给客户端。
我希望只将POST
请求传递给http入站适配器,而OPTIONS
请求由框架处理,但这可能是错误的解释。
什么阻止POST请求成功?我的配置有问题吗?我是否应该处理OPTIONS
请求?
在后续尝试中,我已将Allow-Control-Allow-Origin: *
扩展程序添加到Chrome,并从前端headers
调用中删除了fetch()
参数。使用此设置,请求可以正常工作,因为浏览器只发出POST
。
我想添加对REST API的请求是成功的,因此CORS配置必须正确;虽然我认为http入站适配器具有与@RestController
相同的配置,但必须缺少某些内容。
我添加了另一个端点来专门处理OPTIONS
请求:
</int-http:inbound-channel-adapter>
<int-http:inbound-channel-adapter id="httpInboundAdapterOptions"
channel="nullChannel"
path="/services/requests"
supported-methods="OPTIONS">
<int-http:cross-origin allow-credentials="false" allowed-headers="*" origin="*" />
</int-http:inbound-channel-adapter>
现在收到OPTIONS
和POST
请求,后者启动整个集成数据处理;浏览器仍然抱怨丢失“Access-Control-Allow-Origin”
标题,从浏览器控制台我只能看到标题:
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Length: 0
Date: Tue, 08 May 2018 14:29:30 GMT
相比之下,REST端点上的GET
带来了这些:
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Vary: Origin
Access-Control-Allow-Origin: *
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Tue, 08 May 2018 14:29:08 GMT