When a Google App Engine endpoint API is called immediately once the page is loaded, the following error is thrown. I need to wait for few seconds to call the API.
Then is same when the page is reloaded by some other means, say called from an other page etc.
I have tried adding a callback to call the API after few milliseconds $timeout(queryCallback, 100, false); The results are the same.
Is this a AngularJS error or resource load error? How to solve the error, please share your comments.
angular-1.2.16.min.js:89 TypeError: Cannot read property 'queryInfo' of undefined
at h.$scope.queryInfoAll (controllers.js:641)
at $scope.queryInfo (controllers.js:616)
at angular-1.2.16.min.js:119
at e (angular-1.2.16.min.js:37)
at angular-1.2.16.min.js:40
controllers.js:641
gapi.client.database.queryInfo().execute(function (resp) {
}
In looking at the Java endpoints example here, you use endpoints in javascript by initializing via a call to
<script src="https://apis.google.com/js/client.js?onload=init"></script>
...which calls the JS method named "init", which is a method name of your choosing. This is, however, a plain ole JS method that is unaware of the AngularJS lifecycle. In your init method, it seems you explicitly init your specific endpoint library, as in:
gapi.client.load(apiName, apiVersion, callback, apiRoot);
So, in your "run()", you may have to ask if "gapi" exists and defer until it is. You would then call "gapi.client.load()" with the callback function set.
Related
I'm working on an in-browser call-centre application and am using the Twilio JavaScript SDK to achieve this. I have created a TwiML application in the Twilio console and provided a 'voice request URL' to return the TwiML, and this works successfully.
The part I'm struggling with is getting the call status returned once the call has ended. The console allows me to provide a 'Status Callback URL' however I need to also pass a dynamic reference to this url to look up specific details about the context of the call within my database.
To initiate the call, I call the connect method passing my reference ie..
Twilio.Device.connect({
Reference: $(this).data('reference')
});
However this does not get passed along with the parameters within the status callback url.
Twilio developer evangelist here.
I assume you are storing some details about the call already. I recommend you also store the call's SID. This is the id for the call within Twilio and will be sent in the parameters of the status callback URL. If you store the Call SID with the other details you keep, then you can match up the callback too.
I'm just trying to verify if an Account exists with a particular email, however I learned that Accounts.findUserByEmail() only works server-side.
It would appear the repeatedly-suggested way would be to define a Meteor.method() and do all the work in there. Unfortunately I apparently have no idea what I'm doing because I'm getting an error that no one else has been getting.
component.js:
Meteor.call('confirm', email);
methods.js:
Meteor.methods({
'confirm': (email) => {
if (Accounts.findUserByEmail(email)) {
return;
}
}
});
All I get is this error:
Exception while simulating the effect of invoking 'confirm' TypeError: Accounts.findUserByEmail is not a function
Am I completely misunderstanding the dynamic of Meteor.methods + Meteor.call? Is it not actually server-side??
Currently using Meteor package, accounts-password#1.3.3
Meteor simulates method calls in the front-end too by running "stubs" of your methods. The idea is to have a better user experience because the UI is updated immediately before the server has responded. However this also means that if you run server-only code in Meteor methods, you have to make sure that the code is only run on the server:
Meteor.methods({
'confirm': (email) => {
if (Meteor.isServer && Accounts.findUserByEmail(email)) {
return;
}
}
});
Alternatively, you can place the above method definition in a file that is only loaded on the server, like any file on the /server-directory or (recommended) in /imports to a file that is only included by server code. Then you shouldn't need to use Meteor.isServer separately.
If your client-side code includes a method definition, it is treated as a stub, which means that it is run in a special mode that provides "optimistic UI" and its effects on data are undone once the actual server method returns its response to the client.
It could be worthwhile to implement different versions of (at least some of the) methods for the client and server, and to avoid including some of them on the client altogether.
If you choose to use the same function on both the client and the server, there are Meteor.isServer, Meteor.isClient and this.isSimulation (the latter is specifically for the methods), that allow you to execute some of the blocks only on the client/server.
Note that the code in your question does not do what you expect it to, and you do not check the method argument.
For this specific use case, you should probably only implement the method on the server (simply don't import its code in your client build):
Meteor.methods({
isEmailInSystem(email) {
check(email, String);
return !!Accounts.findUserByEmail(email);
}
});
You can read more about the method lifecycle in The Meteor Guide.
From the guide (gist, some details omitted):
Method simulation runs on the client - If we defined this Method in client and server code, as all Methods should be, a Method simulation is executed in the client that called it.
The client enters a special mode where it tracks all changes made to client-side collections, so that they can be rolled back later. When this step is complete, the user of your app sees their UI update instantly with the new content of the client-side database, but the server hasn’t received any data yet.
A method DDP message is sent to the server
Method runs on the server
Return value is sent to the client
Any DDP publications affected by the Method are updated
updated message sent to the client, data replaced with server result, Method callback fires
After the relevant data updates have been sent to the correct client, the server sends back the last message in the Method life cycle - the DDP updated message with the relevant Method ID. The client rolls back any changes to client side data made in the Method simulation in step 1, and replaces them with the actual changes sent from the server in step 5.
Lastly, the callback passed to Meteor.call actually fires with the return value from step 4. It’s important that the callback waits until the client is up to date, so that your Method callback can assume that the client state reflects any changes done inside the Method.
All meteor methods can be called same way from client and server side.
Let's say user knows or can predict all the method names on server, then he is able to call them and use it's result however he want.
example:
A method which performs cross domain http request and return response can be used to overload server by calling huge amounts of data Meteor.call(httpLoad, "google.com");, or a method which load data from mongo can be used to access database documents if the client know document _id Meteor.call(getUserData, "_jh9d3nd9sn3js");.
So, how to avoid this situations, may be there is a better way to store server-only functions than in Meteor.methods({...})?
Meteor methods are designed to be accessed from the client, if you don't want this, you just need to define a normal javascript function on the server. A really basic example would be:
server/server.js:
someFunction = function(params) {
console.log('hello');
}
As long as it's in the server folder, the function won't be accessible from the client.
For coffeescript users, each file is technically a separate scope, so you would have to define a global variable with #, e.g.
#someFunction = (params) ->
console.log 'hello'
or if you want to scope the function to a package:
share.someFunction = (params) ->
console.log 'hello'
If you have methods that need to be accessible from the client but only for say admin users, you need to add those checks at the start of the meteor method definition:
Meteor.methods({
'someMethod': function(params) {
var user = Meteor.user();
if (user && (user.isAdmin === true)) {
// Do something
} else {
throw new Meteor.Error(403, 'Forbidden');
}
}
});
I'm not going to vouch for the security of this example - it's just that, an example - but hopefully it gives you some idea of how you would secure your methods.
EDIT: Noticed the other answers mention using a if (Meteor.isServer) { ... } conditional. Note that if you are doing this inside methods which are also accessible on the client, the user will be still be able to see your server code, even if they can't run it. This may or may not be a security problem for you - basically be careful if you're hardcoding any 3rd-party API credentials or any kind of sensitive data in methods whose code can be accessed from the client. If you don't need the method on the client, it would be better to just use normal JS functions. If you're wrapping the whole Meteor.methods call with a isServer conditional, the code will be on the server only, but can still be called from the client.
as rightly stated in other answers, your methods will always be accessible from the client (per design). yet, there is a simple workaround to check if the call originates from the client or from the server. if you do a
if ( this.connection == null )
this will return true if the method was called from server. like that you can restrict the method body execution to 'secure' calls.
I think this page explains it: http://meteortips.com/first-meteor-tutorial/methods/
I'm quoting:
"The safer approach is to move these functions to the isServer conditional, which means:
Database code will execute within the trusted environment of the server.
Users won’t be able to use these functions from inside the Console, since users don’t have direct access to the server.
Inside the isServer conditional, write the following:
Meteor.methods({
// methods go here
});
This is the block of code we’ll use to create our methods."
and so on. I hope this helps.
With proper app design, you shouldn't care whether a request was through the web UI or via something typed in a console window.
Basically, don't put generic, abuse worthy functions in Meteor.methods, implement reasonable access controls, and rate-limit and/or log anything that could be a problem.
Any server-side function defined in Meteor.methods will have access to the current user id through this.userid. This userid is supplied by Meteor, not a client API parameter.
Since that Meteor Method server-side code knows the login status and userid, it can then do all the checking and rate limiting you want before deciding to do that thing that the user asked it to do.
How do you rate limit? I've not looked for a module for this lately. In basic Meteor you would add a Mongo collection for user actions accessible server-side only. Insert timestamped, userid specific data on every request that arrives via a Meteor method. Before fulfilling a request in the server method code, do a Mongo find for how many such actions occurred from this userid in a relevant period. This is a little work and will generates some overhead, but the alternative of rate-limiting via a server-wide underscore-style debounce leaves a function open for both abuse and denial-of-service by an attacker.
From the Chrome console window of my Chrome app, I'm making these calls:
window.navigator.appVersion.match(/Chrome\/(.*?) /)[1];
"37.0.2062.120"
chrome.identity.getProfileUserInfo(console.log)
undefined
Why is the callback (console.log) never called? It should print a userInfo object returned w/o needing network IO. I'm getting no callback in the console, or in the code run in my app.
The API is here: https://developer.chrome.com/apps/identity#method-getProfileUserInfo
What did I miss?
Thanks!
console.log is not a JavaScript function. Pass a function (an anonymous function will do) with an argument to the API call, and see if you get something then. Also, this API requires that the manifest.json file have "identity" permission, and (1) you may not have that in the manifest, or (2) you do, but somehow the API call isn't permitted when typing directly to the console (something I personally have never done). If your tests indicate that #2 is a possibility, put the API call into a JavaScript file and try it that way.
I'm using WinJS.xhr to call a ReST service... when I call the url on the browser I can see the complete returned xml. So I want to parse that xml to show some of the data.
WinJS.xhr({ url: "http://myserver/myservice" }).
then(processPosts, downloadError);
The problem is my downloadError function does not have parameters so I have no idea what went wrong.
What am I missing?
The help page is not very helpful :(
Edit: I used to fiddler to see what's on the wire and I don't see the request. The server I'm targeting is my own LAN, I also tried with its IP Address with same results (none)
When there is an error the callback function will take one parameter. The downloadError will need to take in one parameter. If you define downloadError as follows you should get more details. The result type should be XMLHttpRequest and using that you can see the status of the request and why it failed.
function downloadError(result){
//check the result param.
}
EDIT:
Check the app capabilities in your application.AppManifest file. The capabilities section is where you define what capabilities are required by your app for example connect to the internet, use the webcam.