Indigo RESTful API / URL Examples

Posted on
Mon Mar 30, 2009 6:58 pm
matt (support) offline
Site Admin
User avatar
Posts: 21411
Joined: Jan 27, 2003
Location: Texas

Indigo RESTful API / URL Examples

New to Indigo 4.0.0 beta 6 is a RESTful API for Indigo's Web server. What does that mean? It means there is now a standard way to get and modify Indigo Devices and Variable values using HTTP. I put together a Wiki page with several Indigo RESTful examples, both using URLs and curl. Hopefully, this will make reading and modifying Indigo Devices (and Vars) a bit easier from remote Web applications, scripts, plug-ins, etc.

Image

Posted on
Tue Mar 31, 2009 10:40 am
asw24b offline
Posts: 222
Joined: Dec 30, 2007
Location: Los Altos Hills, CA

(No subject)

Very cool !

Thanks !!

Posted on
Fri Jun 13, 2014 9:36 pm
mark_anderson_us offline
Posts: 65
Joined: Jun 05, 2014

Re: Indigo RESTful API / URL Examples

Hi Guys

I'm developing in Visual Studio on a virtual machine. The host OS is OS X and Indigo is running there. If I run the following on the Mac everything is OK

http://127.0.0.1:8176/devices/ I get the device list

IF I change it to use my IP

http://192.168.168.157:8176/devices/ from either the local Mac or the Windows VM, I am prompted fro a password. This means my rest calls fail.

My firewall is off.

So two questions, from the same browser on Mac, why is work with loopback address but not real IP.

How do I pass credentials in my Rest calls?

Thanks

MArk

Posted on
Sat Jun 14, 2014 2:08 am
howartp offline
Posts: 4559
Joined: Jan 09, 2014
Location: West Yorkshire, UK

Re: Indigo RESTful API / URL Examples

mark_anderson_us wrote:
So two questions, from the same browser on Mac, why is work with loopback address but not real IP.

How do I pass credentials in my Rest calls?

Thanks

MArk

Hi Mark,

I've just replied to your other thread about passing credentials to Indigo in AngularJS.

With regards loopback versus real IP, I suspect that is built into the authentication systems that I've explained on that thread; your research on how to use "withAuthentication: true" will being you to references about Cross-Site requests.

If you are writing code to retrieve files from a webserver, you can quite happily retrieve
Code: Select all
<img src="../secure/topsecret.jpg">
because it is on the same server.

If you try and retrieve
Code: Select all
<img src="www.mywebsite.com/secure/topsecret.jpg">
you will be challenged for authentication UNLESS you have told mywebsite to accept traffic from YourWinVM.local as trusted. (I'm not sure you do that, but that's the theory as I understand it...) You are trying to access resources cross-site, ie between your site and the remote site (which just happens to be your own) which isn't permitted for security reasons.

If you try and retrieve
Code: Select all
<img src="www.othersite.com/secure/topsecret.jpg">
and that site has authentication turned on, you will be challenged for authentication which you won't be able to provide, and the owner is unlikely to have configured your network as trusted.

The same applies on local webservers - if you are writing code to communicate with 127.0.0.1, it knows you are on the same server. If you try and communicate with 192.168.168.157, it treats you as a remote user and you have to authenticate.

Peter

Posted on
Sat Jun 14, 2014 7:06 am
mark_anderson_us offline
Posts: 65
Joined: Jun 05, 2014

Re: Indigo RESTful API / URL Examples

Thanks Peter.

What's strange is if I put the loopback URL in safari it works. I created a web server on OS X and called that from safari on same mac (where inidigo is) using the loopback address and I get:

XMLHttpRequest cannot load http://localhost:8176/devices/. Cross origin requests are only supported for HTTP.

I have a method to remove the cross origin request denial, so I'll give that a trt

Regards

mark

Posted on
Sat Jun 14, 2014 7:11 am
howartp offline
Posts: 4559
Joined: Jan 09, 2014
Location: West Yorkshire, UK

Re: Indigo RESTful API / URL Examples

mark_anderson_us wrote:
What's strange is if I put the loopback URL in safari it works.

Yes, because the loopback URL / IP is always local.

Peter

Posted on
Mon Jun 16, 2014 7:12 am
mark_anderson_us offline
Posts: 65
Joined: Jun 05, 2014

Re: Indigo RESTful API / URL Examples

So, I spent hours on this over weekend and am at a complete standstill.

I have an angular app that I can use to query git hub repos, so I know everything i good on my web server and client app. I replaced the URL for github with the URL for my Indiigo server device list and it fails with:

XMLHttpRequest cannot load http://172.30.90.30:8176/devices. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:50376' is therefore not allowed access. (http://localhost:50376 is my dev web server). This seems to be a CORS issue and it seems to me like the API needs changing: http://enable-cors.org/server.html

I don't have much experience in this area. Anyone got any ideas/suggestions?

This the header from my API call:

Code: Select all
Key   Value
Request   GET /devices HTTP/1.1
Referer   http://localhost:50376/index.html
Accept   application/json, text/plain, */*
Accept-Language   en-US
Origin   http://localhost:50376
Accept-Encoding   gzip, deflate
User-Agent   Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
Host   172.30.90.30:8176
DNT   1
Connection   Keep-Alive
Cache-Control   no-cache



This is the header from the reply, but the body is empty.

Code: Select all
Key   Value
Response   HTTP/1.1 200 OK
Server   IndigoWebServer/5.0
Allow   GET, HEAD, POST, PUT
Date   Mon, 16 Jun 2014 13:24:52 GMT
Content-Type   text/html;charset=utf-8
Content-Length   597


From what I understand the response needs to contain an Access-Control-Allow-Origin: header

From the link above:

valid CORS responses; omitting the header will cause the CORS request to fail. The value of the header can either echo the Origin request header (as in the example above), or be a '*' to allow requests from any origin. If you’d like any site to be able to access your data, using '*' is fine. But if you’d like finer control over who can access your data, use an actual value in the header.


Regards

Mark

Posted on
Mon Jun 16, 2014 8:15 am
mark_anderson_us offline
Posts: 65
Joined: Jun 05, 2014

Re: Indigo RESTful API / URL Examples

OK, so I did some more testing. Below is a simple HTML page that should display the servers response. If you try one of the two commented out URL's, they work great. The one to my indigo just fails (note I have authentication off on Indigo while i test)

Code: Select all
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
</head>
<body>
    <p align="center" style="font-size: 20px;">
        <a href="#" onclick="makeCorsRequest(); return false;">Test</a>
    </p>
    <div id="response">

    </div>
</body>
<script >
    // Create the XHR object.
    function createCORSRequest(method, url) {
        var xhr = new XMLHttpRequest();
        if ("withCredentials" in xhr) {
            // XHR for Chrome/Firefox/Opera/Safari.
            xhr.open(method, url, true);
        } else if (typeof XDomainRequest != "undefined") {
            // XDomainRequest for IE.
            xhr = new XDomainRequest();
            xhr.open(method, url);
        } else {
            // CORS not supported.
            xhr = null;
        }
        return xhr;
    }

    // Helper method to parse the title tag from the response.
    function getTitle(text) {
        return text.match('<title>(.*)?</title>')[1];
    }

    // Make the actual CORS request.
    function makeCorsRequest() {
        // All HTML5 Rocks properties support CORS.
        //var url = 'http://updates.html5rocks.com';
        //var url = 'https://api.github.com/users/angular';
        var url = 'http://172.30.90.30:8176/devices.xml/';


        var xhr = createCORSRequest('GET', url);
        if (!xhr) {
            //alert('CORS not supported');
            document.querySelector('#response').innerHTML = 'CORS not supported';
            return;
        }

        // Response handlers.
        xhr.onload = function () {
            var text = xhr.responseText;
            //var title = getTitle(text);
            //alert('Response from CORS request to ' + url + ': ' + title);
            document.querySelector('#response').innerHTML = text; //url + ': ' + title;
        };

        xhr.onerror = function () {
            //alert('There was an error making the request.');
            document.querySelector('#response').innerHTML = 'There was an error making the request.';
        };

        xhr.send();
    }
</script>
</html>

Posted on
Mon Jun 16, 2014 9:09 am
matt (support) offline
Site Admin
User avatar
Posts: 21411
Joined: Jan 27, 2003
Location: Texas

Re: Indigo RESTful API / URL Examples

I don't know if this is related to the problem but instead of:

Code: Select all
        var url = 'http://172.30.90.30:8176/devices.xml/';

You should have:

Code: Select all
        var url = 'http://172.30.90.30:8176/devices.xml';

That is, devices.xml is the file/object to be retrieved not a folder/directory.

Edit: Nevermind -- I just tried manually and they both worked, so the Web server is smart enough to automatically drop the ending /.

Image

Posted on
Mon Jun 16, 2014 9:36 am
mark_anderson_us offline
Posts: 65
Joined: Jun 05, 2014

Re: Indigo RESTful API / URL Examples

Hi Matt

Spent a few more hours researching this and I can't see way around this without support for CORS (adding the necessary headers in the outgoing response).

The root of the problem seems to be it's OK to use HTTP for cross domain (otherwise you wouldn't be able to browse the web), but API's use XMLHttpRequest which specifically blocks cross-domain. Like I said I'm no expert, but it seems the server responses need:

Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: *

Although it might be safer to allow the user to enter the values after Access-Control-Allow-Origin: so they can be a bit more secure for example they could add 3 domains and this would insert 3 headers

Access-Control-Allow-Origin: http://domain1.com
Access-Control-Allow-Origin: http://domain2.com
Access-Control-Allow-Origin: http://domain3.com

Any chance of getting this supported. I'm happy to beta test

Regards

Mark

Posted on
Mon Jun 16, 2014 9:49 am
RogueProeliator offline
User avatar
Posts: 2501
Joined: Nov 13, 2012
Location: Baton Rouge, LA

Re: Indigo RESTful API / URL Examples

Mark:

You might want to take a look at the HTML5 window.postMessage interface... this is designed to safely allow cross-domain and cross-frame communication. I have not actually used this, only read about it, so YMMV. However, in my reading it is designed to safely allow exactly what you are trying to achieve (note that even on the same server a different port is considered a foreign source from a cross-site scripting perspective.

Adam

Posted on
Mon Jun 16, 2014 10:01 am
mark_anderson_us offline
Posts: 65
Joined: Jun 05, 2014

Re: Indigo RESTful API / URL Examples

Thanks Adam

Will take a look and report back. I realized the issue about the port no this morning. Wasted a lot time not knowing that :oops:

My other thought was to setup a proxy server. I figured that if it listened on (for example) port 9000 and redirected traffic to indigo and indigo then replied vie the proxy server, I *may* be able to insert the headers on the proxy server. Googled it a bit but everything with OS X and proxy came back with how to configure proxy settings. This is probably my last straw to clutch at. Hopefully the guys will add CORS support. Doesn't seem to be a big dev effort.

Thanks again

Mark

Posted on
Mon Jun 16, 2014 10:08 am
RogueProeliator offline
User avatar
Posts: 2501
Joined: Nov 13, 2012
Location: Baton Rouge, LA

Re: Indigo RESTful API / URL Examples

If I were you, I might consider looking at the Cheetah templating engine... since your overall layout should be standard HTML/JS, you could easily convert your existing code to be rendered via Cheetah (almost just drop it in place from my limited experience). An Indigo Web Server (IWS) Plugin can execute a Cheetah template, if I am not mistaken, so you would need only create an IWS Plugin (will take you like 20 minutes) that runs your Cheetah template. Thus, you are on the same server and port. As a bonus, I believe this will allow you to easily use Prism Reflector for secure access if you so desire.

I hadn't thought of that need before until you brought up the XSS issue.

Adam

Posted on
Mon Jun 16, 2014 11:07 am
jay (support) offline
Site Admin
User avatar
Posts: 18201
Joined: Mar 19, 2008
Location: Austin, Texas

Re: Indigo RESTful API / URL Examples

I'd caution anyone about building an IWS plugin - as we've stated before, we're going to be converting the web server to use the IOM to access the server (a la Server Plugins) rather than it's current built-in method. Those old communication methods will be deprecated so any existing IWS plugins will need to be rewritten, at least in terms of data access and communication with the Indigo Server process.

Now, if you're just building the IWS plugin to serve up your pages (so they can be used through the reflector) and rather than using the built-in database access/server communication you use the RESTful API, then the amount of change required to port your IWS plugin may be less (the current plan is to try to minimize any RESTful API changes, at least with respect to backwards compatibility). I want to stress however that we haven't even started down that road as of yet, so it's just a guess at this point. We may get further into porting IWS and determine that we'll need some significant rework that will break the existing IWS plugins beyond just server communication.

We don't currently have any plans to switch from CherryPy as the web server and Cheetah as the template engine, but even those aren't necessarily sacred if we determine there's a better way to go moving forward.

We just want to make it clear where we are with respect to IWS plugins.

Jay (Indigo Support)
Twitter | Facebook | LinkedIn

Posted on
Mon Jun 16, 2014 11:09 am
mark_anderson_us offline
Posts: 65
Joined: Jun 05, 2014

Re: Indigo RESTful API / URL Examples

Thanks Adam

That reminded me of the other avenue I was considering, which I may need to do anyway. I'm planning to use Angular and MVC, to test, I was having my controller call the existing RESTAPi's to display the devices, change settings, etc. This was going to be my proof of concept (along with a responsive design HTML client). As long as I got that bit working, I feel comfortable switching to Indigo.

The next thing would need to do is update the pages automatically. When I initiate the device change from my client's easy enough as I know what's change. However, i someone walks up to light switch and dims the light and my app is showing the lights for that room, it should update the UI to show the new dim level. The worst way to do this is full HTML page refreshes (highly undesirable), better: have the controllers get the latest states periodically, which would automatically update the views in the client (so I'm only updating parts of the DOM instead of entire page refreshes). Ideal case is to have the models only update on changes. I certainly haven't thought through the entire process yet, but my two preliminary thoughts were:

1) write a message handler in my backend that would listen for messages from Indigo. Then create triggers on device changes and have it send the message to my back end
2) write a plug-in that would do this more efficiently.

Took a quick look at the Cheetah pages and it looks like it might do it, but I'd still need to write the plug-in to detect status changes, so doesn't seem to matter whether I call cheetah templates or my controller. (Haven't read the API docs yet, as I was hoping to get basic stuff doe with Rest)

Regards

mark
Last edited by mark_anderson_us on Mon Jun 16, 2014 11:51 am, edited 1 time in total.

Who is online

Users browsing this forum: No registered users and 1 guest