2012-12-21 52 views
2

我遇到了CORS和WCF(SOAP,不是REST)集成的問題。 當我從JS的請求,一個例外是「消息的身體無法閱讀,因爲它是空的」,在WCF跟蹤日誌(邏輯上,與OPTION CORS請求連接)CORS + WCF(SOAP)

身體:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:a="http://www.w3.org/2005/08/addressing/"> 
    <s:Header> 
    </s:Header> 
    <s:Body> 
     <GetInfo xmlns="http://tempuri.org/"></GetInfo> 
    </s:Body> 
</s:Envelope> 

JS請求:

$.ajax({ 
    type: "POST", 
    url: "http://localhost:8081/service_deploy/service1.svc/serviceSoap",  
    headers: { "SOAPAction": "http://tempuri.org/IService/GetInfo" }, 
    data: body,  
    contentType: "text/xml", 
    timeout: 10000 
}); 

CORS請求:

OPTIONS http://localhost:8081/service_deploy/service1.svc/serviceSoap 
HTTP/1.1 
Host: localhost:8081 
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:16.0) Gecko/20100101 Firefox/16.0 
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 
Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3 
Accept-Encoding: gzip, deflate 
Connection: keep-alive 
Origin: http://localhost:49209 
Access-Control-Request-Method: POST 
Access-Control-Request-Headers: content-type,soapaction 
Pragma: no-cache 
Cache-Control: no-cache 

例外:

Type: System.ServiceModel.ProtocolException, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 
Mes: There is a problem with the XML that was received from the network. See inner exception for more details. 
    Inner type: System.Xml.XmlException, System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 
    Inner mes: The body of the message cannot be read because it is empty. 

堆棧跟蹤:

System.ServiceModel.Channels.HttpChannelListener.HttpContextReceived(HttpRequestContext context, Action callback) System.ServiceModel.Activation.HostedHttpTransportManager.HttpContextReceived(HostedHttpRequestAsyncResult result) 
System.ServiceModel.Activation.HostedHttpRequestAsyncResult.HandleRequest() 
System.ServiceModel.Activation.HostedHttpRequestAsyncResult.BeginRequest() 
System.ServiceModel.Activation.HostedHttpRequestAsyncResult.OnBeginRequest(Object state) 
System.ServiceModel.AspNetPartialTrustHelpers.PartialTrustInvoke(ContextCallback callback, Object state) 
System.ServiceModel.Activation.HostedHttpRequestAsyncResult.OnBeginRequestWithFlow(Object state) 
System.Runtime.IOThreadScheduler.ScheduledOverlapped.IOCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped) 
System.Runtime.Fx.IOCompletionThunk.UnhandledExceptionFrame(UInt32 error, UInt32 bytesRead, NativeOverlapped* nativeOverlapped) 
System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP) 

如何集成CORS和WCF SOAP或處理這種低級別的WCF異常?

+0

你能告訴你的JS要求的一個例子的CORS的例子嗎? –

+0

嗯,真正有趣的問題,確實延伸WCF的可擴展性的極限:)我認爲這可以完成例如使用自定義通道,甚至是自定義編碼器,但不記得WCF消息處理管道如何工作 - 如果您發佈了異常的實際類型和所有內部異常信息,這將有所幫助 - 這可以幫助我找到檢測到空郵件的確切位置。 –

+0

感謝您的回覆!我發佈了一些關於請求和異常的附加信息。 – Vladislav

回答

1

在servlet容器中需要一個過濾器來處理OPTIONS請求並使用適當的頭文件集來回答問題。

web.xml文件可能看起來像這樣

[...] 
<filter> 
    <filter-name>CORSFilter</filter-name> 
    <filter-class>my.namespace.CORSFilter</filter-class> 
</filter> 
<filter-mapping> 
    <filter-name>CORSFilter</filter-name> 
    <url-pattern>/*</url-pattern> 
</filter-mapping> 
[...] 

這是過濾

public class CORSFilter implements Filter { 
    // For security reasons set this regex to an appropriate value 
    // example: ".*example\\.com" 
    private static final String ALLOWED_DOMAINS_REGEXP = ".*"; 

    public void doFilter(ServletRequest servletRequest, 
     ServletResponse servletResponse, FilterChain filterChain) 
     throws IOException, ServletException { 

    HttpServletRequest req = (HttpServletRequest) servletRequest; 
    HttpServletResponse resp = (HttpServletResponse) servletResponse; 

    String origin = req.getHeader("Origin"); 
    if (origin != null && origin.matches(ALLOWED_DOMAINS_REGEXP)) { 
     resp.addHeader("Access-Control-Allow-Origin", origin); 
     if ("options".equalsIgnoreCase(req.getMethod())) { 
     resp.setHeader("Allow", "GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS"); 
     if (origin != null) { 
      String headers = req.getHeader("Access-Control-Request-Headers"); 
      String method = req.getHeader("Access-Control-Request-Method"); 
      resp.addHeader("Access-Control-Allow-Methods", method); 
      resp.addHeader("Access-Control-Allow-Headers", headers); 
      resp.setContentType("text/plain"); 
     } 
     resp.getWriter().flush(); 
     return; 
     } 
    } 

    // Fix the ios6 issue: caching post requests 
    if ("post".equalsIgnoreCase(req.getMethod())) { 
     resp.addHeader("Cache-Control", "no-cache"); 
    } 

    if (filterChain != null) { 
     filterChain.doFilter(req, resp); 
    } 
    } 

    @Override public void destroy() {} 
    @Override public void init(FilterConfig arg0) throws ServletException {} 
} 
+0

感謝您的回覆。如果使用Java技術,我會使用相同的方法。但是,該技術使用的是Microsoft WCF。 WCF有一個類似的方法(行爲),但之前引發了一個異常。 – Vladislav