First of all, I must say that I'm very new to Google Closure, but I'm learning :)
Okay, so I'm making a web app that's going to be pretty big, and I thought it would be good to manage all the AJAX requests in one XhrManager. No problem there.
But, is it possible to have some kind of default callback that would check for errors first, display them if necessary and then when it passes, launch the "real" callback? I'm talking about a feature like the decoders in amplify.js. Here's their explanation:
Decoders allow you to parse an ajax response before calling the success or error callback. This allows you to return data marked with a status and react accordingly. This also allows you to manipulate the data any way you want before passing the data along to the callback.
I know it sounds complicated (and it is, really), so the fact that I'm not that good at explaining helps a good deal too, but yeah.
The solution I have in my head right now is creating an object that stores all the 'real callbacks', of which the 'error-checking callback' would execute the correct one after it finished checking, but I feel that's a bit hack-ish and I think there has to be a better way for this.
Since you always have to decode/verify your AJAX data (you never trust data returned from a server now do you?), you're always going to have different decoders/verifiers for different types of AJAX payloads. Thus you probably should be passing the decoder/verifier routine as the AJAX callback itself -- for verifications common to all data types, call a common function inside the callback.
An added benefit of this will be the ability to "translate" unmangled JSON objects into "mangled" JSON objects so that you don't have to do use quoted property access in your code.
For example, assume that your AJAX payload consists of the following JSON object:
{ "hello":"world" }
If you want to refer to the hello property in your code and still pass the Compiler's Advanced Mode, you'll need to do obj["hello"]. However, if you pass in your decoder as the callback, and the first line you do:
var decoded = { hello:response["hello"] };
then do your error checking etc. before returning decoded as the AJAX response. In your code, you can simply do obj.hello and everything will be nicely optimized and mangled by Advanced Mode.
Related
There's a bit of someone else's code I am trying to add functionality to. It's using websockets to communicate with a server which I will most likely not be able to change (the server runs on a 3$ micro-controller...)
The pattern used, for instance when uploading data to the server, consists in using global variables, then sending a series of messages on the socket, as well as having an 'onmessage' which will handle the response. This seems clumsy, given that it assumes that there is only ever one socket call made at a time (I think the server guarantees that in fact). The messages sent by the server can be multiple, and even figuring out when the messages are finished is fiddly.
I am thinking of making things so that I have a better handle on things, mostly w.r.t. being able to know when the response has arrived (and finished), going to patterns like
function save_file(name, data, callback) {
}
And perhaps at some point I can even turn them into async functions.
So couple of ideas:
- is there some kind of identifier that I could find in the websocket object that might allow me to better string together request and response?
- short of that, what is the right pattern? I started using custom events, that allows me to much better tie the whole process, where I can supply a callback by attaching it to the event, but even doing removeEventListener is tricky because I need to keep reference to every single listener to make sure I can remove them later.
Any advice anyone?
I know a couple of approaches using Ajax to manipulate database, I'm just not quite sure which one (if any) would be proper and most used so I have a couple of questions.
Have one url to handle all kind of requests accordingly or multiple for each specific reason?
Would it be better to have a single function containing Ajax request to which an object parameter can be passed to manipulated request (Url, Type, etc.) or multiple functions, each with static properties of Ajax request for specific thing?
What would be the most clean design pattern of structuring data manipulation? Thanks!
I'm not sure anyone can answer this definitively without more specific information about the domain you're dealing with. It's possible that there is a case where one function could deal with multiple CRUD operations based on the parameters passed in, and a clever architecture could make decisions based on the parameters.
In probably most cases the decision-making process would become very ugly (large switch statements, for example), and here more explicit functions and methods would be more descriptive and appropriate.
As mentioned by Steve in the comments, REST could be an appropriate way to differentiate server-side calls while using a single client-side AJAX function. All that's needed on the client is knowledge of the url to be used.
I just noticed that Meteor.call, the concept that prevent user from invoke collection's insert, update, remove method, still able to be invoked from JavaScript console.
For client's example:
// client
...
Meteor.call('insertProduct', productInfo);
...
Here's the server part:
// server
Meteor.methods({
insertProduct: function( productInfo ){
Product.insert(...);
}
})
OK, I know people can't invoke Product.insert() directly from their JavaScript console.
But if they try a little bit more, they'd find out there's Meteor.call() in client's JavaScript from Developer tool's resource tab.
So now they can try to invoke Meteor.call from their console, then try to guessing what should be productInfo's properties.
So I wonder how can we prevent this final activity?
Does Meteor.call done the job well enough?
or I'm missing something important?
Meteor.call is a global function, just like window.alert(). Unfortunately, there is nothing you can do from preventing a user calling Meteor.call. However, you can validate the schema of data and the actual data of what a user is sending. I'd recommend https://github.com/aldeed/meteor-simple-schema (aldeed:simple-schema as the meteor package name) to ensure you don't get garbage data in your project.
As others pointed out, "Meteor.call" can surely be used from the console. The subtle issue here is that there could be a legal user of a meteor app who can in turn do bad things on the server. So even if one checks on the server if the user is legal, that by itself does not guarantee that the data is protected.
This is not an issue only with Meteor. I think all such apps would need to potentially protect against corruption of their data, even through legal users
One way to protect such corruption is by using IIFE (Immediately Invoked Function Expression)
Wrap your module in a IIFE. Inside the closure keep a private variable which stores a unique one time use key (k1). That key needs to be placed there using another route -- maybe by ensuring that a collection observer gets fired in the client at startup. One can use other strategies here too. The idea is to squirrel in the value of k1 from the server and deposit it in a private variable
Then each time you invoke a Meteor.call from inside you code, pass k1 along as one of the parameter. The server in turn checks if k1 was indeed legal for that browser connection
As k1 was stored inside a private variable in the closure that was invoked by the IIFE, it would be quite difficult for someone at the browser console to determine the value of k1. Hence, even though "Meteor.call" can indeed be called from the browser console, it would not cause any harm. This approach should be quite a good deterrent for data corruption
As mentionned by #Faysal, you have several ways to ensure your calls are legit. An easy step to do so is to implement alanning:roles and do role checks from within your method like the following:
Meteor.methods({
methodName: function() {
if (!Roles.userIsInRole(this.userId, 'admin')) {
throw new Meteor.Error(403, 'not authorized);
} else { yourcode });
This way, only admin users can call the method.
Note that you can also check this.connection from within the method and determine if the call comes from the server (this.connection === false) or from the client.
Generally speaking, doing checks and data manipulations from your methods is a nice way to go. Allow/deny are nice to begin with but become really hard to maintain when your collections get heavier and your edge-cases expand.
You cannot block Meteor.call from the console, just like you can't block CollectionName.find().count() from the console. These are global functions in meteor.
But there are simple steps you can take to secure your methods.
Use aldeed:simple-schema to set the types of data your collection can accept. This will allow you to set the specific keys that your collection takes as well as their type (string, boolean, array, object, integer) https://github.com/aldeed/meteor-simple-schema
Ensure that only logged in users can update from your method. Or set global Allow/Deny rules. https://www.meteor.com/tutorials/blaze/security-with-methods && https://www.discovermeteor.com/blog/allow-deny-a-security-primer/
Remove packages insecure and autopublish
The simple combo of schema and allow/deny should do you just fine.
As you know by now that you can't really block calling Meteor.call from Javascript console, what i'd like to add as a suggestion with #Stephen and #thatgibbyguy that, be sure to check your user's role when adding documents into the collection. Simple-Schema will help you prevent inserting/updating garbage data into the collection. and alanning:roles package certainly makes your app secure by controlling who has the permission to write/read/update your collection documents.
Alanning:roles Package
I know these types of question come up fairly often, but I need help with a wait-like mechanism in JavaScript. I know setTimeout-based solutions are going to come up, but I'm not sure how to pull it off in my case.
I'm writing an API that uses a WebSocket internally. There's a connect() method that sets up the WebSocket, and I need to make it not return until after the WebSocket is set up. I'd like it to return a value for whether or not the connection was successful, but that's not the main problem.
The issue I'm hitting is that after a user calls connect(), they may call another method that relies on the WebSocket to be properly set up. If it's called too early, an error is thrown stating that the object is not usable.
My current solution is setting a "connected" flag when I've determined a successful connection and in each method checking for it in each method. If it's not connected, I add the method call to a queue that is ran through by the same code that sets the flag. This works, but it introduces that style of code all over my methods and also seems misleading from the user-perspective, since the call of those functions is deferred. Also, if there is other user code that relies on those calls being completed before it gets to them, it won't behave as expected.
I've been racking my brain with how to handle this case. The easiest solution is to just find a way to block returning from connect until after the WebSocket is set up, but that's not really the JavaScript way. The other option was to make them provide the rest of their code in a callback, but that seems like a weird thing to do in this case. Maybe I'm over-thinking it?
Edit: To better illustrate my problem, here's a example of what the user could do:
var client = new Client(options);
client.connect();
client.getServerStatus();
The getServerStatus() method would be using the WebSocket internally. If the WebSocket is not set up yet, the user will get that not usable error.
Todays Javascript does not really work like that unfortunately. In the future (ECMA6) there may be new language features that address this issue more directly. However for now you are stuck with the currently accepted method of handling asynchronous events, which is limited to callbacks. You may also want to explore 'promises' to handle 'callback hell' however you will need a library for this.
And yes it does seem strange to have callbacks everywhere, especially for someone new to web programming, however it is really the only way to go about it at this stage (assuming you want a cross-browser friendly solution).
"Wait" is almost the keyword you are looking for. Actually, it's yield that does this. See e.g. MDN's documentation.
There's a connect() method that sets up the WebSocket, and I need to make it not return until after the WebSocket is set up
That isn't going to happen unless you rewrite the javascript execution engine.
Either the code trying to send data will need to check the socket state (I'd go with encapsulating the socket in a object, supplying a method which sets a member variable on the open/close events and poll the state of that member variable from the external code). Alternatively you could add messages and call backs to a queue and process the queue when the socket connects.
I'm trying to come closer to a solution for the problem of my previous question.
The scheme I would like to try is following:
User requests an action from RoR controller.
Action makes some database queries, makes some calculations, sets some session variable(s) and returns some RJS code as the response. This code could either
update a progress bar and make another ajax request.
display the final result (e.g. a chart grahic) if all the processing is finished
The browser evaluates the javascript representation of the RJS. It may make another (recursive? Is recursion allowed at all?) request, or just display the result for the user.
So, my question this time is: how can I embed a XMLHttpRequest call into rjs code properly?
Some things I'd like to know are:
Should I create a new thread to avoid stack overflow. What rails helpers (if any) should I use?
Have anybody ever done something similar before on Rails or with other frameworks?
Is my idea sane?
You may find RJS information harder to come by these days, I think unobtrusive JavaScript has gained more mindshare in the Rails community. What you're describing is certainly possible. My suggestion is to spend a little time learning AJAX with jQuery. Here are some steps you might take: 1) make a GET request to controller action, 2) do something, respond with JSON, 3) in your success handler code client side, determine if you need to call the server again.
Check the Railscast on jQuery, here is the transcription
http://asciicasts.com/episodes/136-jquery
jQuery $.get() or $.getJSON
http://api.jquery.com/jQuery.get/
Rails' respond_to block, check out the "wants.js" code here
http://www.mckinneystation.com/2009/07/13/rails-respond_to-made-it-too-easy/
You could respond with your Ruby object serialized as JSON:
render :json => #thing.to_json
Using $.getJSON() will deserialize the response into a JavaScript object, so you easily access properties with the dot syntax. e.g. (pseudo-code):
$.getJSON('/url-to-thing.js', function(thing) {
if( thing.status != 'done' ) { /* call function again */ }
});
In this way, the function would stop being called once the 'thing' is 'done.' Getting comfortable with the responsibilities of the client and server parts can be daunting initially but will pay off in the long run by allowing you to develop far more dynamic and interactive web applications.