MEAN stack delete action is not done correctly. ERR_EMPTY_RESPONSE - mean

Whilst doing a MEAN tutorial, I've got this fine code deleting articles from mongo (via mongoose)
$scope.removeArticle = function(id){
$http.delete('/articles/' + id)
.success(function(data){
console.log(data);
});
$location.path('/articles');
}
The console.log prints me a nice 200,
but $location.path never happens, because something goes wrong on the server side. (errors are at the bottom)
Here is the routes/articles.js file that successfully catches the $http request
router.delete('/:id', function(req,res,next){
var id = req.params.id;
Article.removeArticle(id, function(err, article){
if (err) console.log(err);
res.location('/articles');
res.redirect('/articles');
});
});
and here is the models/article.js that successfully deletes the article from the db
module.exports.removeArticle = function(id, callback){
Article.findById(id, function(err, article){
if(!article) return next(new Error('Could not load article'));
article.remove(callback);
});
};
My server log says this
DELETE /articles 200 120010ms
DELETE /articles 200 120008ms
DELETE /articles 200 120006ms
and my Chrome console says this
DELETE http://localhost:3000/articles net::ERR_EMPTY_RESPONSE
and the tutorial concludes in this state. Anyone see what I missed?

The issue here, as far as I can tell from the code you posted, is the route is not actually handling the success. You should return a JSON object along with the status code to the client and not a redirect call.
The redirection on successful deletion should be handled on the client side but you need to place the call in the .success function because in some cases the location handler might be called before the .success has had a chance to finish.

Related

Zapier - Invalid API Response

I'm integrating a CRM with Facebook lead Ads using Zapier, and I can create a lead in Facebook and create it in the CRM without any issues.
After a successful post (i.e. successfully creating the lead), I'm curious what I should be returning, I would have thought
return Ok();
would have been enough. Instead, I get an error message saying:
- Got a non-object result, expected an object from create ()
What happened (You are seeing this because you are an admin):
Executing creates.ZapLead.operation.perform with bundle
Invalid API Response:
- Got a non-object result, expected an object from create ()
What should I be returning?
Code which makes the post is:
perform: (z, bundle) => {
const promise = z.request({
url: 'https://{{bundle.authData.subdomain}}.ngrok.io/api/zapier/create/lead/' + bundle.inputData.lead_type + '/' + bundle.inputData.core_customerTypeId,
method: 'POST',
body: JSON.stringify({
fields: bundle.inputData
}),
headers: {
'content-type': 'application/json'
}
});
// return promise.then((response) => JSON.parse(response.content));
return promise.then((response) => {
if (response.status != 200) {
throw new Error(`Unexpected status code ${response.status}`);
}
});
Any ideas?
Thanks,
David here, from the Zapier Platform team.
While your answer is technically correct, I wanted to add some context about the error and why your solution works.
Zapier expects a javascript object (basically anything valid and wrapped in {}) to come out of a create function. That's why JSON.parse(response.content) works, it's returning whatever the server said. Your code throws an error if it's not a 200, but doesn't return anything if it is a 200. Since undefined is not of type Object, the error you're seeing is thrown.
While {"Success":"Success","Attempt":null,"Id":null,"RequestId":null} is totally a valid response (it's an object!), it's more useful for the end-user to return data about the new lead that was created. That way, it can be used downstream for other actions.
​Let me know if you've got any other questions!
As a side note, we're very open to how to make that error message more clear; it's one devs struggle with a lot.
I think I found it. Looks like I need to return this if successful:
{"Success":"Success","Attempt":null,"Id":null,"RequestId":null}

Planner/Task endpoint not certain when PATCH data gets updated

I was trying to use the planner endpoint on version 1 of the graph. The main goal for me is to update the status of a task and decide whether it is ‘completed’ or ‘to do’. The first thing I do is to get all tasks from myself. See the endpoint below:
https://graph.microsoft.com/v1.0/me/planner/tasks
function plannerCompleteTask(id, etag) {
var specialEtag = etag.replace(/\\/g, "");
var deferred = $q.defer();
var endpoint = config.baseGraphApiUrl + 'planner/tasks/' + id;
var data = {
"percentComplete": "100"
};
var configRest = {
headers: {
"content-type": "application/json",
"If-Match": specialEtag
}
}
//"completedDateTime": "2018-02-15T07:56:25.7951905Z",
$http.patch(endpoint, data, configRest).then(function (result) {
console.log('log code', result);
deferred.resolve(result.status);
});
return deferred.promise;
}
I will create the following request
This will return a status: 204 with no content.
If I rerun the query with a "percentageCompleted: 0" in the body I get the following error.
Also If I try to log the request I get back from the AJAX call it doesn't give me back anything. As if there is no error handling being send back. I would need this because I have to reload the data in my application; but right now my code runs before the changes on the graph get completed, yet it returns a 204 status.
So I am clueless to find out when the call doesn't work or to find out when it is finished. Did anyone faced this issue before?
Thanks for reading and any help would be much appreciated. Cheers!
I think what you are looking for is the "prefer" header. If in your patch request you provide the "prefer" header with value "return=representation", the result of the patch will be final task data, including the new etag, with 200 status code, instead of default behavior of returning 204 "no content" status code.
Write operations in Planer are asynchronous. So, when possible, you should always update your local data based on the results of write operations with the prefer header, instead of reading them again.
In your requests, since you are reading the data before the task update is complete, essentially you are updating the same state of the task to be completed and not completed at the same time, which is the reason for the conflict.

difference between fetching page and file in serviceworker

event.respondWith(caches.match(event.request).then(function (response) {
if (response) {
return response;
}
//return fetch(event.reuqest, { credentials: 'include' });
//event.respondWith(fetch(event.request, { credentials: 'include' }));
}));
This is a common code for handling request via serviceworkers , if the url is in cache then return cache response or fetch it from server .
But my doubt is regarding the 2 commented lines , we need to use one of them for fetching the response .
My doubt is, when i use event.respondWith(fetch(event.request, { credentials: 'include' for fetching a page , i get the following error
DOMException: Failed to execute 'respondWith' on 'FetchEvent': The fetch event has already been responded to.
But the page is finally rendered , definitely browser is finally fetching the response , but when i use sam for fetching an image , i get the same error and on top of that the image is not fetched .
if i use the second option that return fetch(event.reuqest, { credentials: 'include' }); , then it works fine for both image as well as page.
I am not able to figure out what is the reason of that error , and also why it is behaving differently for file and page .
My another doubt is , do i actually need the credential parameter here ,i added it because most of the implementations i saw in web have used it,but what i have observed is that the request object already has a credential property with it , now it is not always
include
sometime it is
same-origin
too.
So could it happen that i am actually overriding the actual credential value by adding it .If that is not the case , then there is no difference in including it or not.It does not matter .
But if it is other way around , then we should not overwrite the credential value, which can have bad side effects.
You already have a call to event.respondWith, you don't need to call it twice.
Your first call is going to use the promise returned by:
caches.match(event.request).then(function(response) {
if (response) {
return response;
}
return fetch(event.reuqest, { credentials: 'include' });
})
This promise resolves to:
response, if the request is in the cache;
the promise returned by the call to fetch, otherwise.
The promise returned by fetch will resolve to a response, which is then going to be used by respondWith.

Service Worker and transparent cache updates

I am trying to install a ServiceWorker for a simple, yet old, Django web app. I started working with the example read-through caching example from the Chrome team
This works well but isn't ideal because I want to update the cache, if needed. There are two recommended ways to do this based on reading all the other service-worker answers here.
Use some server-side logic to know when the stuff you show has updated and then update your service worker to change what is precached. This is what sw-precache does, for example.
Just update the cache version in the service worker JS file (see comments in the JS file on the caching example above) whenever resources you depend on update.
Neither are great solutions for me. First, this is a dumb, legacy app. I don't have the application stack that sw-precache relies on. Second, someone else updates the data that will be shown (it is basically a list of things with a details page).
I wanted to try out the "use cache, but update the cache from network" that Jake Archibald suggested in his offline cookbook but I can't quite get it to work.
My original thinking was I should just be able to return the cached version in my service worker, but queue a function that would update the cache if the network is available. For example, something like this in the fetch event listener
// If there is an entry in cache, return it after queueing an update
console.log(' Found response in cache:', response);
setTimeout(function(request, cache){
fetch(request).then(function(response){
if (response.status < 400 && response.type == 'basic') {
console.log("putting a new response into cache");
cache.put(request, response);
}
})
},10, request.clone(), cache);
return response;
But this doesn't work. The page gets stuck loading.
whats wrong with the code above? Whats the right way to get to my target design?
It sounds like https://jakearchibald.com/2014/offline-cookbook/#stale-while-revalidate is very close to what you're looking for
self.addEventListener('fetch', function(event) {
event.respondWith(
caches.open('mysite-dynamic').then(function(cache) {
return cache.match(event.request).then(function(response) {
var fetchPromise = fetch(event.request).then(function(networkResponse) {
// if we got a response from the cache, update the cache
if (response) {
cache.put(event.request, networkResponse.clone());
}
return networkResponse;
});
// respond from the cache, or the network
return response || fetchPromise;
});
})
);
});
On page reload you can refresh your service worker with new version meanwhile old one will take care of request.
Once everything is done and no page is using old service worker, It will using newer version of service worker.
this.addEventListener('fetch', function(event){
event.responseWith(
caches.match(event.request).then(function(response){
return response || fetch(event.request).then(function(resp){
return caches.open('v1').then(function(cache){
cache.put(event.request, resp.clone());
return resp;
})
}).catch(function() {
return caches.match('/sw/images/myLittleVader.jpg');
});
})
)
});
I recommend you to walk through below link for detailed functionality
https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers

server returning 302 moved on create in Rails

I've got a Backbone.js/Rails app and I'm trying to create a new object through Backbone model.save().
The server is returning a 302 moved, but checking the rails controller, the create object exists, and I can navigate to the index, so the routes are properly in place.
I've tried replacing the backbone.js with a regular jquery .ajax function, and both return the 302, as I originally thought the error was in backbone, but I think this is showing that the error is actually in rails.
The request payload/parameters is pretty simple
{"user_id":130,"message_text":"does this go 302","authenticity_token":"GxN8nPf5YwS2j2HhWZxWiKej3Y72Vb5IQZ98u5Nl2gs="}
The backbone save method is
var user_message = new Myapp.Models.UserMessage({
user_id: user.id,
message_text: $('input[name="message"]',this.el).val()
});
user_message.save({
success: function(response) {
new Message({message: response.message});
},
error: function() {
new Error({ message: "adding message" });
}
});
A "302" response has nothing to do with backbone, as you've noted. It looks like you have authorization / authentication code that is causing this.

Resources