【问题标题】:SOAPConnection not handling gzip responseSOAPConnection 不处理 gzip 响应
【发布时间】:2011-07-05 03:01:02
【问题描述】:

我正在使用 SOAPConnection 来调用基于 SOAP 的 Web 服务。请求在标头中使用“Accept-Encoding: gzip,deflate”发送。 我使用 fiddler 来获取响应,它是 gzip 压缩的,但是在反序列化消息时,SOAPConnection 给出了一个错误,提示“invalid utf-8”消息。

我尝试了正常的http post,http响应能够正确解压缩响应。我是否需要在 SOAPConnection 上设置一些属性才能让它处理 gzip 消息?

【问题讨论】:

    标签: web-services soap gzip


    【解决方案1】:

    我发现这个 sn-p 在做这项工作

            SOAPMessage response = conn.call(finalRequest, aUrl);
    
            // The response is gzip encoded, so decompress the response.
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            response.writeTo(out);
            byte[] barr = out.toByteArray();
            InputStream gzipStream = new GZIPInputStream(new ByteArrayInputStream(barr));
            Reader decoder = new InputStreamReader(gzipStream, "UTF-8");
            BufferedReader buffered = new BufferedReader(decoder);
            int n = 0;
            char[] cbuf = new char[1024];
            Writer w = new StringWriter();
            while ((n = buffered.read(cbuf)) != -1) {
                w.write(cbuf,0,n);
            }
            // the writer now contains unzipped message.
            System.out.println(w.toString());
    

    【讨论】:

      【解决方案2】:

      GZIP 请求,响应表单服务器:

      如果服务器启用了 GZip,则服务器发送 gzip 压缩文本数据。为此,我们需要一个带有 Http 标头的请求:

      • 请求:我们必须发送一个包含 Accept-Encoding: gzip 标头的 HTTP 请求。
      • 响应:如果启用 gzip,服务器应返回 Content-Encoding: gzip 标头。

      肥皂网络服务:

      使用 SOAPConnectiona 请求 WebService 并获取 response in GZIP compressed 格式:

      public static String getGZIP(byte[] zipBytes) {
          try {
              GZIPInputStream gzipInput = new GZIPInputStream( new ByteArrayInputStream(zipBytes) );
              return IOUtils.toString(gzipInput);
          } catch (IOException e) {
              throw new UncheckedIOException("Error while decompression!", e);
          }
      }
      public static void getSOAPConnection(SOAPMessage soapMsg) throws Exception {
          System.out.println("\n===== SOAPConnection =====");
          
          MimeHeaders headers = soapMsg.getMimeHeaders();
          headers.addHeader("SoapBinding", serverDetails.get("SoapBinding") );
          headers.addHeader("MethodName", serverDetails.get("MethodName") );
          headers.addHeader("SOAPAction", serverDetails.get("SOAPAction") );
          headers.addHeader("Content-Type", serverDetails.get("Content-Type")); // InBound
          headers.addHeader("Accept-Encoding", serverDetails.get("Accept-Encoding")); // OutBound
      
          if (soapMsg.saveRequired()) soapMsg.saveChanges();
           
          /*SOAPMessage message = MessageFactory.newInstance().createMessage(headers, new ByteArrayInputStream(TSOXML.getBytes()));*/
          SOAPConnectionFactory newInstance = SOAPConnectionFactory.newInstance();
          javax.xml.soap.SOAPConnection connection = newInstance.createConnection();
      
          SOAPMessage resp = connection.call(soapMsg, getURL( serverDetails.get("SoapServerURI") ));
          MimeHeaders mimeHeaders = resp.getMimeHeaders();
          String[] header = mimeHeaders.getHeader("Content-Encoding");
          String contentEoncoding = "";
          if (header != null && header.length > 0) contentEoncoding = header[0].toString();
          System.out.println("Content:"+contentEoncoding);
      
          if (contentEoncoding.equalsIgnoreCase("GZIP")) {
              System.out.println("SOAP Message in GZIP");
      
              ByteArrayOutputStream out = new ByteArrayOutputStream();
              resp.writeTo(out);
              byte[] zipBytes = out.toByteArray();
              String gZipString= getGZIP(zipBytes);
              System.out.println("Response:"+ gZipString);
      
              SOAPMessage soapMessage = getSOAPMessagefromDataXML(gZipString);
              System.out.println("SOAP Message Object:\n"+soapMessage);
      
              getSOAPXMLasString(soapMessage);
          } else {
              getSOAPXMLasString(resp);
          }
      }
      

      使用 HTTPCline 请求 SOAP WS。 SOAPUI 请求方式:

      public static void getHttpURLConnection_Core(SOAPMessage soapMsg) throws Exception {
          System.out.println("\n===== java.net.HttpURLConnection =====");
          
          URL url = new URL(null, serverDetails.get("SoapServerURI"));
          String protocol = url.getProtocol();
          System.out.println("Protocol: "+protocol);
          
          Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(PROXY_ADDRESS, PROXY_PORT));
          
          HttpURLConnection connection = (HttpURLConnection) url.openConnection(proxy);
          connection.setReadTimeout(5 * 1000);
          connection.setConnectTimeout(5 * 1000);
          connection.setDoInput(true); connection.setDoOutput(true); connection.setUseCaches(true);
          
          //String authString = username + ":" + password; // Authorization: Basic ZW9uMDE5XzAxOkVsaWFfMTIz
          //String authMsg = "Basic " + Base64.encode(authString.getBytes());
          //connection.setRequestProperty(javax.ws.rs.core.HttpHeaders.AUTHORIZATION, authMsg);
          ((HttpURLConnection) connection).setRequestMethod("POST");
          
          connection.setRequestProperty(javax.ws.rs.core.HttpHeaders.ACCEPT, "text/xml");
          connection.setRequestProperty(javax.ws.rs.core.HttpHeaders.ACCEPT_LANGUAGE, "en-US,en;q=0.9");
          
          connection.setRequestProperty("MethodName", serverDetails.get("MethodName") );
          connection.setRequestProperty("SOAPAction", serverDetails.get("SOAPAction") );
      
          connection.setRequestProperty("HTTP_ACCEPT_ENCODING", "gzip, deflate, br");
          connection.setRequestProperty("Accept-Encoding", serverDetails.get("Accept-Encoding"));
      
          String soapxmLasString = getSOAPXMLasString(soapMsg);
          connection.setRequestProperty(javax.ws.rs.core.HttpHeaders.CONTENT_TYPE, "text/xml");// serverDetails.get("Content-Type")
          connection.setRequestProperty( "Content-Length", String.valueOf(soapxmLasString.length()));
          
          DataOutputStream dataOutputStream = new DataOutputStream(connection.getOutputStream());
          try {
              dataOutputStream.writeBytes(soapxmLasString);
          } finally {
              dataOutputStream.close();
          }
          
          long start = System.currentTimeMillis();
          
          long end = System.currentTimeMillis();
          String date = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(Calendar.getInstance().getTime());
          System.out.println("TIme taken Date:"+date+", Time:"+ (end-start));
          String contentEncoding = connection.getContentEncoding();
          System.out.println("Encoding:"+ contentEncoding);
          
          int responseCode = connection.getResponseCode();
          String responseMessage = connection.getResponseMessage();
          
          System.out.println("Response Code: " + responseCode + " " + responseMessage);
          
          String xmlRply = null ;
          String requestStatus = "Fail";
          if (responseCode == HttpURLConnection.HTTP_OK) {
              requestStatus = "Pass";
              
              InputStream inputStream = connection.getInputStream();
              xmlRply = getStreamContent(inputStream, contentEncoding);
          } else { // Response Code: 500 Internal Server Error
              InputStream errorStream = connection.getErrorStream();
              xmlRply = getStreamContent(errorStream, contentEncoding);
          }
          System.out.println("Reply: " + xmlRply);
          System.out.println("Request Status:"+ requestStatus);
      }
      public static String getStreamContent(InputStream input, String encoding) throws IOException {
          byte[] httpRply;
          String rply;
          httpRply = IOUtils.toByteArray(input);
          System.out.println("Byte Array:"+httpRply.toString());
          if (encoding == null) {
              rply = new String(httpRply);
          } else if ( encoding.equalsIgnoreCase("GZIP") ) {
              rply = getGZIP(httpRply);
          } else { // "ISO-8859-1", ";TF-8"
              rply = new String(httpRply, encoding);
          }
          return rply;
      }
      

      使用 GZIP 格式的服务器响应的工作示例。

      public class SOAP_Weather {
      
          static final String PROXY_ADDRESS = "Proxy_*****.net";
          static final int PROXY_PORT = 9400;
          
          static HashMap<String, String> serverDetails = new HashMap<>();
          static {
              // https://graphical.weather.gov/xml/ : conus
              serverDetails.put("SoapServerURI", "https://graphical.weather.gov:443/xml/SOAP_server/ndfdXMLserver.php");
              serverDetails.put("SoapWSDL", "https://graphical.weather.gov/xml/SOAP_server/ndfdXMLserver.php?wsdl");
              serverDetails.put("SoapXML", "<ndf:CornerPoints xmlns:ndf=\"https://graphical.weather.gov/xml/DWMLgen/wsdl/ndfdXML.wsdl\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"><sector xsi:type=\"xsd:string\">conus</sector></ndf:CornerPoints>");
              serverDetails.put("SoapBinding", "ndfdXMLBinding");
              serverDetails.put("MethodName", "CornerPoints");
              serverDetails.put("SOAPAction", "https://graphical.weather.gov/xml/DWMLgen/wsdl/ndfdXML.wsdl#CornerPoints");
              
              serverDetails.put("User-Agent", "Apache-HttpClient");
              serverDetails.put("Accept-Encoding", "gzip,deflate,sdch");
              serverDetails.put("Content-Type", "text/xml;charset=UTF-8");
          }
          public static void main(String[] args) throws Exception {
              callSoapService();
          }
          public static void callSoapService( ) throws Exception{
              String xmlData = serverDetails.get("SoapXML");
              
              DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
              dbFactory.setNamespaceAware(true);
              dbFactory.setIgnoringComments(true);
              DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
                  InputSource ips = new org.xml.sax.InputSource(new StringReader(xmlData));
                  Document docBody = dBuilder.parse(ips);
                  //docBody.createElementNS(DSIG_NS, "ds");
                  
              System.out.println("Data Document: "+docBody.getDocumentElement());
              
              // Protocol 1.1=SOAP-ENV Content-Type:text/xml; charset=utf-8, 1.2=env Content-Type:application/soap+xml; charset=utf-8
              MessageFactory messageFactory = MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL);
              SOAPMessage soapMsg = messageFactory.createMessage();
              
              SOAPPart soapPart = soapMsg.getSOAPPart();
              SOAPEnvelope soapEnv = soapPart.getEnvelope();
              SOAPBody soapBody = soapEnv.getBody();
              
              soapBody.addDocument(docBody);
              
              // Invoke the webService.
              System.out.println("Request SOAP Message:");
              soapMsg.writeTo(System.out);
              System.out.println("\n");
              
              // Protocol 1.1=SOAP-ENV Content-Type:text/xml; charset=utf-8, 1.2=env Content-Type:application/soap+xml; charset=utf-8
              SOAPEnvelope envelope = soapMsg.getSOAPPart().getEnvelope();
              if (envelope.getElementQName().getNamespaceURI().equals("http://schemas.xmlsoap.org/soap/envelope/")) {
                  System.out.println("SOAP 1.1 NamespaceURI: http://schemas.xmlsoap.org/soap/envelope/");
                  serverDetails.put("Content-Type", "text/xml; charset=utf-8");
              } else {
                  System.out.println("SOAP 1.2 NamespaceURI: http://www.w3.org/2003/05/soap-envelope");
                  serverDetails.put("Content-Type", "application/soap+xml; charset=utf-8");
              }
              getSOAPConnection(soapMsg); // Disadvantage 1:
              getHttpURLConnection_Core(soapMsg);
          }
          
          private static URL getURL(String endPointUrl) throws MalformedURLException {
              URL endpoint = new URL(null, endPointUrl, new URLStreamHandler() {
                  protected URLConnection openConnection(URL url) throws IOException {
                      URL clone = new URL(url.toString());
          
                      URLConnection connection = null;
                      if (PROXY_ADDRESS != null && PROXY_PORT != 0 ) { // https://stackoverflow.com/a/22533464/5081877
                          Socket socket = new Socket();
                          SocketAddress sockaddr = new InetSocketAddress(PROXY_ADDRESS, PROXY_PORT);
                          socket.connect(sockaddr, 10000);
                          Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(socket.getInetAddress(), PROXY_PORT));
                          if (proxy.address().toString().equals("0.0.0.0/0.0.0.0:80") || proxy.address().toString() != null) {
                              System.out.println("Connection through proxy ...");
                              connection = clone.openConnection(proxy);
                          } else {
                              connection = clone.openConnection();
                          }
                      } else {
                          connection = clone.openConnection();
                      }
                      
                      connection.setConnectTimeout(5 * 1000); // 5 sec
                      connection.setReadTimeout(5 * 1000); // 5 sec
                      return connection;
                  }
              });
              return endpoint;
          }
          public static String getSOAPXMLasString(SOAPMessage soapMsg) throws SOAPException, IOException {
              ByteArrayOutputStream out = new ByteArrayOutputStream();
              soapMsg.writeTo(out);
              // resp.writeTo(System.out);
              String strMsg = new String(out.toByteArray());
              System.out.println("Soap XML: "+ strMsg);
              return strMsg;
          }
          public static SOAPMessage getSOAPMessagefromDataXML(String saopBodyXML) throws Exception {
              DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
              dbFactory.setNamespaceAware(true);
              dbFactory.setIgnoringComments(true);
              DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
              InputSource ips = new org.xml.sax.InputSource(new StringReader(saopBodyXML));
              Document docBody = dBuilder.parse(ips);
              System.out.println("Data Document: "+docBody.getDocumentElement());
              
              MessageFactory messageFactory = MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL);
              SOAPMessage soapMsg = messageFactory.createMessage();
              
              SOAPBody soapBody = soapMsg.getSOAPPart().getEnvelope().getBody();
              soapBody.addDocument(docBody);
              
              return soapMsg;
          }
      
          // SOPAConneciton and HTTPClien connection functions
      }
      

      【讨论】:

        【解决方案3】:

        你看到了吗?

        SOAPMessage - SOAPConnection - gzip - how to

        此外,如果您使用 AXIS2,它具有内置功能,可以使用 MTOM 压缩 base64 编码的二进制内容:

        http://axis.apache.org/axis2/java/core/docs/mtom-guide.html

        【讨论】:

        • 是的,查看了stackoverflow链接,我做的完全一样,但是在处理soap响应时我收到了帖子中提到的错误。不幸的是,由于我无法控制的原因,Axis 不是一个选项。
        【解决方案4】:

        只是为了完成该 sn-p - 如果您想使用解压缩的 SOAPMessage,您需要将其加载到新消息中。

        SOAPMessage responseCompressed = connection.call(reqMessage, endpoint);
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        responseCompressed.writeTo(out);
        byte[] barr = out.toByteArray();
        InputStream gzipStream = new GZIPInputStream(new ByteArrayInputStream(barr));
        

        这是魔法线

        SOAPMessage response = factory.createMessage(responseCompressed.getMimeHeaders(), gzipStream);
        

        factory 是你的 MessageFactory。

        现在响应将像没有 gzip 标头一样运行。你把它放进去。

        【讨论】:

          猜你喜欢
          • 2011-05-16
          • 2014-04-18
          • 2010-12-17
          • 1970-01-01
          • 2014-02-24
          • 1970-01-01
          • 1970-01-01
          • 2013-03-12
          • 1970-01-01
          相关资源
          最近更新 更多