External Control changes?

I developed a program for a third party control system to query the Roku 3, parse the channel data, etc. Everything has been working great for at least a year, until the other day. Now when I use the command.

GET /query/apps no longer replies with the app list, it gives me a 400 error. Has something changed with the external control protocol since the last firmware update on the device itself? Is there something I can check on the Roku 3 that maybe has blacklisted my controller for some reason?

I use my windows phone app and things seem to work fine, and the control I dev’d worked fine until a couple days ago and that programming hasn’t changed.

This still works for me on 6.2. Do you get an error from this command?


curl http://192.168.1.xxx:8060/query/apps

–Mark

No, I get the same error.

HTTP/1.1 400 Bad Request

I send

“curl http://192.168.1.233:8060/query/apps HTTP/1.1\r\n”

I receive

“HTTP/1.1 400 Bad Request”
"Server: Roku UpnP/1.0 MiniUPnPd/1.4
“Content-Length: 0”

I’m not sure why you added the “HTTP/1.1” etc after the command. The command I quoted (“curl” followed by one URL parameter) is the complete curl command. Nevertheless, something’s not right. What model are you using and what firmware version is it running?

–Mark

Yes, I tried it without the HTTP as well and I get the same results.

I’m running a 4200X - Roku 3 with software v6.2 build 3332.

I’m opening a client to the IP address port 8060, if that’s not correct please let me know.

Strange, that’s the same model and firmware I tested. Can you PM your serial number to me?

–Mark

“mjrtoo” wrote:
Yes, I tried it without the HTTP as well and I get the same results.

I’m running a 4200X - Roku 3 with software v6.2 build 3332.

I’m opening a client to the IP address port 8060, if that’s not correct please let me know.

Did you try the command exactly as shown by Mark? I.e. no “HTTP/1.1\r\n” at the end…that is not part of a curl command.

The problem is probably that the HTTP parser is requiring CR-LF line endings now. It was not intentional to affect any clients.

If you use curl or any standard HTTP tool or library, it should do that correctly, but if you have custom code you may need to modify it so it outputs a CR-LF after each line and an empty line after the last line.

“RokuKC” wrote:

“mjrtoo” wrote:
Yes, I tried it without the HTTP as well and I get the same results.

I’m running a 4200X - Roku 3 with software v6.2 build 3332.

I’m opening a client to the IP address port 8060, if that’s not correct please let me know.

Did you try the command exactly as shown by Mark? I.e. no “HTTP/1.1\r\n” at the end…that is not part of a curl command.

The problem is probably that the HTTP parser is requiring CR-LF line endings now. It was not intentional to affect any clients.

If you use curl or any standard HTTP tool or library, it should do that correctly, but if you have custom code you may need to modify it so it outputs a CR-LF after each line and an empty line after the last line.

Yup, that’s there, if you don’t terminate it properly you get nothing. I only have one line that looks like this.

curl http://192.168.1.233:8060/query/apps[0d][0a][0a], same 400 error result. I’ve tried several different combinations of the line terminators and always get the 400 error.

“mjrtoo” wrote:
I’m running a 4200X - Roku 3 with software v6.2 build 3332.

I’m opening a client to the IP address port 8060, if that’s not correct please let me know.
Just open that URL in a web browser - click http://192.168.1.233:8060/query/apps - and you should see the listing, it is that simple. If it shows in browser, then there is some quirk in your client. Btw I have an ECP app and if this broke, i’d be having a few complaints in my inbox already… nope, nothing - weather is clear!

The curl command you posted is not valid. The HTTP stuff you typed after the URL is not sent to the unit. That’s not how curl works. If you type the command EXACTLY the way I typed it (replacing xxx with your IP address), it should work. Also note that you need TWO CR-LF sequences (four characters) after the GET line, one to terminate the line and one to indicate an empty line. If you still think it’s not working correctly, please post the complete shell session that you’re using to demonstrate the problem.

–Mark

-v is your friend:

$ curl -v "http://192.168.1.28:8060/query/apps HTTP/1.1\r\n"
* About to connect() to 192.168.1.28 port 8060 (#0)
*   Trying 192.168.1.28...
* Adding handle: conn: 0x7fbbd0804400
* Adding handle: send: 0
* Adding handle: recv: 0
* Curl_addHandleToPipeline: length: 1
* - Conn 0 (0x7fbbd0804400) send_pipe: 1, recv_pipe: 0
* Connected to 192.168.1.28 (192.168.1.28) port 8060 (#0)
> GET /query/apps HTTP/1.1\r\n HTTP/1.1
> User-Agent: curl/7.30.0
> Host: 192.168.1.28:8060
> Accept: */*
> 
< HTTP/1.1 400 Bad Request
* Server Roku UPnP/1.0 MiniUPnPd/1.4 is not blacklisted
< Server: Roku UPnP/1.0 MiniUPnPd/1.4
< Content-Length: 0

See where it says “GET /query/apps HTTP/1.1\r\n HTTP/1.1”? Yes, have no business manually slapping “HTTP/…”.

And btw, this doesn’t even send CR+LF but the 4 characters \ r \ n. I wondered how is that done in shell and seems the right way is $‘yada \r\n yada’. But regardless, it won’t work even then.

So back to the first post. The same thing happens with the GET request, 400 error. This had been working for over a year, there’s nothing wrong with the old code, here is a code snippet from the program, \x being the escape character for this compiler to concatenate the CR-LF-CR-LF onto the end of the statement.

tx$ = "GET /query/apps\x0D\x0A\x0D\x0A";

and

tx$ =  "curl http://192.168.1.233:8060/query/apps\x0D\x0A\x0D\x0A"

Results in the exact same 400 error, using the -v did not print out a more verbose message in my console.

(\r and \n are shortcuts in this compiler, but I’ve changed it to be straight up hex as above)

Ok, you’re still confused. The curl command should be typed in a Linux shell, not sent to the unit via some programmatic networking API. The curl command doesn’t need any CR-LFs at the end. The GET line needs the CR-LFs at the end. Without seeing more of your code it’s hard to say what you’re doing wrong, but it doesn’t look like you’re sending the Host header, which is also required in HTTP 1.1. Did you confirm that it works in a browser as EnTerr suggested?

–Mark

“RokuMarkn” wrote:
Ok, you’re still confused. The curl command should be typed in a Linux shell, not sent to the unit via some programmatic networking API. The curl command doesn’t need any CR-LFs at the end. The GET line needs the CR-LFs at the end. Without seeing more of your code it’s hard to say what you’re doing wrong, but it doesn’t look like you’re sending the Host header, which is also required in HTTP 1.1. Did you confirm that it works in a browser as EnTerr suggested?

–Mark

The only thing I’m confused about is why it stopped working with the GET after over a year of operation. Did something change in the way I need to send this data? Seriously, all I was doing previously is opening a client to 192.168.1.233:8060, and upon a connection, send “GET /query/apps HTTP/1.1\r\n\r\n”. This all worked fine, what has changed in what you’re evidently requiring now?

So here’s the code, it was working with \r\n\r\n instead of \x0D\x0A\x0D\x0A that it appears I now have to use to get it working. And I’ve further edited it to test without HTTP/1.1 and that doesn’t work.

STRING_FUNCTION queryServices()
{
	TRACE("In queryServices Function");                                  
	tx$ = "GET /query/apps HTTP/1.1\x0D\x0A\x0D\x0A";
	TRACE("tx$ = %s", tx$);
	RETURN(tx$);
}

STRING_FUNCTION directAppSelect(INTEGER selApp)
{
	TRACE("In directAppSelect Function");
	tx$ = "POST /launch/" + service[selApp].appID + " HTTP/1.1\x0D\x0A\x0D\x0A";
	currentlySelectedAppID = selApp;
	TRACE("tx$ = %s", tx$);
	RETURN(tx$);
}

STRING_FUNCTION keyCommand (STRING key$)
{
	tx$ = "POST /" + key$ + " HTTP/1.1\x0D\x0A\x0D\x0A";
	RETURN(tx$);
}