Get method gets called n number of times when streaming MEAN stack - angularjs

I have a MEAN stack, when the frontend calls for a url like /movies/KN3MJQR.mp4,
the get block in the routes.js looks like this
app.get('/movie/:url', function(req, res) {
try {
var url = req.url.split('/')[2]
res.sendfile(moviesFolder + url);
#i want to add my logic for incrementing view count here.
} catch (e) {
console.log(e);
}
});
I want to add logic to increment the view count of each of the movie whenever a request is raised for the .mp4 . I tried adding the increment view count logic at the place commented in the code as shown above only to find that the whole get method gets called n number of times as the streaming happens. How do I handle this logic?
Update : Code to check the same as answered by #rsp
if(req.get('Range')===('bytes=0-')){
console.log('first call');
}else{
console.log('further call');
}

The endpoint can be hit many times because res.sendfile() supports ranges and the client can do multiple downloads of partial data.
You can inspect the relevant header with req.get('Range') and see if it's the first or last part (depending on whether you want to count every started download or only the finished ones).
For more info on the header, see:
https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35

Related

how to fetch the record from mongodb to part of html page automaticalyy without refreshing/reloading manually. using MEAN stack

Need some help reading Mean stack. I have a requirement like,
When a record is inserted into database, part of html page should get displayed with the new inserted record without reloading/refreshing manually.
Html page should get automatically updated with new record.
observations so far:
I am already using angularjs, nodejs and mongodb.
Using refresh() function, able to update part of hrml page manually.
I am to insert the record from html page to mongodb.
You should use websockets ( socket.io is a good option ).
In the route responsible for document insertion/update on the backend, you should emit a new_document signal with the document's body to all sockets in the site...
Example:
app.post('/api/posts', (req, res) => {
Post.insert(postBody).then(body => {
io.emit('new_document', body); // Broadcast to all websocket clients
res.json(body);
}).catch(err => {
console.error(err);
res.status(500).json({error: err.message});
});
});
Then, in the front-end, you should listen for the new_document event and call the refresh() function as callback or, even better, write a function to add just the new document.
Example:
socket.on('new_document', function (body) {
// ... code to add body to HTML ...
});

JMeter looping with indexes and property update

I'm attempting to create a test plan when a certain value is reached, then some functionality happens. The test plan consists of multiple threads running with a loop, and when some condition is reached I'd like to fire an HTTP request .
I'll drill down to the guts of it:
In my test I have logic in a looping way with multiple threads, and when a condition is met (the condition is met every 10 seconds) then I need to iterate through a value that it's value should be saved from the previous iteration - that value which I defined is a property (inside user.properties) - startIndex = 0 (initialized to 0).
So I've made a While Controller which it's condition is like this:
${__javaScript(${__P(startIndex,)}<=${currBulk},)}
And I expect the HTTP request, which depends on startIndex value inside the while to be executed when startIndex<=currBulk variable.
Inside the While Controller the HTTP request should to be fired until all indexes are covered, and I've written it like this inside BeanShell PostProcessor:
int startIndexIncInt = Integer.parseInt(props.getProperty("startIndex")); //get the initiated index of the loop
startIndexIncInt = startIndexIncInt + 1; //increment it and see if needed to fire the request again, by the original While condition
vars.put("startIndexIncIntVar", String.valueOf(startIndexIncInt));
props.put("startIndex",vars.get("startIndexIncIntVar")); //the property incremental and update
So, I designed it like in order that in the next time (after 10 more seconds) I'll have an updated startIndex that will be compared to the new currBulk (which is always updated by my test plan).
And I just cant have it done . I keep receiving errors like:
startIndexIncInt = Integer.parseInt(props.ge . . . '' : Typed variable declaration : Method Invocation Integer.parseInt
Needless to say that also the var startIndexIncIntVar I defined isn't setted (I checked via debug sampler).
Also, my problem isn't with the time entering the while, my problems are basically with the variable that I should increment and use inside my HTTP request (the while condition, and beanshell post processor script)
Just for more info on it, if I'd written it as pseudo code it would look like this:
startInc = 0
----Test plan loop----
------ test logic, currBulk incremented through the test-----
if(time condition to enter while){
while (startIndex <= currBulk){
Send HTTP request (the request depends on startIndex value)
startIndex++
}
}
Please assist
It appears to be a problem with your startIndex property as I fail to see any Beanshell script error, the code is good so my expectation is that startIndex property is unset or cannot be cast to the integer. You can get a way more information regarding the problem in your Beanshell script in 2 ways:
Add debug() command to the beginning of your script - you will see a lot of debugging output in the console window.
Put your code inside try block like:
try {
int startIndexIncInt = Integer.parseInt(props.getProperty("startIndex")); //get the initiated index of the loop
startIndexIncInt = startIndexIncInt + 1; //increment it and see if needed to fire the request again, by the original While condition
vars.put("startIndexIncIntVar", String.valueOf(startIndexIncInt));
props.put("startIndex", vars.get("startIndexIncIntVar")); //the property incremental and update
} catch (Throwable ex) {
log.error("Beanshell script failure", ex);
throw ex;
}
this way you will be able to see the cause of the problem in jmeter.log file
Actually it appears that you are overscripting as incrementing a variable can be done using built-in components like Counter test element or __counter() function. See How to Use a Counter in a JMeter Test article for more information on the domain.

CucumberJs skipping step definition - maybe callback last parameter in step definition?

I just started working with cucumberJs, gulp and protractor for an angular app and noticed, luckily as all my steps were passing, that if you don't pass in and use that 'callback' parameter in the step definition, cucumberJs might NOT know when this step is completed and will skip other steps and mark them all as 'passed'
Below is an example from the cucumberJs doc: https://github.com/cucumber/cucumber-js
Example 1:
this.Given(/^I am on the Cucumber.js GitHub repository$/, function (callback) {
// Express the regexp above with the code you wish you had.
// `this` is set to a World instance.
// i.e. you may use this.browser to execute the step:
this.visit('https://github.com/cucumber/cucumber-js', callback);
//
The callback is passed to visit() so that when the job's finished, the
next step can
// be executed by Cucumber
.
});
Example 2:
this.When(/^I go to the README file$/, function (callback) {
// Express the regexp above with the code you wish you had.
Call callback() at the end
// of the step, or callback(null, 'pending') if the step is not yet implemented:
callback(null, 'pending');
});
Example 3:
this.Then(/^I should see "(.*)" as the page title$/, function (title, callback) {
// matching groups are passed as parameters to the step definition
var pageTitle = this.browser.text('title');
if (title === pageTitle) {
callback();
} else {
callback(new Error("Expected to be on page with title " + title));
}
});
};
I understand you have 2 choices here:
a. Either you return a promise and don't pass the call back OR
b. You pass in the callback parameter and call it whenever the step definition is complete so cucumberJs knows to return and go to next step or next scenario.
However, I tried both above and still running into a weird situation where the top two scenarios will work NORMALLY as you would expect, but the third and fourth scenario within that same feature file will be skipped and all passed.
Is there anything special to consider about features with more than 2 scenarios?
As long as I have <= 2 scenarios per feature files, everything works fine, but the moment I had a third scenario to that feature file, that third scenario is ignored and skipped.
Any ideas?
Without seeing your actual steps I can't say for sure but it sounds like an asynchronous issue or dare I say it, a syntax error in the scenario. Have you tried changing the order of the scenarios to see if that has an impact.

laravel angularjs update multiple rows

i have a sortable table and after successfully moving an item i want to update all the rows in the databasetable which are effected from sorting.
my problem is that i dont know what's the best way to update multiple rows in my database with eloquent and how to send the data correct with angularjs
in angularjs i did this
//creating the array which i want to send to the server
var update = [];
for (min; min <= max; min++){
...
var item = {"id": id, "position": position};
update.push(item);
...
}
//it doesn't work because its now a string ...
var promise = $http.put("/api/album/category/"+update);
//yeah i can read update in my controller in laraval, but i need the fakeid, because without
//i get an error back from laravel...
var promise = $http.put("/api/album/category/fakeid", update);
in laravel i have this, but is there an possibility to update the table with one call instead of looping
//my route
Route::resource('/api/album/category','CategoryController');
//controller
class CategoryController extends BaseController {
public function update()
{
$updates = Input::all();
for($i = 0; $i<count($updates); $i++){
Category::where('id','=', $updates[$i]["id"])
->update(array('position' => $updates[$i]["position"]));
}
}
}
and yes this works but i think there are better ways to solve the put request with the fakeid and the loop in my controller ;)
update
k routing is solved ;) i just added an extra route
//angularjs
var promise = $http.put("/api/album/category/positionUpdate", update);
//laravel
Route::put('/api/album/category/positionUpdate','CategoryController#positionUpdate');
Try post instead put.
var promise = $http.post("/api/album/category/fakeid", update);
PUT vs POST in REST
PUT implies putting a resource - completely replacing whatever is available at the given URL with a different thing. By definition, a PUT is idempotent. Do it as many times as you like, and the result is the same. x=5 is idempotent. You can PUT a resource whether it previously exists, or not (eg, to Create, or to Update)!
POST updates a resource, adds a subsidiary resource, or causes a change. A POST is not idempotent, in the way that x++ is not idempotent.
By this argument, PUT is for creating when you know the URL of the thing you will create. POST can be used to create when you know the URL of the "factory" or manager for the category of things you want to create.
so:
POST /expense-report
or:
PUT /expense-report/10929
I learned via using following
Laravel+Angular+Bootstrap https://github.com/silverbux/laravel-angular-admin
Laravel+Angular+Material https://github.com/jadjoubran/laravel5-angular-material-starter
Hope this help you understand how to utilize bootstrap & angular and speed up your develop by using starter. You will be able to understand how to pass API request to laravel and get callback response.

WMS GetFeatureInfo; multiple layers, different sources

I'm developing a web application using GeoExt, OpenLayers and having my own GeoServer to serve various maps. Still, I want to let the user add other WMS's if needed, to be able to play around with all desired layers.
Thus, my problem with the GetFeatureInfo request. Right now I have a toolbar button attached to geoext's map panel,
new GeoExt.Action({
iconCls: "feature",
map: map,
toggleGroup: "tools",
tooltip: "Feature",
control: featureControl
})
its control attribute being
var featureControl = new OpenLayers.Control.WMSGetFeatureInfo({
queryVisible: true,
drillDown: true,
infoFormat:"application/vnd.ogc.gml"
});
I've also defined an event listener to do what I really want once I receive the responses, but that is not relevant here. My problem is the following:
Considering the user clicks on a point where there are 2+ visible layers and at least one of them is from a different source, OpenLayers will have to do one AJAX request per different source and, from OpenLayers own documentation,
Triggered when a GetFeatureInfo response is received. The event
object has a text property with the body of the response (String), a
features property with an array of the parsed features, an xy property
with the position of the mouse click or hover event that triggered the
request, and a request property with the request itself. If drillDown
is set to true and multiple requests were issued to collect feature
info from all layers, text and request will only contain the response
body and request object of the last request.
so, yeah, it will obviously wont work like that right away. Having a look at the debugger I can clearly see that, giving two layers from different sources, it actually DOES the request, it's just that it doesn't wait for the first's response and jumps for the next one (obviously, being asynchronous). I've thought about doing the requests one-by-one, meaning doing the first one as stated above and once it's finished and the response saved, go for the next one. But I'm still getting used to the data structure GeoExt uses.
Is there any API (be it GeoExt or OpenLayers) option/method I'm missing? Any nice workarounds?
Thanks for reading :-)
PS: I'm sorry if I've not been clear enough, english is not my mother tongue. Let me know if something stated above was not clear enough :)
i Hope this help to someone else, I realized that: you're rigth this control make the request in asynchronous mode, but this is ok, no problem with that, the real problem is when the control handle the request and trigger the event "getfeatureinfo" so, i modified 2 methods for this control and it works!, so to do this i declare the control first, and then in the savage mode i modified the methods here is de code:
getInfo = new OpenLayers.Control.WMSGetFeatureInfo({ drillDown:true , queryVisible: true , maxFeatures:100 });
//then i declare a variable that help me to handle more than 1 request.....
getInfo.responses = [];
getInfo.handleResponse=function(xy, request) { var doc = request.responseXML;
if(!doc || !doc.documentElement) { doc = request.responseText; }
var features = this.format.read(doc);
if (this.drillDown === false) {
this.triggerGetFeatureInfo(request, xy, features);
} else {
this._requestCount++;
this._features = (this._features || []).concat(features);
if( this._numRequests > 1){
//if the num of RQ, (I mean more than 1 resource ), i put the Request in array, this is for maybe in a future i could be need other properties or methods from RQ, i dont know.
this.responses.push(request);}
else{
this.responses = request;}
if (this._requestCount === this._numRequests) {
//here i change the code....
//this.triggerGetFeatureInfo(request, xy, this._features.concat());
this.triggerGetFeatureInfo(this.responses, xy, this._features.concat());
delete this._features;
delete this._requestCount;
delete this._numRequests;
// I Adding this when the all info is done 4 reboot
this.responses=[];
}
}
}
getInfo.triggerGetFeatureInfo= function( request , xy , features) {
//finally i added this code for get all request.responseText's
if( isArray( request ) ){
text_rq = '';
for(i in request ){
text_rq += request[i].responseText;
}
}
else{
text_rq = request.responseText;
}
this.events.triggerEvent("getfeatureinfo", {
//text: request.responseText,
text : text_rq,
features: features,
request: request,
xy: xy
});
// Reset the cursor.
OpenLayers.Element.removeClass(this.map.viewPortDiv, "olCursorWait");}
Thanks, you bring me a way for discover my problem and here is the way i solved, i hope this can help to somebody else.
saheka's answer was almost perfect! Congratulations and thank you, I had the same problem, and with it I finally managed to solve it.
What I would change in your code:
isArray() does not work, change it like this: if(request instanceof Array) {...} at the first line of getInfo.triggerGetFeatureInfo()
to show the results in a popup this is the way:
My code:
getInfo.addPopup = function(map, text, xy) {
if(map.popups.length > 0) {
map.removePopup(map.popups[0]);
}
var popup = new OpenLayers.Popup.FramedCloud(
"anything",
map.getLonLatFromPixel(xy),
null,
text,
null,
true
);
map.addPopup(popup);
}
and in the getInfo.triggerGetFeatureInfo() function, after the last line, append:
this.addPopup(map, text_rq, xy);
A GetFeatureInfo request is send as a JavaScript Ajax call to the external server. So, the requests are likely blocked for security reasons. You'll have to send the requests to the external servers by a proxy on your own domain.
Then, configure this proxy in openlayers by setting OpenLayers.ProxyHost to the proper path. For example:
OpenLayers.ProxyHost = "/proxy_script";
See http://trac.osgeo.org/openlayers/wiki/FrequentlyAskedQuestions#ProxyHost for more background information.

Resources