Golang实现Cisco Callmanager AXL API查询

Golang实现Cisco Callmanager AXL API查询 我正在使用Go语言构建一个HTTP POST请求进行REST查询。我试图运行一个SQL命令,但问题可能在于请求体中丢失了查询内容。通过Postman运行时该查询可以正常工作。如果需要,我可以提供更多详细信息。希望能获得帮助来解决这个问题。

func main() {
    fmt.Println("hello world")
}
13 回复

不客气。很高兴能帮到你。

更多关于Golang实现Cisco Callmanager AXL API查询的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


好的。请提供更多细节,以便有人能够帮助您。

以下是代码的输出:

image

请查看以下示例

https://goplay.space/#j4fJy33jNCo

我现在必须赶去上班,所以没时间详细解释

好的,我已经移除了额外的解引用并再次运行。这次查询成功执行并返回了我的数据。感谢您的帮助!现在是时候解析所有数据了 😊

func main() {
    fmt.Println("hello world")
}

请求体中的字符串/字节并不在请求中。只有作为 http.NewRequest 最后一个参数传递的 io.Reader。你能否同时移除 body_data 中的引号转义?将 \" 替换为仅 "

此外,您的body_data缺少xml标签

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns .....

也许您还应该告诉服务器请求内容是xml?通过为请求添加content-type标头。

使用curl能正常工作吗?像这个示例:https://developer.cisco.com/docs/axl/#!hello-world-with-curl/hello-world-with-curl

599是某种超时状态。https://httpstatuses.com/599

有件事我不太理解。您是否需要在body_data中转义斜杠?它们位于反引号包裹的字符串中,这种情况下应该不需要转义斜杠吧?要在论坛中发布代码,您可以将代码上传到Go playground然后在此处分享链接,或者用两行标记包裹代码。在代码前使用go,在代码后使用

// 代码示例位置

好的,我觉得问题可能出在 body_data 变量上,但我不太确定。我是 Go 语言的新手,可能代码写得不太对。当我尝试复制粘贴代码时,论坛报错了。作为新用户,我每篇帖子只能包含 2 个链接。它可能不喜欢 http 引用,所以一直在报错。

以下是代码:

image

Johan,

我能再请教一个问题吗?能否帮我看看这个解析和结构体的部分?

以下是返回结果的起始部分:

<?xml version='1.0' encoding='UTF-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Body><ns:executeSQLQueryResponse xmlns:ns="http://www.cisco.com/AXL/API/11.5"><return><row><pkid>01056b15-1b8e-748d-bd5b-a790637904fd</pkid><fkroutepartition>e0b331fb-a429-7ca2-deb3-d4629573e923</fkroutepartition>

以下是我正在调试的结构体:

	XMLName xml.Name `xml:"return"`
	MyRows   []MyRow   `xml:"row"`
}

type MyRow struct {
				
	pkid string `xml:"ns:executeSQLQueryResponse:row:pkid"`
	dnorpattern string `xml:"dnorpattern"`
}

我还在学习这个部分,所以还没有完全理解。我知道需要一个结构体来容纳行的数组结构。这个结构正确吗?

以下是我尝试进行反序列化的代码段:

data, _ := ioutil.ReadAll(response.Body)
		fmt.Println(string(data))
		
		/*
		err := xml.Unmarshal([]byte(data), &MyRows)
		if err != nil {
			fmt.Printf("error: %v", err)
			return
		}
		fmt.Printf("pkid:%s",MyRows.pkid)
		*/

我对反序列化本身还不太理解。有什么建议吗?

谢谢, Kevin

嗨 Johan,

好的,我去掉了多余的引号,但仍然收到599错误。我已经确认11.5是正确的版本。当我打印请求时,看不到请求体的文本内容。我该如何查看它以确认格式正确?另外,虽然我是远程连接到服务器所在的环境,但我已确认可以ping通服务器,所以网络连接看起来没问题。

package main

import (
   "fmt"
   "io/ioutil"
   "net/http"
   "strings"
   "crypto/tls"
   "encoding/base64"
)

const myUser = "admin"
const myPass = "pass123"

func basicAuth(username, password string) string {
 auth := username + ":" + password
  return base64.StdEncoding.EncodeToString([]byte(auth))
}

func redirectPolicyFunc(req *http.Request, via []*http.Request) error{
req.Header.Add("Authorization","Basic " + basicAuth(myUser,myPass))
return nil
}

func main() {
   
   
   fmt.Printf("Starting POST\n")
   
   body_data := `<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://www.cisco.com/AXL/API/11.5">
<soapenv:Header/>
<soapenv:Body>
<ns:executeSQLQuery>
<sql>
SELECT * from numplan
            
</sql>
</ns:executeSQLQuery>
</soapenv:Body>
</soapenv:Envelope>`
   
   request, httpErr := http.NewRequest("POST", "https://10.75.115.20:8443/axl/", strings.NewReader(body_data))
   request.Header.Set("SOAPAction", "CUCM:DB=11.5 executeSQLQuery")
   request.Header.Add("Authorization","Basic " + basicAuth(myUser,myPass))
   
   if httpErr != nil {
   	fmt.Printf("The HTTP request creation failed with error %s\n", httpErr)
   }
   
   // ignore certs during data collection
    tr := &http.Transport{
       TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
   }
   client := &http.Client{Transport: tr}
   
   response, err := client.Do(request)
   if err != nil {
   	fmt.Printf("The HTTP request failed with error %s\n", err)
   } else {
   	data, _ := ioutil.ReadAll(response.Body)
   	fmt.Println(string(data))
   }
   
   fmt.Println("\n\nRequest:")
   fmt.Println(request)
}

在Go语言中实现Cisco CallManager AXL API查询时,请求体格式不正确是常见问题。AXL API使用SOAP协议,需要正确的XML格式和SOAP头部。以下是完整的示例代码:

package main

import (
    "bytes"
    "crypto/tls"
    "fmt"
    "io/ioutil"
    "net/http"
    "text/template"
)

const soapTemplate = `<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
                  xmlns:ns="http://www.cisco.com/AXL/API/{{.Version}}">
    <soapenv:Header/>
    <soapenv:Body>
        <ns:executeSQLQuery>
            <sql>{{.SQLQuery}}</sql>
        </ns:executeSQLQuery>
    </soapenv:Body>
</soapenv:Envelope>`

type SOAPRequest struct {
    Version  string
    SQLQuery string
}

func main() {
    // AXL API配置
    url := "https://your-cucm-server:8443/axl/"
    username := "your-username"
    password := "your-password"
    
    // SQL查询语句
    sqlQuery := "SELECT name, description FROM device"
    
    // 构建SOAP请求
    requestData := SOAPRequest{
        Version:  "12.5", // 根据你的CUCM版本调整
        SQLQuery: sqlQuery,
    }
    
    // 解析模板
    tmpl, err := template.New("soap").Parse(soapTemplate)
    if err != nil {
        fmt.Printf("模板解析错误: %v\n", err)
        return
    }
    
    // 生成SOAP请求体
    var soapBody bytes.Buffer
    err = tmpl.Execute(&soapBody, requestData)
    if err != nil {
        fmt.Printf("模板执行错误: %v\n", err)
        return
    }
    
    // 创建HTTP客户端(跳过证书验证,生产环境应使用有效证书)
    client := &http.Client{
        Transport: &http.Transport{
            TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
        },
    }
    
    // 创建HTTP请求
    req, err := http.NewRequest("POST", url, &soapBody)
    if err != nil {
        fmt.Printf("请求创建错误: %v\n", err)
        return
    }
    
    // 设置请求头
    req.Header.Set("Content-Type", "text/xml; charset=utf-8")
    req.Header.Set("SOAPAction", `CUCM:DB ver=12.5 executeSQLQuery`)
    req.SetBasicAuth(username, password)
    
    // 发送请求
    resp, err := client.Do(req)
    if err != nil {
        fmt.Printf("请求发送错误: %v\n", err)
        return
    }
    defer resp.Body.Close()
    
    // 读取响应
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        fmt.Printf("响应读取错误: %v\n", err)
        return
    }
    
    fmt.Printf("响应状态: %d\n", resp.StatusCode)
    fmt.Printf("响应内容: %s\n", string(body))
}

关键要点:

  1. AXL API使用SOAP协议而非纯REST,需要正确的XML格式
  2. 必须设置SOAPAction头部和Content-Type: text/xml
  3. 使用基本认证(Basic Auth)
  4. 根据你的CUCM版本调整API版本号(示例中使用12.5)
  5. SQL查询需要包含在<ns:executeSQLQuery>标签中

如果你的查询仍然不工作,请检查:

  • CUCM服务器地址和端口是否正确
  • 用户名密码是否有AXL权限
  • SQL语法是否符合CUCM数据库结构
  • 防火墙和网络连接是否正常
回到顶部