简体   繁体   English

使用Apache CXF在SOAP POST请求中获取错误但curl工作正常

[英]Getting Error in SOAP POST request using Apache CXF but curl works

I'm having a very strange problem. 我有一个非常奇怪的问题。 I'm trying to do a SOAP POST request over HTTPS. 我正在尝试通过HTTPS执行SOAP POST请求。 When I'm sending the request from my code, I'm getting HTTP 500 error. 当我从我的代码发送请求时,我收到HTTP 500错误。 Now from the cxf log if I copy the same SOAP message(header and body) that I got error for and post it using a simple curl request it's working fine. 现在从cxf日志中,如果我复制了相同的SOAP消息(标题和正文),我得到了错误,并使用简单的curl请求发布它,它工作正常。 Below is how I'm creating service class and other initialization 下面是我如何创建服务类和其他初始化

URL wsdlurl = SOAPWebServiceTransport.class.getClassLoader().
        getResource("my.wsdl");
OnlinePort service= new OnlinePortService(wsdlurl).getOnlinePortPort();
Client proxy = ClientProxy.getClient(service);

// Provides WS-Security
WSS4JOutInterceptor wss4jOut = new WSS4JOutInterceptor();
wss4jOut.setProperty("action", "UsernameToken");
wss4jOut.setProperty("user", userName);
wss4jOut.setProperty("passwordType", "PasswordText");
wss4jOut.setProperty("password", password);
wss4jOut.setProperty(WSHandlerConstants.ADD_UT_ELEMENTS,
        WSConstants.NONCE_LN + " " + WSConstants.CREATED_LN);
wss4jOut.setProperty(WSHandlerConstants.PW_CALLBACK_CLASS, ServerPasswordCallback.class.getName());

proxy.getEndpoint().getOutInterceptors().add(wss4jOut);
setConduitProperties((HTTPConduit) proxy.getConduit(),url);

In the set conduit method I'm ignoring the ssl check (for development env only) and setting some header. 在set conduit方法中,我忽略了ssl检查(仅用于开发环境)并设置了一些标头。

TLSClientParameters tcp = new TLSClientParameters();
tcp.setDisableCNCheck(true);
// Creating Trust Manager
TrustManager[] trustAllCerts = new TrustManager[] {
    new X509TrustManager() {
        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
            return null;
        }

        public void checkClientTrusted(
                java.security.cert.X509Certificate[] certs, String authType) {
        }

        public void checkServerTrusted(
                java.security.cert.X509Certificate[] certs, String authType) {
        }
} };

tcp.setTrustManagers(trustAllCerts);
conduit.setTlsClientParameters(tcp);

HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
httpClientPolicy.setAllowChunking(false);
httpClientPolicy.setAccept("*/*");
httpClientPolicy.setContentType("text/xml;charset=UTF-8");
httpClientPolicy.setHost(url.split("/")[2]);
conduit.setClient(httpClientPolicy);

Any help would be highly appreciable. 任何帮助都会非常值得赞赏。

Response-Code: 500
Encoding: ISO-8859-1
Content-Type: text/html;charset=ISO-8859-1
Headers: {connection=[close], content-type=[text/html;charset=ISO-8859-1],
          Date=[Mon, 15 Jun 2015 06:42:09 GMT], Server=[Apache-Coyote/1.1],
          Set-Cookie=[JSESSIONID=FF0E4F5DCA42F700FFAC46BBD039FC20; Path=/; Secure],
          transfer-encoding=[chunked]}
Payload: 

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

> <html> <head> <meta http-equiv="Content-Type" content="text/html;
> charset=ISO-8859-1"/> <title>Error Page</title> </head> <body>Invalid
> Request </body> </html>


at org.apache.cxf.interceptor.StaxInInterceptor.handleMessage(StaxInInterceptor.java:79)
    at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:263)
    at org.apache.cxf.endpoint.ClientImpl.onMessage(ClientImpl.java:797)
    at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponseInternal(HTTPConduit.java:1618)
    at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponse(HTTPConduit.java:1491)
    at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1399)
    at org.apache.cxf.io.CacheAndWriteOutputStream.postClose(CacheAndWriteOutputStream.java:47)
    at org.apache.cxf.io.CachedOutputStream.close(CachedOutputStream.java:188)
    at org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:56)
    at org.apache.cxf.transport.http.HTTPConduit.close(HTTPConduit.java:646)
    at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:62)
    at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:263)
    at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:533)
    at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:463)
    at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:366)
    at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:319)
    at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:88)
    at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:134)
 Caused by: org.apache.cxf.interceptor.Fault: Response was of unexpected text/html ContentType.  Incoming portion of HTML stream: 

CURL Request CURL请求

curl -k --header "Content-Type: text/xml;charset=UTF-8" --header "SOAPAction:" --data @soaprequest.xml https://url curl -k --header“Content-Type:text / xml; charset = UTF-8”--header“SOAPAction:” - data @ soaprequest.xml https:// url

Curl log in verbose (ofcourse have changed some url port names0 卷曲登录详细 (当然已更改了一些URL端口名称0

Error response from server 服务器的错误响应

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
<title>Error Page</title>
</head>
<body>Invalid Request
</body>
</html> 

SOAP works on xml and I can see the you have the following error SOAP适用于xml,我可以看到你有以下错误

Caused by: org.apache.cxf.interceptor.Fault: Response was of unexpected text/html ContentType. Incoming portion of HTML stream:

Which is saying that your response is coming in HTML, Response-Code: 500 Encoding: ISO-8859-1 Content-Type: text/html;chars 这就是说您的回复是HTML格式, Response-Code: 500 Encoding: ISO-8859-1 Content-Type: text/html;chars

So there might be a problem with your WebService try using SOAP UI 因此,您的WebService尝试使用SOAP UI时可能会出现问题

also this link will be quite helpful talks about the same issue. 关于同样的问题,这个链接也会很有帮助。 https://forums.mulesoft.com/questions/27468/web-service-consumer-response-was-of-unexpected-te.html https://forums.mulesoft.com/questions/27468/web-service-consumer-response-was-of-unexpected-te.html

If you can't access the log on the server you can try to check if your code request and the curl request are different. 如果您无法访问服务器上的日志,可以尝试检查您的代码请求和卷曲请求是否不同。

To do that you can sniff the http request with a sniffer like tcpmon . 要做到这一点,你可以使用像tcpmon这样的嗅探器来嗅探http请求。

Tcpmon operates as a proxy between your client and the server. Tcpmon作为客户端和服务器之间的代理。 It intercepts all requests and print the details of each request and response. 它拦截所有请求并打印每个请求和响应的详细信息。

The turnaround was to use core java HttpURLConnection to achieve this. 转机是使用核心java HttpURLConnection来实现这一目标。

A method something like this helped the cause ad post a webservice call without any framework.: 像这样的方法帮助原因广告在没有任何框架的情况下发布了webservice调用:

public HttpURLConnection getHttpConn(String webservice_url) throws IOException {
URL endpoint = new URL(webservice_url);
URLConnection connection = endpoint.openConnection();
HttpURLConnection httpConn = (HttpURLConnection) connection;
byte[] encodedBytes = Base64.encodeBase64((getUsername()+":"+getPassword()).getBytes());
httpConn.setRequestMethod(getRequestMethod());
httpConn.setRequestProperty(HTTP_ACCEPT_ENCODING, getAccept_Encoding());
httpConn.setRequestProperty(HTTP_CONTENT_TYPE, getContentType());
httpConn.setRequestProperty(getContent_Length(), getContent_Length());
httpConn.setRequestProperty(HTTP_HOST, getHost());
httpConn.setRequestProperty(getConnection(), getConnection());
httpConn.setRequestProperty(HTTP_COOKIE2, getCookie2());
httpConn.setRequestProperty(HTTP_COOKIE, getCookie());
httpConn.setRequestProperty("Authorization", "Basic "+new String(encodedBytes));
httpConn.setDoOutput(true);
httpConn.setDoInput(true);
return httpConn;
}

Ensure to configure the http client in the CXF config file (cxf.xml). 确保在CXF配置文件(cxf.xml)中配置http客户端。

As documented in Apache CXF document: 如Apache CXF文档中所述:

1.Add the http-conduit namespace and xsd: 1.添加http-conduit命名空间和xsd:

<beans ...
       xmlns:http-conf="http://cxf.apache.org/transports/http/configuration
       ...
       xsi:schemaLocation="...
           http://cxf.apache.org/transports/http/configuration
           http://cxf.apache.org/schemas/configuration/http-conf.xsd
       ...">

2.Add the http-conduit tag/element and set the RecieveTimeout/ConnectionTimeout to 180000ms: 2.添加http-conduit标签/元素并将RecieveTimeout / ConnectionTimeout设置为180000ms:

<http-conf:conduit name="*.http-conduit">
      <http-conf:client 
                      ConnectionTimeout="300000"
                      ReceiveTimeout="300000"/>       
</http-conf:conduit>

try using Fiddler as a proxy and compare both requests. 尝试使用Fiddler作为代理并比较两个请求。 there must be a difference either in the headers or in the request body. 在标题或请求正文中必须存在差异。

Fiddler is also capable of decoding TLS. Fiddler还能够解码TLS。

good luck to anyone.. 祝所有人好运..

Check the WSDL URL. 检查WSDL URL。

URL has to be given till ?wsdl 必须提供URL直到?wsdl

I've faced problem similar to yours recently. 我最近遇到了与你类似的问题。 I've just added 2 artifacts into dependencies: 我刚刚在依赖项中添加了2个工件:

    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-rt-transports-http</artifactId>
        <version>${cxf.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-rt-transports-http-jetty</artifactId>
        <version>${cxf.version}</version>
    </dependency>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM