Service requests against Fritz!Box devices fail
wichert opened this issue · 7 comments
I am trying a very simple test against a Fritz!Box device:
package main
import (
"fmt"
"log"
"github.com/huin/goupnp/dcps/internetgateway1"
)
func main() {
clients, _, err := internetgateway1.NewWANIPConnection1Clients ()
if err != nil {
log.Fatal(err)
}
for _, client := range clients {
status, _, _, err := client.GetStatusInfo()
if err != nil {
log.Fatal(err)
}
fmt.Println(status)
}
}
but this always fails:
2014/06/05 11:30:25 goupnp: SOAP request got HTTP 500 Internal Server Error
I did a bit of on-wire sniffing to compare what goupnp does versus what miniupnpc does. This is a working request from miniupunc:
POST /igdupnp/control/WANIPConn1 HTTP/1.1
Host: 192.168.178.1:49000
User-Agent: Darwin/13.0.0, UPnP/1.0, MiniUPnPc/1.9
Content-Length: 271
Content-Type: text/xml
SOAPAction: "urn:schemas-upnp-org:service:WANIPConnection:1#GetStatusInfo"
Connection: Close
Cache-Control: no-cache
Pragma: no-cache
<?xml version="1.0"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><s:Body><u:GetStatusInfo xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1"></u:GetStatusInfo></s:Body></s:Envelope>
This is a failing request from goupnp:
POST /igdupnp/control/WANIPConn1 HTTP/1.1
Host: 192.168.178.1:49000
User-Agent: Go 1.1 package http
Content-Length: 154
CONTENT-TYPE: text/xml; charset="utf-8"
SOAPACTION: urn:schemas-upnp-org:service:WANIPConnection:1#GetStatusInfo
Accept-Encoding: gzip
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><s:Body></s:Body></s:Envelope>
This shows several differences:
- miniupunc includes the
<?xml version="1.0" encoding="utf-8"?>
preamble. - miniupunc includes an
<u:GetStatusInfo xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1">
element in the SOAP body.
I suspect the latter part is the critical one.
I did a very quick hack by modifying encodeRequestAction
:
func encodeRequestAction(inAction interface{}) ([]byte, error) {
requestBuf := new(bytes.Buffer)
requestBuf.WriteString(soapPrefix)
requestBuf.WriteString("<u:GetStatusInfo xmlns:u=\"urn:schemas-upnp-org:service:WANIPConnection:1\"></u:GetStatusInfo>")
That indeed fixed the 500 errors.
You're quite right... I suspect this never worked, and I never tested things that actually required arguments to the action (ugh, lazy me - that's pretty bad). Thanks for reporting this.
I've pushed a fix. It's not pretty... but then, Go's support for controlling namespace prefixes is a pain, and a lot of UPnP servers seem to choke on most of the XML that Go's XML library emits (even though it's valid).
Let me know if that works for you!
I realised shortly after writing a reply that while this code works for actions with no parameters, I'm not sure that I ever got around to testing actions with parameters. I'll need to do that... Probably setting up some basic unit tests around soap actions.
I've added a test and confirmed a fix as working with parameters as well now. This should now be in a better state.
Thanks, this works correctly for me now.
Excellent, thanks for the confirmation.