0

I am writing a Python3 script to trigger an Axis camera via their HTTP API. The string they need in the url to trigger the Digital Input (with authorization) is:

"http://{ip}/axis-cgi/param.cgi?action=update&IOPort.I0.Input.Trig={open/closed}"

If I put this in a browser it works AKA response 200 - OK. When I run this on my Linux machine using the urllib request.

#encode user,pass
values = { 'username': username,'password': password }
data = urllib.urlencode(values)

#Axis param.cgi action
action = "update"
trig = "closed"

cgi_args = {"action": action, "IOPort.I0.Input.Trig": trig}
cgi_data = urllib.urlencode(cgi_args)
url = "http://{ip}/axis-cgi/param.cgi?{data}".format(ip=ip, data=cgi_data)

req = urllib2.Request(url, data, headers={'Content-type': 'text/html'})
print(req.get_full_url())

response = urllib2.urlopen(req)
result = response.read()
print (result)

The output is:

http://192.168.50.191/axis-cgi/param.cgi?action=update&IOPort.I0.Input.Trig=closed
action must be specified

I know that I am authenticated otherwise I get Unauthorized response from server.

As you can see for debugging I print the req.get_full_url() to make sure I've built the url string correctly, however the server responds with action must be specified which is what I get in the browser when I just have http://192.168.50.191/axis-cgi/param.cgi? in the address bar. So the action portion of the URL appears to not be making it to the server.

I've tried:

  1. Using %3F as the ? character, but I get 404 error
  2. Embedding the data in the data parameter does not work either

Anything I am missing here?

Dillon Tucker
  • 55
  • 1
  • 8
  • This isn't `https`, so you can just grab a network trace using e.g. `tcpdump` if you want to verify exactly what data your code is sending to the camera. Can you reproduce this behavior using `curl` on the command line? – larsks May 20 '20 at 19:11
  • Yes I can repeat the problem using curl: `curl --data-urlencode "username=" --data-urlencode "password=" "http://192.168.50.191/axis-cgi/param.cgi?action=update&IOPort.I0.Input.Trig=open"` Output: `action must be specified` I noticed that my browser uses GET mothod while this is a POST method. How would I authenticate a GET if it does not take basic authentication? – Dillon Tucker May 20 '20 at 19:37
  • I've written this in C# and it works but the class in C# for Authorization is `NetworkCredential` – Dillon Tucker May 20 '20 at 20:02
  • I figured out the cURL command for GET request with authentication type I need. the parameter I was missing was `--digest`. so my full command is: `curl --digest --user user:pass 'http://192.168.50.191/axis-cgi/param.cgi?action=update&IOPort.I0.Input.Trig=open'` now just need to select digest for my urllib request in the script – Dillon Tucker May 20 '20 at 20:54

1 Answers1

0

used pycurl with digest authorization for a GET request with auth:

def configCurl():
username = "user"
password = "pass"
auth_mode = pycurl.HTTPAUTH_DIGEST
curl = pycurl.Curl()
curl.setopt(pycurl.HTTPAUTH, auth_mode)
curl.setopt(pycurl.USERPWD, "{}:{}".format(username, password))
curl.setopt(pycurl.WRITEFUNCTION, lambda x: None)
return curl

curl = configCurl()
curl.setopt(curl.URL, url)
curl.perform()
curl.close()
Dillon Tucker
  • 55
  • 1
  • 8