在不使用 Undertow 的情况下读取 POST 请求
Reading a POST request in Undertow without consuming it
在 Undertow 中,我有两个链接的处理程序:
- 第一个处理程序读取请求,然后通过
next.handleRequest(exchange);
调用第二个处理程序
- 第二个处理程序是代理处理程序,它将请求发送到处理请求的外部服务器。
我的问题是读取请求的第一个处理程序。请求 headers 没什么大不了的,但是获取 POST 请求的 body 数据是个问题。
问题 How to properly read POST request body in a Handler? 中所示的现有解决方案消耗了请求 body su,处理程序链接不再起作用。
如何读取请求 body 数据而不使用它或以处理程序链之后无法工作的方式更改请求?
找到问题了,最后是ByteBuffer.flip()
.
的漏接
如果有人需要这样的 POST 数据 reader 可以使用以下简化的 AbstractStreamSourceConduit
实现,它能够读取传入的 POST 数据而无需消耗它:
exchange.addRequestWrapper(new ConduitWrapper<StreamSourceConduit>() {
@Override
public StreamSourceConduit wrap(ConduitFactory<StreamSourceConduit> factory, HttpServerExchange exchange) {
StreamSourceConduit source = factory.create();
return new AbstractStreamSourceConduit<StreamSourceConduit>(source) {
ByteArrayOutputStream bout = new ByteArrayOutputStream(8192);
@Override
public int read(ByteBuffer dst) throws IOException {
int x = super.read(dst);
if (x >= 0) {
ByteBuffer dup = dst.duplicate();
dup.flip();
byte[] data = new byte[x];
dup.get(data);
bout.write(data);
} else {
// end of stream reached
byte[] data = bout.toByteArray();
// ... to something with data
}
return x;
}
};
}
});
在 Undertow 中,我有两个链接的处理程序:
- 第一个处理程序读取请求,然后通过
next.handleRequest(exchange);
调用第二个处理程序
- 第二个处理程序是代理处理程序,它将请求发送到处理请求的外部服务器。
我的问题是读取请求的第一个处理程序。请求 headers 没什么大不了的,但是获取 POST 请求的 body 数据是个问题。
问题 How to properly read POST request body in a Handler? 中所示的现有解决方案消耗了请求 body su,处理程序链接不再起作用。
如何读取请求 body 数据而不使用它或以处理程序链之后无法工作的方式更改请求?
找到问题了,最后是ByteBuffer.flip()
.
如果有人需要这样的 POST 数据 reader 可以使用以下简化的 AbstractStreamSourceConduit
实现,它能够读取传入的 POST 数据而无需消耗它:
exchange.addRequestWrapper(new ConduitWrapper<StreamSourceConduit>() {
@Override
public StreamSourceConduit wrap(ConduitFactory<StreamSourceConduit> factory, HttpServerExchange exchange) {
StreamSourceConduit source = factory.create();
return new AbstractStreamSourceConduit<StreamSourceConduit>(source) {
ByteArrayOutputStream bout = new ByteArrayOutputStream(8192);
@Override
public int read(ByteBuffer dst) throws IOException {
int x = super.read(dst);
if (x >= 0) {
ByteBuffer dup = dst.duplicate();
dup.flip();
byte[] data = new byte[x];
dup.get(data);
bout.write(data);
} else {
// end of stream reached
byte[] data = bout.toByteArray();
// ... to something with data
}
return x;
}
};
}
});