Cisco Callmanager axl api query


(Kevin Hoyt) #1

I’m working on a REST query with go, building an http post. I’m trying to run a sql command and I think what’s happening is I’m losing the query in the request body. The query works when I run it via Postman. I can provide more details if needed. I’m looking for help to get this running.


(Johan Dahl) #2

Hi. Yes provide more details so someone can help you :slight_smile:


(Kevin Hoyt) #3

Hi,

sure, I think it’s losing the body_data var, but I’m not sure. I’m new to go, so I may not have this written correctly. The forum was erroring when I tried to copy and paste the code itself. As a new user I am limited to 2 links in a post. It must not like the http references so it was complaining.

here is the code:


(Kevin Hoyt) #4

Here is the output from the code:


(Johan Dahl) #5

599 is a timeout of some kind. https://httpstatuses.com/599

One thing I don’t understand. Do you need to escape the / in body_data. They are inside a string enclosed in backticks where you don’t need to escape / ? And to post code in the forum you could either put in a go playground and link it here or put in between two lines. Before code ```go and ``` after the code.


(Johan Dahl) #6

Here I found this: https://community.cisco.com/t5/unified-communications/axl-http-599-error/m-p/2294204/highlight/true#M42815. Are you sure your database is version 11.5?


(Kevin Hoyt) #7

Hi Johan,

ok, I removed the extra ‘’ and still getting the 599. I have confirmed that 11.5 is the proper version. When I print the request I don’t see the text of the body. How would I see that to be sure it looks correct? Also, I am remotely connected to the env where the server is, but I have confirmed that I can ping the server so connectivity looks good.

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)
}

(Johan Dahl) #8

The string/bytes of the body isn’t in the request. Just the io.Reader which you give as the last argument in http.NewRequest. Could you also remove the escaping of quotation marks in body_data? Replace \" with only "


(Johan Dahl) #9

And also your body_data misses the xml-tag

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

and maybe you also should tell the server that the content of the request is xml? By adding a content-type header to the request.

Does it work with curl? Like this example: https://developer.cisco.com/docs/axl/#!hello-world-with-curl/hello-world-with-curl


(Kevin Hoyt) #10

ok, I removed the additional dereference and ran it again. This time the query ran and returned my data. Thank you for your help! Now it’s time to parse it all out :slight_smile:


(Johan Dahl) #11

Your welcome. Good I could help you.


(Kevin Hoyt) #12

Johan,

Can I ask you 1 more question? Can you help me with the parsing and struct?

Here is the start of the result:

<?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>

and here is the struct I’m messing with:

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

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

I’m still learning this so it’s not fully making sense to me. I understand needing a struct to contain the array structure of rows. Is the structure corect?

Here is the code segment where I’m trying to unmarshal

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)
		*/

I’m not quite understanding the unmarshall itself. Any suggestions?

Thanks,
Kevin


(Johan Dahl) #13

See this example

https://goplay.space/#j4fJy33jNCo

I have to run to work so I have no time to explain it right now