How to propagate the ajax.abort() to the controller - javascript

I have a problem with propagating the aborting of my ajax call to the controller.
I have a JavaScript function in View code that may be called by a user at any point. This then transmits a value to the controller using ajax. The controller then does a time consuming opertion on the Input and returns a result.
What I want is that when user calls the function if it is already doing the time consuming opertation to either:
Stop and to start again with the new Input. In essence I need to propagate the abort call up to my controller code and deal with it accordingly
OR
I need to be able to run multiple simultaneous instances of the controller function.
Is this possible? and what is the best way to do it.
View Code
var AJAXSetPalette = null;
function DoSometing(Input) {
if (AJAXSetPalette)
AJAXSetPalette.abort();
AJAXSetPalette = $.ajax({
type: "POST",
url: "ImagesAnalysis/DoSomething",
datatype: "json",
traditional: true,
data: Input,
success: function (Data) {
DoJSFunction(Data);
}
return;
}
Controller
public int DoSomething(int Input)
{
int RetVal
//Calculate RetVal from Input, very Time Consuming
Return RetVal
}

This is a client-server issue. Connections between a client and a server in HTTP are not persistent. The client opens a connection to the server and makes a request. The connection is then closed. The server processes the request, opens a connection back to the client, and sends the response.
Note: As of HTTP 1.1, this is not technically true any more. Connections are actually persisted in many cases over HTTP 1.1, but merely to reduce the delay from having to re-establish the connection. In principle, both the client and server still behave as if the connection has been closed.
The point is that once your AJAX request is sent, the server is merrily on its way processing the request. If the client should abort the request, there's no notification given to the server. When the server attempts to send the response, it will simply be refused, and the server will disregard it and move on to the next request.
That's how the TCP/IP and HTTP protocols were designed to behave, and it's what makes the Internet possible as a loosely connected network of nodes that can drop off or come online at will.
Long and short, there's no way to cancel the request on the server-side from the client once it's been sent.
For your scenario, the best thing would be to simply disable the user's ability to issue another request until the server has responded or some timeout period has elapsed. If the request is so resource intensive and you can call it as many times as you want as fast as you want, that's a huge opportunity for a DoS attack

Related

How detect changes of an api

I have a api that returns if the building is open and how much peapole are in there.
Now i want my Discord Bot to send a message when the Building opens.
How do i do that?
if the api recives a request the response is looks this :
state: {
open: false/true
}
It may be helpful to clear out the terminology: the "API" in this context is the endpoints exposed by the server and their request/response schemas (you can think of it as the fields you send and receive back). Now, this doesn't change in your case: it's the same endpoint, and the same fields. What changes is the value.
Now, you are probably doing a HTTP request to a given URL, where the server is. And in HTTP world, we say that we are requesting a resource. The resource behind https://stackoverflow.com is the homepage of this website. The resource behind the endpoint you are calling is a building's state. This resource changes overtime, it may open or closed at any time, people going in and out. But the API doesn't change in this case.
Let's reword your question, so it can be clearer: How can a client know when a HTTP resource changes? If your server only exposes this endpoint to know the state of the building, the answer is a sad "it can't". Let's say that I close the building, the server knows it somehow and now the building's state is {"open": false}. But the server doesn't have any mechanism to say to your client that the state changed, the server just waits for the client to ask what the state is, and returns. Allowing a server to send data to your client without the client requesting first adds some complexity to your architecture, and although there's a bonus (the client will know of state changes as soon as possible), in your case, it may not be necessary.
One alternative is long polling, in long polling your client makes a request to the server and the server doesn't respond immediately, it... waits. Waits for an update, like a change in building's state. When an update happens, then it sends a response. The client, in turn, requests again! And waits for the server to send an update... In practice, the client will keep up with the server state. The mentioned article for long polling gives a good example: https://javascript.info/long-polling#regular-polling
The one caveat is that the server must also support long polling. If the server just returns whatever the resource's state is, then the client will keep receiving the same state over and over. Another valid solution is instead of waiting for updates, the client keeps requesting the server for every few seconds. You may miss some updates! But in some cases, it's fine to lose track of a few updates.
Ok, enough theory. What about your case? If you want to know if a door is open or closed, but don't care to know when it happens, you can just request the server every five seconds or so:
In some pseudo javascript code, and very inspired by the long polling article mentioned before:
async function subscribe() {
let buildingState = null
while (true) {
const response = await fetch("/subscribe")
if (response.status != 200) {
// An error - let's show it
showMessage(response.statusText)
}
// Get and show the message
const message = await response.json()
// a function that returns true/false if the state is different
if (stateChanged(message, buildingState)) {
updateDiscordBot(message)
buildingState = message
}
// wait five seconds and repeat
await new Promise(resolve => setTimeout(resolve, 5000));
}
}
subscribe();
This works fine. But if you want for your client to immediately know when a door is opened or closed, this is not enough: opening and closing a door is a quite fast action, and even if you request the server every second, you may lose updates. In this case, the server needs to change. Either by implementing long polling, or something like websockets... you didn't mention that the server is in your control, but if it doesn't, it may be helpful to talk with who maintains it to work out a solution.
If you only have pull access to that API then the only way to detect state change is to periodically send a request, store response, and trigger your bot on stored response change.

Ajax server side setup and teardown

I have the following situation:
Server-side, I have a relational database, and am doing some rather computationally-intensive requests on it. For a request, there is a resource intensive setup task. Many of my requests require this same setup step, which I don't want to repeat, which leads me to want a single call. However, each request takes a lot of time, which makes me want to issue them asynchronously as several calls, so that the user gets stuff as it becomes available. I could try to just "keep the setup step around", but I don't really want the server to try to guess when the client is done, and it can't rely on the client to tell it when to clean up.
Here's what I would LIKE to happen:
- Client-side, I gather up the requests that I want to make, A,B and C. They all require the same setup step.
- So that I don't have to repeat the setup step, I issue one ajax call for A,B and C simultaneously.
- So that the user doesn't have to wait forever for results, I return answers for A,B and C asynchronously, handing them back to the client as the results become available.
Something like:
$.ajax({
type: "GET",
url: "/?A=1&B=2&C=3",
partialSuccess: function (data) {
if (partialSuccess.which == "A") {
doStuffForTaskA();
}
},
success: function (data) {
console.log("all tasks complete!");
}
});
I'm pretty sure the sort of thing I have in the code above is not possible. Any thoughts on the best way to accomplish what I'm trying to do? (I am also the author of the server-side code. It happens to be c sharp, but I'm somewhat more interested in this as a 'which protocol, and how does it work' question)

Will ajax in beforeunload reliably execute?

I have a HTML5 application that needs to send a disconnect ajax request when the user changes/refreshes the page. I am currently using this code:
window.addEventListener("beforeunload", function(event) {
$.ajax({
url: api_disconnect,
data: { identifier: token },
method: "GET"
});
});
I don't need to process the response, or even ensure that the browser receives a response. My question is, can I rely on the server receiving the request?
And if not, how can I accomplish this? Currently I have the app send an "I'm alive!" request every 15 seconds (which already feels like too much). I want the server to know the second the user disconnects.
To clarify, I know that if the browser/computer crashes there's nothing I can do about that. That's what the heartbeat is for. I just mean in a normal use case, when the user closes/changes/refreshes the page.
You cannot 100% rely on the ajax call getting through. You can test many browsers and operating systems and determine which ones will usually get the ajax call sent before the page is torn down, but it is not guaranteed to do so by any specification.
The heartbeat like you are using is the most common work-around. That will also cover you for a loss in network connection or a power-down or computer sleep mode or browser crash which the beforeunload handler will not.
Another work-around I've seen discussed is to use a socket.io connection to the server. Since the socket.io connection has both a small, very efficient heartbeat and the server will see the socket get closed when the page is closed, you kind of get the best of both worlds since you will see an abnormal shut-down via the heartbeat and you will see a normal shut-down immediately via the webSocket connection getting closed.

Error while getting messges from sockets in javascript

Hi i am having trouble with creating a socket communication from java script code.
I am always getting error while sending a message or closing the socket from server.
My Socket server code.
// Start listening for connections.
while (true)
{
Console.WriteLine("Waiting for a connection...");
// Program is suspended while waiting for an incoming connection.
Socket handler = listener.Accept();
data = null;
// An incoming connection needs to be processed.
while (true)
{
int bytesRec = handler.Receive(bytes);
data += Encoding.ASCII.GetString(bytes, 0, bytesRec);
break;
}
// Show the data on the console.
Console.WriteLine("Text received : {0}", data);
// Echo the data back to the client.
byte[] msg = Encoding.ASCII.GetBytes(data);
handler.Send(msg);
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
JavaScript code:
var connection = new WebSocket('ws://Myip:11000', ['soap', 'xmpp']);
// When the connection is open, send some data to the server
connection.onopen = function () {
connection.send('Ping'); // Send the message 'Ping' to the server
connection.send('your message');
};
// Log errors
connection.onerror = function (error) {
console.log('WebSocket Error ' + error);
};
connection.onclose = function (msg) {
console.log('WebSocket Error ' + msg);
};
It gets connected to server socket, but always gets error while closing or sending a message from server.
If this is really your actual code:
handler.Send(msg);
handler.Shutdown(SocketShutdown.Both);
handler.Close();
…then it's pretty broken. First, you can't assume that Socket.Send() actually sends all the bytes you asked it to. You have to check the return value, and keep sending until you've actually sent all the data.
Second, the initiation of a graceful closure should use SocketShutdown.Send, not SocketShutdown.Both. Specifying "Both" means (among other things) that you're not going to wait for the other end to negotiate the graceful closure. That you're just done and won't even receive any more data, in addition to being done sending.
And of course, the code is calling Close() before the other end has in fact acknowledged the graceful closure (by itself sending any remaining data it wanted to send and then shutting down with "Both").
Is all this the reason for your problem? I can't say for sure, since I have no way to test your actual code. But it's certainly a reasonable guess. If you tear down the connection without waiting after you try to send something, there's not any guarantee that the data will ever leave your machine, and in any case the other end could easily see the connection reset before it gets a chance to process any data that was sent to it.
There aren't a huge number of rules when it comes to socket programming, but what rules exist are there for a reason and are generally really important to follow. You should make sure your code is following all the rules.
(The rest of the code is also different from what I'd consider the right way to do things, but the problems aren't entirely fatal, the way that the over-eager connection destruction is).
I am afraid WebSocket does not work that way.
When the Javascript code connects to the server, it will send a HTTP request as ASCII text. That request will include a HTTP header Sec-WebSocket-Protocol: soap, xmpp, as you are requiring those protocols in your WebSocket creation.
Since your server code does not reply with an appropiate HTTP response accepting the websocket connection, the connection will fail. When you try to send data back, the client will not recognize it as a HTTP response and a error will be thrown.
A websocket is not a regular socket connection, it won't work that way. It requires HTTP negotiation and there is a schema for data framing. I recommend you to go through this article that explains very well how it works: http://chimera.labs.oreilly.com/books/1230000000545/ch17.html
If you are interested in learning how to develop a server, take a look to this tutorial in MDN: https://developer.mozilla.org/en-US/docs/WebSockets/Writing_WebSocket_server I also have an open source WebSocket server in C# you can take a look if you like.

Security in a Javascript based app -refreshing a users hash

I'm developing an hybrid mobile app using HTML/CSS/JS, I'm going over security with login information, the system I have set up creates an hash after a user logs in, this hash has a time limit and is set via localStorage
Essentially, I would have something like this is localstorage:
hash
5f4a09cfec2a6d8f306eecb3844e33e9
hash_expiration
1373012945
password
*encryted user password*
This hash is sent to my server for validation in the header of all my AJAX requests (accompanied by the user id for database matching)
I'm mostly opening this topic to discuss best practices on how to deal with recreating hash keys, I need to figure out a way to refresh a users hash key.
Considering my experience with AJAX and JS is still rather limited, I thought about using the AJAX setup to check for a new hash, like so:
$.ajaxSetup({
beforeSend: function(xhr, settings) {
var time = new Date().getTime(); //unix time
var hash_time = localStorage.getItem("hash_expiration");
if(time>hash_time){
//ajax request to fetch new hash, async: false to make sure this completes before continuing with other AJAX calls
}
}
});
I would send the user id and his encrypted password to verify him and return a new hash.
Should I be sending AJAX requests in the ajaxSetup's beforeSend? How would this conflict with other beforeSends across my application?
Basicallly on the clients side you shouldnt have anything except hash. On the server side this hash must be associated with user it belongs to, expire time and anything else you need.
Send this hash with each request, and on server side validate it. When it expires you have to send (server) appropriate headers like 401 - Unauthorized. Client have to understand that response and try to exchange hash to new one. And finally when client gets new valid hash it can resume sending requests.
... and you shouldnt check expire time at client, this job for server.
thanks.

Categories

Resources