【问题标题】:Groovy httpBuilder POST XML with Basic Authentication带有基本身份验证的 Groovy httpBuilder POST XML
【发布时间】:2015-02-05 23:56:51
【问题描述】:

我正在尝试将 POST 请求发送到 Restful WS,请求最初是 xml,响应也是如此。

我还需要发送基本身份验证。 起初,我遇到了未定义类的问题,幸运的是,我花了 6 个罐子来解决这个问题。

现在我不断收到以下信息: 捕获:groovyx.net.http.HttpResponseException:错误请求

听起来它不喜欢 POST 请求。我尝试了不同的方法,包括 RESTClient,我尝试通过传递文件或作为字符串 var 以原始 xml 格式委派请求。 我不完全理解 httpBuilder 中的 post 或 request 方法之间的区别。

如果有人能帮我指出我做错了什么,将非常感激

def http = new HTTPBuilder('http://some_IP:some_Port/')
http.auth.basic('userName','password')
http.post(path:'/path/ToServlet')

http.post(POST,XML)
{

  delegate.contentType="text/xml"
  delegate.headers['Content-Type']="text/xml"
  //delegate.post(getClass().getResource("/query.xml"))
 // body = getClass().getResource("/query.xml")
   body = 
   {
      mkp.xmlDeclaration()

        Request{
          Header{
                     Command('Retrieve')
                     EntityIdentifiers
                     {
                       Identifier(Value:'PhoneNumber', Type:'TelephoneNumber')
                      }
                                  EntityName('Subscriber')
                  }
         }
   }
}

现在,如果我在请求中翻译了错误的 XML,这里是它的 XML 版本:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Provisioning xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Request>
    <Header>
        <Command>Retrieve</Command>
        <EntityIdentifiers>
            <Identifier Value="phoneNumber" Type="TelephoneNumber" />
        </EntityIdentifiers>
        <EntityName>Subscriber</EntityName>
    </Header>
</Request>
</Provisioning>

【问题讨论】:

    标签: xml post groovy httpbuilder


    【解决方案1】:

    好吧,过了一段时间我收集了解决方案是将 groovy 库升级到 2.4 和 httpClient4.0.1 和 httpBuilder 4.x

    这似乎已经成功了,因为我最初使用的是 groovy 1.5.5 您拥有的另一个选择是将 Java 和 Groovy 一起使用 Java 以使用 URL 和 HttpURLConnection 类建立连接,希望那里有足够的示例。 请注意,这不是 SSL,如果您想使用 SSL 和 https 执行此操作,可能需要采取额外的步骤

    import groovy.xml.*
    import groovy.util.XmlSlurper.*
    import groovy.util.slurpersupport.GPathResult.*
    
    
    import groovyx.net.http.HTTPBuilder
    
    import groovyx.net.http.EncoderRegistry
    import java.net.URLEncoder
    import java.net.URLEncoder.*
    import org.apache.http.client.*
    import org.apache.http.client.HttpResponseException
    import org.apache.http.protocol.ResponseConnControl;
    import org.apache.http.conn.ssl.*
    import org.apache.http.conn.ssl.TrustStrategy
    
    import static java.net.URLEncoder.encode
    import static groovyx.net.http.ContentType.*
    import static groovyx.net.http.HTTPBuilder.request
    import static groovyx.net.http.Method.POST
    //import static groovyx.net.http.RESTClient.*
    
    
    def SMSCmirrorServerTor = "http://IP:PORT"
    def SMSCmirrorServerMntrl = "http://IP:PORT"
    
    
    def msisdn = args[0]
    
    //Connect to method HTTP xml URL encoded request, XML response
    def connectSMSC(server, MSISDN)
    {
      // Variables used for the response
      def result = ""
      //Variables used for request
      // one way is to use raw xml
      def rawXML = """
      <Provisioning xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>
              <Request>
                      <Header>
                              make sure your <xml> is well formatted use xml formatter online if need be
                      </Header>
              </Request>
      </Provisioning>"""
    
        def http = new HTTPBuilder(server)
        http.auth.basic('username','password')
        http.contentType = TEXT
        http.headers = [Accept: 'application/xml', charset: 'UTF-8']
    
        http.request(POST)
        {
          uri.path = 'Servlet or WS/Path'
          requestContentType = URLENC
          body = "provRequest=" + encode(rawXML,"UTF-8")
    
    
          response.success = { resp, xml ->
    
            def xmlParser = new XmlSlurper().parse(xml)
            //Helps if you know in advance the XML response tree structure at this point it's only xmlSlurper doing the work to parse your xml response
            def ResponseStatus = xmlParser.Response.Header.ResponseStatus
            result += "Response Status: " + ResponseStatus.toString() + "\n================\n"
    
            def ResponseHeader = xmlParser.Response.Header.Errors.Error
            ResponseHeader.children().each
            {
              result += "\n${it.name()}: " + it.text().toString() + "\n"
    
            }
    
            def xmlDataRootNode = xmlParser.Response.Data.Subscriber
            xmlDataRootNode.children().each
            {
    
              if (it.name() == 'UserDevices')
              {
                result += "\n" + it.UserDevice.name() + " :" + "\n-----------------\n"
                it.UserDevice.children().each
                {
                  result += it.name() + " :" + it.text().toString() + "\n"
                }
              }
              else
              {
                 result += "\n${it.name()}: " + it.text().toString() + "\n"
              }
    
            }//End of each iterator on childNodes
    
            if (ResponseStatus.text().toString() == "Failure")
            {
              def ErrorCode = resp.status
              result += "Failed to process command. Bad request or wrong input"
              //result += "\nHTTP Server returned error code: " + ErrorCode.toString()
              // Note this error is for bad input server will still return status code 200 meaning o.k. unlike err 401 unathorized or err 500 those are http errors so be mindful of which error handling we're talking about here application layer vs http protocol layer error handling
            }
    
          }//End of response.success closure
        }//End of http.request(POST) method 
    
      result
    }//end of connectSMSC method
    
    
    //the following is only in case server A is down we can try server B 
    def finalResponse=""
    try
    {
      finalResponse += connectSMSC(SMSCmirrorServerTor,msisdn)
    
    }
    
    catch(org.apache.http.conn.HttpHostConnectException e)
    {
    
      finalResponse += "Encountered HTTP Connection Error\n ${e}\n Unable to connect to host ${SMSCmirrorServerTor}\n Trying to connect to mirror server ${SMSCmirrorServerMntrl} instead\n"
      finalResponse += connectSMSC(SMSCmirrorServerMntrl,msisdn)
    }
    catch (groovyx.net.http.HttpResponseException ex)
    {
    
      finalResponse += "Encountered HTTP Connection Error Code: ${ex.statusCode}\n"
      finalResponse += connectSMSC(SMSCmirrorServerMntrl,msisdn)
    }
    /*
    *
    * java.lang.IllegalArgumentException: port out of range:
    
    */
    catch(java.lang.IllegalArgumentException e)
    {
     finalResponse += "Error: " + e
    }
    
    catch(java.io.IOException e)
    {
    
      finalResponse += "IO Error: " + e
      finalResponse += connectSMSC(SMSCmirrorServerMntrl,msisdn)
    }
    catch(java.io.FileNotFoundException e)
    {
    
      finalResponse += "IO Error: " + e
      finalResponse += connectSMSC(SMSCmirrorServerMntrl,msisdn)
    }
    
    
    println finalResponse.toString()
    

    【讨论】:

      【解决方案2】:

      看起来您正在发布请求,但两者都没有正确形成。试试这样的:

      def writer = new StringWriter()
      
      def req = new MarkupBuilder(writer)
      req.mkp.xmlDeclaration(version:"1.0", encoding:"utf-8")
      req.Provisioning {
          Request {
              Header {
                  Command('Retrieve')
                  EntityIdentifiers {
                      Identifier(Value:'PhoneNumber', Type:'TelephoneNumber')
                  }
                  EntityName('Subscriber')
              }
          }
      }
      
      def http = new HTTPBuilder('http://some_IP:some_Port/path/ToServlet')
      http.auth.basic('userName','password')
      http.post(contentType:XML, query:writer) { resp, xml ->
          // do something with response
      }
      

      【讨论】:

      • 谢谢@MichaelRutherford 现在似乎好多了,我实际上可以看到格式良好的 xml 请求,但是 HTTPBuilder 抱怨兼容的参数类型我现在在命令行中运行 groovy 脚本时得到以下信息: java.io.StringWriter 无法转换为 java.util.Map
      • 在 Eclipse 中我得到这个错误,有人说是 groovyx.net 带有某种 Eclipse 错误:没有方法签名:groovyx.net.http.HTTPBuilder.post() 适用于参数类型:(java.util.LinkedHashMap, SMSC$_run_closure2) 值:{["contentType":application/xml, "query": @Michael Rutherfurd跨度>
      • groovy.xml.MarkupBuilder 无法转换为 java.util.Map 从 xml.MarkupBuilder 获取转换错误 Map 或 LinkedHashMap 知道如何转换为正确的类型!!?
      • 尝试 body:writer.toString() 而不是 query:writer。我现在无法测试它,但我认为它应该可以工作。
      • 不幸的是,我尝试使用 Eval.me(writer) 时仍然遇到相同的错误,希望将其转换为 Map 或 LinkedHashMap,因为它似乎想要它而不是 java.io.stringWriter 或字符串对象类型.如果我使用 send(),我是否缺少 request() 或 post() 中的任何参数?我试过了,到目前为止也没有运气
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-05
      • 2020-06-08
      • 2018-01-24
      相关资源
      最近更新 更多