我可以在Glassfish(或任何应用程序服务器)上拦截对我的WSDL的调用吗? [英] Can I intercept calls for my WSDL on Glassfish (or on any app server)?
问题描述
我使用 @WebService
注释创建了一个Java web服务,并将该服务部署到位于代理服务器后面的Glassfish服务器中。
问题是当某人访问我们的WSDL并查看他们看到的服务端点地址位置时, > http:// app server url / service ...
而不是
http://代理服务器网址/服务...
我希望在WSDL的服务端点地址位置中返回代理服务器URL,而不是应用服务器url。
我想知道的是,我可以编写一个Filter或Listener来侦听对WSDL的请求,然后使用代理服务器URL修改WSDL服务端点地址吗?推荐的方法是什么 - 我认为过滤器是最好的选择,但不是100%确定?
顺便说一句 - 我想可能会有Glassfish中的一个简单设置来执行此操作,但我一直无法找到一个工程。
我采取了过滤方法,这就是我想出的。这似乎工作。
我已经包含了我的 Filter 的
方法。我也写了一个自定义的 HttpServletResponseWrapper
,但是这个实现非常简单。
$ b
Apache反向代理添加 x -forwarded-host
值添加到HTTP标头(并且是我用来替换应用程序服务器名称的名称)。我想到的另一种选择是将代理服务器的地址作为应用服务器上的一个属性,并抓住它。最终,我认为这是一种更干净的方式。
/ *
*用代理替换服务器URL服务器URL从代理服务器调用
* /
@Override
public void doFilter(
ServletRequest请求,
ServletResponse响应,
FilterChain filterChain)throws IOException,ServletException
{
WsdlResponseWrapper myResponse = new WsdlResponseWrapper((HttpServletResponse)response);
filterChain.doFilter(request,myResponse);
boolean isResponseOutputStream = myResponse.getOutputStreamContent()。length> 0;
/ *
*发送到此方法的servlet响应只允许访问
* getOutputStream或getWriter,而不是两者。如果试图访问两者,它将抛出
*异常。
*
*如果出于这个原因,我首先检查输出流并写入
*表示内容(如果存在),然后仅在
*输出流是空的。
* /
StringBuffer responseBuffer;
if(isResponseOutputStream){
responseBuffer = new StringBuffer(new String(myResponse.getOutputStreamContent()));
} else {
responseBuffer = new StringBuffer(myResponse.getWriterContent());
}
//当从代理服务器调用时更改URL
if(request instanceof HttpServletRequest){
HttpServletRequest httpServletRequest =(HttpServletRequest)请求;
String requestedHostname = httpServletRequest.getHeader(x-forwarded-host); ((null!= requestedHostname)&&!requestedHostname.isEmpty()){
String myHostname = httpServletRequest.getHeader(host);
int myPort = httpServletRequest.getLocalPort();
//更改主机名
int index = responseBuffer.indexOf(myHostname);
int length = myHostname.length();
while(index> -1){
responseBuffer.replace(index,index + length,requestedHostname);
index = responseBuffer.indexOf(myHostname);
}
//删除端口
String portString =:+ myPort;
length = portString.length();
index = responseBuffer.indexOf(portString);
while(index> -1){
responseBuffer.replace(index,index + length,);
index = responseBuffer.indexOf(portString);
$ b //转发响应
if(isResponseOutputStream){
response.getOutputStream()。write(responseBuffer 。的ToString()的getBytes());
} else {
response.getWriter()。print(responseBuffer);
}
}
I've created a Java web service using the @WebService
annotation and deployed the service to a Glassfish server that lives behind a proxy server.
The problem is when someone accesses our WSDL and looks at the service endpoint address location they see
http://app server url/service...
instead of
http://proxy server url/service...
I'd like to have the proxy server URL returned in the service endpoint address location of the WSDL instead of the app server url.
What I'm wondering is, can I write a Filter or a Listener to listen for requests to the WSDL, then modify the WSDL service endpoint address with the proxy server URL? What might be the recommended way to do this - I was thinking a Filter is the best choice, but wasn't 100% sure?
BTW - I thought there might be a simple setting in Glassfish to do this, but I haven't been able to locate one that works.
I took the filter approach and here's what I came up with. It seems to work.
I've included the code for my Filter
's doFilter
method. I also wrote a custom HttpServletResponseWrapper
, but that implementation was pretty straightforward.
the Apache reverse-proxy adds the x-forwarded-host
value to the HTTP header (and is the name I use to replace the app servers name). Another alternative I thought of was to place the proxy server's address as a property on the app server and grab that. Ultimately, I thought this was a cleaner way to go.
/*
* Replace the server URL with the proxy server URL when called from a proxy server
*/
@Override
public void doFilter(
ServletRequest request,
ServletResponse response,
FilterChain filterChain) throws IOException, ServletException
{
WsdlResponseWrapper myResponse = new WsdlResponseWrapper((HttpServletResponse) response);
filterChain.doFilter(request, myResponse);
boolean isResponseOutputStream = myResponse.getOutputStreamContent().length > 0;
/*
* The servlet response sent into this method only allows access to
* getOutputStream or getWriter, not both. It will throw an
* exception if an attempt is made to to access both.
*
* If this reason, I'm checking the output stream first and writing
* that content if it exists, then printing to the writer only if
* the output stream is empty.
*/
StringBuffer responseBuffer;
if (isResponseOutputStream) {
responseBuffer = new StringBuffer(new String(myResponse.getOutputStreamContent()));
} else {
responseBuffer = new StringBuffer(myResponse.getWriterContent());
}
// Change the URL when called from a proxy server
if (request instanceof HttpServletRequest) {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
String requestedHostname = httpServletRequest.getHeader("x-forwarded-host");
if ((null != requestedHostname) && !requestedHostname.isEmpty()) {
String myHostname = httpServletRequest.getHeader("host");
int myPort = httpServletRequest.getLocalPort();
// change the hostname
int index = responseBuffer.indexOf(myHostname);
int length = myHostname.length();
while (index > -1) {
responseBuffer.replace(index, index+length, requestedHostname);
index = responseBuffer.indexOf(myHostname);
}
// remove the port
String portString = ":" + myPort;
length = portString.length();
index = responseBuffer.indexOf(portString);
while (index > -1) {
responseBuffer.replace(index, index+length, "");
index = responseBuffer.indexOf(portString);
}
}
}
// forward the response
if (isResponseOutputStream) {
response.getOutputStream().write(responseBuffer.toString().getBytes());
} else {
response.getWriter().print(responseBuffer);
}
}
这篇关于我可以在Glassfish(或任何应用程序服务器)上拦截对我的WSDL的调用吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!