Ionic $http.get issues


#1

I’m trying to get access to my portal through angularjs $http.get. I’m receiving a status of 401 now and this error. “No ‘Access-Control-Allow-Origin’ header is present on the requested resource.” I am running from Android phone.

Is there an example of this anywhere?

Thanks,
Cory


#2

Hi @cbrandes,

Thanks for posting! Sounds like you are running into cross-origin issues, and your browser will not allow you to request a resource in this fashion.

Are you using the Portals API to request resources from our platform? You for sure will want to using this API to interact with our Proof of Concept builder from a different application.

If you continue to have trouble, I would recommend posting back with capture or print out of your GET request. We may be able to spot something.

Thanks,
-Martin


#3

This is the call I am using. It is most likely filled with issues. :smile:

$http.get('http://m2.exosite.com/onep:v1/stack/alias?temp HTTP/1.1', 
{params:{'Content-type': 'application/x-www-form-urlencoded; charset=utf-8',
        'X-Exosite-CIK': <CIK filled here>
    }}).then(function(resp) {
console.log('Success', resp);
$scope.points[0].value = resp.data;

}, function(err) {
console.error(‘ERR’, err);
$scope.points[0].error = err;
});

Thanks,
Cory


#4

Hi Cory,
In your configuration object, the items you list as ‘params’ are actually ‘headers’, so you should swap that property name out, and see if this resolves your problem.

Here is an example of an Angular $http() request with a config object:
$http({
method: ‘GET’,
url: ‘/some/url.py’,
params: {
search: ‘something’ // will result in url /some/url.py?search=something
},
data: ‘… data for post/put requests…’,
headers: {
‘Accept’: ‘application/json’
},
cache: true,
});
– from https://groups.google.com/d/msg/angular/3GM6ztubvVA/LJpUs1im4_EJ

You can see above the difference in usage between headers and params. If fixing that doesn’t help, we can work with you on some possibilities for adding cross-origin request parameter to your headers, but read on as you may have simpler options.

Also, is there a reason you’re using the Device HTTP API with your Angular application, rather than the RPC API? Generally we recommend the HTTP API for bandwidth-constrained applications; the RPC API is more fully featured. http://docs.exosite.com/rpc/

To further simplify things, if your app is a Node app, I do recommend using our OneP library, which will allow you to more easily work with the One Platform without having to manage all the details of the calls yourself: https://github.com/exosite-labs/node-onep . Similar libraries for other platforms are located here: https://github.com/exosite-labs

Let us know if you have further questions!
Thanks,
Michelle


#5

I will take a look at the RPC api and the OneP lib. As far as the device call, just a lack of knowledge.

I did add a meta tag to my index.html file to help with the cross-origin stuff, but that was just a cut and paste from others code that had the same issue.

Appreciate the help,

Cory


#6

Pardon my newb status here with nodejs and ionic. I’ve installed the onep module in my ionic app (npm install onep). I can see the folder in the Source/node_modules/, copied the onep folder from Sources/node_modules/ to lib/. Added reference to the rpc.js in the index.html.

Added this line: var rpc = require(‘onep/rpc’); to my .controller. It seems to complain about the ‘require’ function.
** I removed this line from the controller and moved it to a factory. This helps the require issue, but now the build complains about the require call in the rpc.js file.

Thanks,
Cory


#7

The weekend attempt was a failure. I tried using browserify to use the node module, that only led to more issues trying to read the build.js file from the output. Back to square one.

Cory


#8

@cbrandes, the node library won’t work for you and actually calling the HTTP-RPC API won’t work at all. (I’m assuming you’re doing things in the browser, if I’m wrong this post might be completely incorrect.)

The HTTP-RPC API doesn’t support CORS which is why you’re seeing the cross-origin errors, see How do I do cross-domain request for why. The last part of that post is also my advice to you:

Also, if you are planning on doing this anyway despite the security
problems, there’s now an easier way to do this than setting up a proxy
server. We recently released a websocket API and webockets don’t seem to
have the same CORS requirements. http://docs.exosite.com/websocket/
It works just like the JSON RPC API over HTTP, but with the addition of
a ‘subscribe’ call that will let you listen for updates to individual
dataports.

I also created a basic library when I was playing with all this awhile ago myself, I will warn you it’s totally unofficial and not thoroughly tested, just something I created to scratch my own itch, see https://www.npmjs.com/package/jsonep

The other option would be to use the portals API as @Martin mentioned in the first reply, http://docs.exosite.com/portals/, if you’re more comfortable with directly making HTTP requests rather than using websockets or (poorly documented) libraries.


#9

Thanks, I’ll look into both.
All I really want right now is to pull one data point from my portal! How I do it doesn’t really matter.

Cory


#10

Trying the websocket approach and a security error. This was from an Android phone and chrome on the laptop. Refused to connect to ‘wss://m2.exosite.com/ws/’ because it violates the following Content Security Policy directive: "default-src ‘self’ http: ". Note that ‘connect-src’ was not explicitly set, so ‘default-src’ is used as a fallback.

My call to open the socket.
var ws = new WebSocket(“wss://m2.exosite.com/ws”);

Cory


#11

I’m not totally up on how Content-Security-Policy works, but my understanding is that is something that is set by your server’s response HTTP headers and is a method for further restricting what your pages’ javascript is allowed to do. This is to prevent against content injection and cross site scripting attacks.

My reading of Content Security Policy directive: "default-src 'self' http: " is that you’re asking the browser to restrict calls to only the server that served the page and only using http. It might be something to do with that meta tag that you added, otherwise if you’re not setting this manually, it might be something that your framework is doing automatically.


#12

@Patrick Removing the meta tag fixed my issue, ugh. I made a connection and the authentication returned ok. On to the next step, ask for data.

Thank,s
Cory


#13

Glad to hear it. Good luck!


#14

Is leaving this section out of the arguments frowned upon? According to the docs these all have defaults, but I am curious if I need to leave the value empty.
{
“starttime”: 1376709504,
“endtime”: 1376709527,
“limit”: 1,
“sort”: “desc”,
“selection”: “all”
}
I receive an error 501 when requesting the value from the portal. Here is my request

var request = {"calls": [{ "id": 1, "procedure": "read", "arguments": [ {"alias":"temp"} // { // "starttime": startTime, // "endtime": "", // "limit": 1, // "sort": "desc", // "selection": "all" // } ] }] };

Thanks,
Cory


#15

I seem to get a response, but invalid is the status of choice.

Thoughts,

Cory


#16

The final arguments are to remove starttime and endtime when they are not needed. I then successfully had data returned.

Thanks to all,

Cory


#17

Well I’m back trying to use the Portals API from my Ionic/android app. The websocket works, but is missing a bunch of calls this API offers. I’m struggling how I make this call “GET /api/portals/v1/data-sources/{data-source-rid}/data”.
I have tried a websocket (didn’t work) var request = 'GET /api/portals/v1/devices/'+ deviceRID +'/data-sources'; console.log('Sending request from refresh', request); ws.send(request); return defer.promise;
This returns an error (JSON parse errro).
What means should I be using to make this request from javascript?

Cory


#18

Hi @cbrandes,

The Portals API is expecting communication over HTTP rather than a web socket. IIRC web sockets just use HTTP as a handshake.

Feel free to go back to using the Angular JS method of sending messages from your app. Provided you send a valid request, you should get the response that you expect. E.G.

$http.get('http://HOSTNAME/PATH/PATH)

Thanks,
-Martin


#19

I get a response of 404 from the server. I assume my object I am passing is incorrect.

var obja = {method: 'GET', url:'https://portals.exosite.com/api/portals/v1/portal/data-sources/<CIK>/data', headers:{'Content-Type': 'application/json; charset=utf-8'}};

If I pass this object in I get a file not found. It seems to look local when I do this.

var obj = {method: 'GET', host: 'https://portals.exosite.com', url:'/api/portals/v1/portal/data-sources/<CIK>/data', headers:{'Content-Type': 'application/json; charset=utf-8'}};

Am I missing the boat completely?

I added Authorization to the headers. Issuing the cURL command (from Linux) with this URL results in a valid return.

[code]var authData = btoa(‘emailAddy:pword’);

var obja = {method: ‘GET’, url:‘https://portals.exosite.com/api/portals/v1/portal/data-sources//data’,
headers:{Authorization: "Basic "+authData,‘Content-Type’: ‘application/json; charset=utf-8’}};

[/code]

Thanks,
Cory


#20

Hi @cbrandes ,

I think in our eagerness to assist you in connecting your application to our platform, my colleagues and I described how to use three different APIs – sorry about that. We are pretty excited to talk about Exosite, and our new features. You will have to excuse our zeal to get new people and products connected to the platform.

Your last two posts have included calls that appear to be portmanteaus of different API’s endpoints that have a similar purpose. Which makes sense considering that you are likely new to using Exosite, and were just blasted with a ton of information.

I would recommend committing to the use of a single API. It sounds based on the feature support of Web Sockets and CORS rules of the One Platform, that the Portals API is what you need to use. In that case you will want to re-visit how you think of authorization in your application. Portals the application doesn’t always think that accessing objects and resource in Exosite requires using the client’s CIK explicitly. The app has its own permission scheme, which is is why its’ endpoints asks for basic authorization. Technically we support generating tokens, and you can read more about that here: http://docs.exosite.com/portals/#get-user-token. To get started, I would recommend hard-coding your credentials in your app, before trying to make anything complicated.

Making a request for a data sources data, you will want to read our available documentation carefully: http://docs.exosite.com/portals/#get-data-source-data

The first example object you posted immediately above appears to be partially complete. You appear to be passing a client’s CIK in your URL path, when you might want to be sending a data source’s RID instead. Your HTTP message also lacks authorization, or if you are trying to use the CIK for authorization, then you are not properly identifying the data source you mean to read.

I am not sure on how to properly send messages in Ionic or Angular, but consider the object below. I think this is closest to what you will want to send.

var obja = {method: 'GET', url:'https://portals.exosite.com/api/portals/v1/portal/data-sources/<RID>/data',
        headers:{'Authorization': 'Basic ' + authData, 'Content-Type': 'application/json; charset=utf-8'}};

If you continue to have trouble let us know. Looking at your code may require understanding of the framework that you are using, and I don’t have that. Though if you were to post a packet capture file of your transmission, I could more easily help troubleshoot what you are sending.

Happy to help,
-Martin