Add HTTP Header in JavaScript to requests for images - javascript

I have a JS/HTML5 Project based on angularjs where I protect the api with an authorization token set in the http header. Now I also want to protect the access to images from the server.
I know how to do it on the server side, but how can I add HTTP Headers to image requests in angular or javascript? For api request we have already added it to the services ($ressource) and it works.

In Angular 1.2.X
There are more than a few ways to do this. In Angular 1.2, I recommend using an http interceptor to "scrub" outgoing requests and add headers.
// An interceptor is just a service.
app.factory('myInterceptor', function($q) {
return {
// intercept the requests on the way out.
request: function(config) {
var myDomain = "http://whatever.com";
// (optional) if the request is heading to your target domain,
// THEN add your header, otherwise leave it alone.
if(config.url.indexOf(myDomain) !== -1) {
// add the Authorization header (or custom header) here
config.headers.Authorization = "Token 12309123019238";
}
return config;
}
}
});
app.config(function($httpProvider) {
// wire up the interceptor by name in configuration
$httpProvider.interceptors.push('myInterceptor');
});
In Angular 1.0.X
If you're using Angular 1.0.X, you'll need to set the headers more globally in the common headers... $http.defaults.headers.common.Authentication
EDIT: For things coming from
For this you'll need to create a directive, and it's probably going to get weird.
You'll need to:
Create a directive that is either on your <img/> tag, or creates it.
Have that directive use $http service to request the image (thus leveraging the above http interceptor). For this you're going to have to examine the extension and set the proper content-type header, something like: $http({ url: 'images/foo.jpg', headers: { 'content-type': 'image/jpeg' }).then(...)
When you get the response, you'll have to take the raw base64 data and set the src attribute of your image element to a data src like so: <img src="data:image/jpeg;base64,9hsjadf9ha9s8dfh...asdfasfd"/>.
... so that'll get crazy.
If you can make it so your server doesn't secure the images you're better off.

As said here you can use angular-img-http-src (bower install --save angular-img-http-src if you use Bower).
If you look at the code, it uses URL.createObjectURL and URL.revokeObjectURL which are still draft on 19 April 2016. So look if your browser supports it.
In order to use it, declare 'angular.img' as a dependency to your app module (angular.module('myapp', [..., 'angular.img'])), and then in your HTML you can use http-src attribute for <img> tag.
For example: <img http-src="{{myDynamicImageUrl}}">
Of course, this implies that you have declared an interceptor using $httpProvider.interceptors.push to add your custom header or that you've set statically your header for every requests using $http.defaults.headers.common.MyHeader = 'some value';

we have the same issue and solve it using a custom ng-src directive ..
basically a secure-src directive which does exactly what ng-src does (its a copy basically) BUT it extends the url with a query parameter which includes the local authentication header.
The server code returning the resources are updated to not only check the header but also the query parameters. of course the token added to the query parameter might be authenticated slightly differently.. e.g. there might be a time window after after a normal rest request in which such a request is allowed etc .. since the url will remain in the browser history.

From oficial documentation at: http://docs.angularjs.org/api/ngResource/service/$resource
Usage
$resource(url, [paramDefaults], [actions]);
[...]
actions: Hash with declaration of custom action that should extend the
default set of resource actions. The declaration should be created in
the format of $http.config:
{action1: {method:?, params:?, isArray:?, headers:?, ...},
action2: {method:?, params:?, isArray:?, headers:?, ...}, ...}
More about $http service:
http://docs.angularjs.org/api/ng/service/$http#usage_parameters

As pointed out Here FIrefox supports httpChannel.setRequestHeader :
// adds "X-Hello: World" header to the request
httpChannel.setRequestHeader("X-Hello", "World", false);
In the example code above we have a variable named httpChannel which
points to an object implementing nsIHttpChannel. (This variable could
have been named anything though.)
The setRequestHeader method takes 3 parameters. The first parameter is
the name of the HTTP request header. The second parameter is the value
of the HTTP request header. And for now, just ignore the third
parameter, and just always make it false.
However this seems to be only available on Firefox (link)
You can either use Cookies to pass the value and retrieve it as a cookie instead of a HttpHeader or use ajax to retrieve the image with a custom header.
More links :
link1
link2

Related

How to read http headers of last response? [duplicate]

How do I access a page's HTTP response headers via JavaScript?
Related to this question, which was modified to ask about accessing two specific HTTP headers.
Related:
How do I access the HTTP request header fields via JavaScript?
It's not possible to read the current headers. You could make another request to the same URL and read its headers, but there is no guarantee that the headers are exactly equal to the current.
Use the following JavaScript code to get all the HTTP headers by performing a get request:
var req = new XMLHttpRequest();
req.open('GET', document.location, false);
req.send(null);
var headers = req.getAllResponseHeaders().toLowerCase();
alert(headers);
Unfortunately, there isn't an API to give you the HTTP response headers for your initial page request. That was the original question posted here. It has been repeatedly asked, too, because some people would like to get the actual response headers of the original page request without issuing another one.
For AJAX Requests:
If an HTTP request is made over AJAX, it is possible to get the response headers with the getAllResponseHeaders() method. It's part of the XMLHttpRequest API. To see how this can be applied, check out the fetchSimilarHeaders() function below. Note that this is a work-around to the problem that won't be reliable for some applications.
myXMLHttpRequest.getAllResponseHeaders();
The API was specified in the following candidate recommendation for XMLHttpRequest: XMLHttpRequest - W3C Candidate Recommendation 3 August 2010
Specifically, the getAllResponseHeaders() method was specified in the following section: w3.org: XMLHttpRequest: the getallresponseheaders() method
The MDN documentation is good, too: developer.mozilla.org: XMLHttpRequest.
This will not give you information about the original page request's HTTP response headers, but it could be used to make educated guesses about what those headers were. More on that is described next.
Getting header values from the Initial Page Request:
This question was first asked several years ago, asking specifically about how to get at the original HTTP response headers for the current page (i.e. the same page inside of which the javascript was running). This is quite a different question than simply getting the response headers for any HTTP request. For the initial page request, the headers aren't readily available to javascript. Whether the header values you need will be reliably and sufficiently consistent if you request the same page again via AJAX will depend on your particular application.
The following are a few suggestions for getting around that problem.
1. Requests on Resources which are largely static
If the response is largely static and the headers are not expected to change much between requests, you could make an AJAX request for the same page you're currently on and assume that they're they are the same values which were part of the page's HTTP response. This could allow you to access the headers you need using the nice XMLHttpRequest API described above.
function fetchSimilarHeaders (callback) {
var request = new XMLHttpRequest();
request.onreadystatechange = function () {
if (request.readyState === XMLHttpRequest.DONE) {
//
// The following headers may often be similar
// to those of the original page request...
//
if (callback && typeof callback === 'function') {
callback(request.getAllResponseHeaders());
}
}
};
//
// Re-request the same page (document.location)
// We hope to get the same or similar response headers to those which
// came with the current page, but we have no guarantee.
// Since we are only after the headers, a HEAD request may be sufficient.
//
request.open('HEAD', document.location, true);
request.send(null);
}
This approach will be problematic if you truly have to rely on the values being consistent between requests, since you can't fully guarantee that they are the same. It's going to depend on your specific application and whether you know that the value you need is something that won't be changing from one request to the next.
2. Make Inferences
There are some BOM properties (Browser Object Model) which the browser determines by looking at the headers. Some of these properties reflect HTTP headers directly (e.g. navigator.userAgent is set to the value of the HTTP User-Agent header field). By sniffing around the available properties you might be able to find what you need, or some clues to indicate what the HTTP response contained.
3. Stash them
If you control the server side, you can access any header you like as you construct the full response. Values could be passed to the client with the page, stashed in some markup or perhaps in an inlined JSON structure. If you wanted to have every HTTP request header available to your javascript, you could iterate through them on the server and send them back as hidden values in the markup. It's probably not ideal to send header values this way, but you could certainly do it for the specific value you need. This solution is arguably inefficient, too, but it would do the job if you needed it.
Using XmlHttpRequest you can pull up the current page and then examine the http headers of the response.
Best case is to just do a HEAD request and then examine the headers.
For some examples of doing this have a look at http://www.jibbering.com/2002/4/httprequest.html
Just my 2 cents.
A solution with Service Workers
Service workers are able to access network information, which includes headers. The good part is that it works on any kind of request, not just XMLHttpRequest.
How it works:
Add a service worker on your website.
Watch every request that's being sent.
Make the service worker fetch the request with the respondWith function.
When the response arrives, read the headers.
Send the headers from the service worker to the page with the postMessage function.
Working example:
Service workers are a bit complicated to understand, so I've built a small library that does all this. It is available on github: https://github.com/gmetais/sw-get-headers.
Limitations:
the website needs to be on HTTPS
the browser needs to support the Service Workers API
the same-domain/cross-domain policies are in action, just like on XMLHttpRequest
Another way to send header information to JavaScript would be through cookies. The server can extract whatever data it needs from the request headers and send them back inside a Set-Cookie response header — and cookies can be read in JavaScript. As keparo says, though, it's best to do this for just one or two headers, rather than for all of them.
(2021) An answer without additional HTTP call
While it's not possible in general to read arbitrary HTTP response headers of the top-level HTML navigation, if you control the server (or middleboxes on the way) and want to expose some info to JavaScript that can't be exposed easily in any other way than via a header:
You may use Server-Timing header to expose arbitrary key-value data, and it will be readable by JavaScript.
(*in supported browsers: Firefox 61, Chrome 65, Edge 79; no Safari yet and no immediate plans for shipping as of 2021.09; no IE)
Example:
server-timing: key;desc="value"
You can use this header multiple times for multiple pieces of data:
server-timing: key1;desc="value1"
server-timing: key2;desc="value2"
or use its compact version where you expose multiple pieces of data in one header, comma-separated.
server-timing: key1;desc="value1", key2;desc="value2"
Example of how Wikipedia uses this header to expose info about cache hit/miss:
Code example (need to account for lack of browser support in Safari and IE):
if (window.performance && performance.getEntriesByType) { // avoid error in Safari 10, IE9- and other old browsers
let navTiming = performance.getEntriesByType('navigation')
if (navTiming.length > 0) { // still not supported as of Safari 14...
let serverTiming = navTiming[0].serverTiming
if (serverTiming && serverTiming.length > 0) {
for (let i=0; i<serverTiming.length; i++) {
console.log(`${serverTiming[i].name} = ${serverTiming[i].description}`)
}
}
}
}
This logs cache = hit-front in supported browsers.
Notes:
as mentioned on MDN, the API is only supported over HTTPS
if your JS is served from another domain, you have to add Timing-Allow-Origin response header to make the data readable to JS (Timing-Allow-Origin: * or Timing-Allow-Origin: https://www.example.com)
Server-Timing headers support also dur(header) field, readable as duration on JS side, but it's optional and defaults to 0 in JS if not passed
regarding Safari support: see bug 1 and bug 2 and bug 3
You can read more on server-timing in this blog post
Note that performance entries buffers might get cleaned by JS on the page (via an API call), or by the browser, if the page issues too many calls for subresources. For that reason, you should capture the data as soon as possible, and/or use PerformanceObserver API instead. See the blog post for details.
For those looking for a way to parse all HTTP headers into an object that can be accessed as a dictionary headers["content-type"], I've created a function parseHttpHeaders:
function parseHttpHeaders(httpHeaders) {
return httpHeaders.split("\n")
.map(x=>x.split(/: */,2))
.filter(x=>x[0])
.reduce((ac, x)=>{ac[x[0]] = x[1];return ac;}, {});
}
var req = new XMLHttpRequest();
req.open('GET', document.location, false);
req.send(null);
var headers = parseHttpHeaders(req.getAllResponseHeaders());
// Now we can do: headers["content-type"]
You can't access the http headers, but some of the information provided in them is available in the DOM. For example, if you want to see the http referer (sic), use document.referrer. There may be others like this for other http headers. Try googling the specific thing you want, like "http referer javascript".
I know this should be obvious, but I kept searching for stuff like "http headers javascript" when all I really wanted was the referer, and didn't get any useful results. I don't know how I didn't realize I could make a more specific query.
Like many people I've been digging the net with no real answer :(
I've nevertheless find out a bypass that could help others. In my case I fully control my web server. In fact it is part of my application (see end reference). It is easy for me to add a script to my http response. I modified my httpd server to inject a small script within every html pages. I only push a extra 'js script' line right after my header construction, that set an existing variable from my document within my browser [I choose location], but any other option is possible. While my server is written in nodejs, I've no doubt that the same technique can be use from PHP or others.
case ".html":
response.setHeader("Content-Type", "text/html");
response.write ("<script>location['GPSD_HTTP_AJAX']=true</script>")
// process the real contend of my page
Now every html pages loaded from my server, have this script executed by the browser at reception. I can then easily check from JavaScript if the variable exist or not. In my usecase I need to know if I should use JSON or JSON-P profile to avoid CORS issue, but the same technique can be used for other purposes [ie: choose in between development/production server, get from server a REST/API key, etc ....]
On the browser you just need to check variable directly from JavaScript as in my example, where I use it to select my Json/JQuery profile
// Select direct Ajax/Json profile if using GpsdTracking/HttpAjax server otherwise use JsonP
var corsbypass = true;
if (location['GPSD_HTTP_AJAX']) corsbypass = false;
if (corsbypass) { // Json & html served from two different web servers
var gpsdApi = "http://localhost:4080/geojson.rest?jsoncallback=?";
} else { // Json & html served from same web server [no ?jsoncallback=]
var gpsdApi = "geojson.rest?";
}
var gpsdRqt =
{key :123456789 // user authentication key
,cmd :'list' // rest command
,group :'all' // group to retreive
,round : true // ask server to round numbers
};
$.getJSON(gpsdApi,gpsdRqt, DevListCB);
For who ever would like to check my code:
https://www.npmjs.org/package/gpsdtracking
Allain Lalonde's link made my day.
Just adding some simple working html code here.
Works with any reasonable browser since ages plus IE9+ and Presto-Opera 12.
<!DOCTYPE html>
<title>(XHR) Show all response headers</title>
<h1>All Response Headers with XHR</h1>
<script>
var X= new XMLHttpRequest();
X.open("HEAD", location);
X.send();
X.onload= function() {
document.body.appendChild(document.createElement("pre")).textContent= X.getAllResponseHeaders();
}
</script>
Note: You get headers of a second request, the result may differ from the initial request.
Another way is the more modern fetch() API
https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch
Per caniuse.com it's supported by Firefox 40, Chrome 42, Edge 14, Safari 11
Working example code:
<!DOCTYPE html>
<title>fetch() all Response Headers</title>
<h1>All Response Headers with fetch()</h1>
<script>
var x= "";
if(window.fetch)
fetch(location, {method:'HEAD'})
.then(function(r) {
r.headers.forEach(
function(Value, Header) { x= x + Header + "\n" + Value + "\n\n"; }
);
})
.then(function() {
document.body.appendChild(document.createElement("pre")).textContent= x;
});
else
document.write("This does not work in your browser - no support for fetch API");
</script>
If we're talking about Request headers, you can create your own headers when doing XmlHttpRequests.
var request = new XMLHttpRequest();
request.setRequestHeader("X-Requested-With", "XMLHttpRequest");
request.open("GET", path, true);
request.send(null);
To get the headers as an object which is handier (improvement of Raja's answer):
var req = new XMLHttpRequest();
req.open('GET', document.location, false);
req.send(null);
var headers = req.getAllResponseHeaders().toLowerCase();
headers = headers.split(/\n|\r|\r\n/g).reduce(function(a, b) {
if (b.length) {
var [ key, value ] = b.split(': ');
a[key] = value;
}
return a;
}, {});
I've just tested, and this works for me using Chrome Version 28.0.1500.95.
I was needing to download a file and read the file name. The file name is in the header so I did the following:
var xhr = new XMLHttpRequest();
xhr.open('POST', url, true);
xhr.responseType = "blob";
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
success(xhr.response); // the function to proccess the response
console.log("++++++ reading headers ++++++++");
var headers = xhr.getAllResponseHeaders();
console.log(headers);
console.log("++++++ reading headers end ++++++++");
}
};
Output:
Date: Fri, 16 Aug 2013 16:21:33 GMT
Content-Disposition: attachment;filename=testFileName.doc
Content-Length: 20
Server: Apache-Coyote/1.1
Content-Type: application/octet-stream
This is my script to get all the response headers:
var url = "< URL >";
var req = new XMLHttpRequest();
req.open('HEAD', url, false);
req.send(null);
var headers = req.getAllResponseHeaders();
//Show alert with response headers.
alert(headers);
Having as a result the response headers.
This is a comparison test using Hurl.it:
Using mootools, you can use this.xhr.getAllResponseHeaders()
This is an old question. Not sure when support became more broad, but getAllResponseHeaders() and getResponseHeader() appear to now be fairly standard: http://www.w3schools.com/xml/dom_http.asp
As has already been mentioned, if you control the server side then it should be possible to send the initial request headers back to the client in the initial response.
In Express, for example, the following works:
app.get('/somepage', (req, res) => {
res.render('somepage.hbs', {headers: req.headers});
})
The headers are then available within the template, so could be hidden visually but included in the markup and read by clientside javascript.
I think the question went in the wrong way,
If you want to take the Request header from JQuery/JavaScript the answer is simply No. The other solutions is create a aspx page or jsp page then we can easily access the request header.
Take all the request in aspx page and put into a session/cookies then you can access the cookies in JavaScript page..

How to send a parameter on the all of request in Restangular

I want to send a parameter as lang for all request that use rectangular. Is there any way so I that add this parameter in app.config section?
Thanks
Set the value in the interceptor, e.g:
Restangular.setDefaultRequestParams({lang: "en"});
Link: setdefaultrequestparams
You can add a request interceptor in config section and then pass an extra param to every request, like Auth token etc.
https://github.com/mgonto/restangular#addrequestinterceptor
Another simpler way is to add default params as described here by resangular api.
https://github.com/mgonto/restangular#setdefaultrequestparams

AngularJS include API key in a get request

I am trying to get information from a fantasy data API using AngularJS. I am using $resource to perform my get request in my controller, but I haven't been able to figure out how to correctly include the API key. Do I need to include it as a header? Thanks.
nflApp.controller('mainController', ['$scope','$resource','$routeParams', function($scope, $resource, $routeParams) {
$scope.fantasyAPI = $resource("https://api.fantasydata.net/nfl/v2/JSON/DailyFantasyPlayers/2015-DEC-28", { callback: "JSON_CALLBACK" }, { get: { method: "JSONP"}});
console.log($scope.fantasyAPI);
}]);
Below is the http request info from the site.
You should set a header with the API key, AngularJS will send them with every request in the following case:
$http.defaults.headers.common["Ocp-Apim-Subscription-Key"] = key;
When adding '.common' you are telling angular to send this in every request so you do not need to add it to every resource that hits the API.
A easy way to do that is by creating your own interceptors from $httpProvider at "config" fase.
To do that, just write something like:
mymodule.config(['$httpProvider', function($httpProvider){
$httpProvider.interceptors.push(function ($q) {
return {
'request': function (config) {
config.headers['Ocp-Apim-Subscription-Key'] = SomeUserClass.AuthToken();
return config;
},
'response': function (response) {
return response;
}
};
});
});
You need to modify request header in JSONP. Unfortunately it is not possible. As the browser is responsible for header creation and you just can't manipulate that when using JSONP method.
how to change the headers for angularjs $http.jsonp
Set Headers with jQuery.ajax and JSONP?
From that link - https://johnnywey.wordpress.com/2012/05/20/jsonp-how-does-it-work/
Why NOT To Use JSONP?
Deciding against using JSONP is directly related to how it works. First of all, the only HTTP method you can use is GET since that is the only method script tags support. This immediately eliminates the use of JSONP as an option to interact with nice RESTful APIs that use other HTTP verbs to do fun stuff like CRUD. And while we’re on the subject of GET, note that using anything other than URL parameters to communicate with the server API (e.g. sending some JSON over) is also not possible. (You could encode JSON as a URL parameter, but shame on you for even thinking that.)
If they only work with header manipulation you will need to do that call from your server side.

How can I query the iTunes search API in javascript?

I am trying to query the App Store for information on a given app, however I keep getting the following error.
XMLHttpRequest cannot load https://itunes.apple.com/lookup?id=<some-app-id>.
No 'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'http://www.<some-website>.co.uk' is therefore not allowed access. The response had HTTP status code 501.
The code I'm using to execute the request is as follows.
Does anyone know where I may be going wrong?
var config = {
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET',
'Access-Control-Allow-Headers': 'Content-Type, X-Requested-With',
}
};
$http.get("https://itunes.apple.com/lookup?id=<some-app-id>", config).success(
function(data) {
// I got some data back!
}
);
You can use $http.jsonp,
$http.jsonp("https://itunes.apple.com/lookup", {
params: {
'callback': 'functionName',
'id': 'some-app-id'
}
});
Where functionName is the name of your globally defined function in string form. You can redefine it in your module so that it has access to $scope.
Documentation
Edit: here's a plunker showing my successful approach roughly getting it into an AngularJS app:
http://plnkr.co/edit/QhRjw8dzK6Ob4mCu6T6Z?p=preview
Adding those headers to your server won't change what is happening. The cross origin headers need to be added by the iTunes API.
That is not going to happen, so what you need to do instead is to use JSONP style callbacks in your webpage. There is an example on the iTunes search API page.
http://www.apple.com/itunes/affiliates/resources/documentation/itunes-store-web-service-search-api.html
Note: When creating search fields and scripts for your website, you
should use dynamic script tags for your xmlhttp script call requests.
For example:
<script src="https://.../search?parameterkeyvalue&callback="{name of JavaScript function in webpage}"/>
Note the 'callback' parameter there. That is a function defined globally in your javascript on the page that will get called with the response from the request to the url in 'src'. That function puts the data into your page, or application. You'll have to figure out how.
It's a shame that the language used in this documentation is not clearer, because you must do some kind of JSONP style workaround since they don't have CORS enabled on their API.
If you need to dynamically add a script tag (fetching data once is not enough) you can try this tutorial:
Dynamically add script tag with src that may include document.write
The API in general is probably intended for use by backends (not affected by cross origin issues), not for client side fetching.
Using angular 2:
constructor(private _jsonp: Jsonp) {}
public getData(term: string): Observable<any> {
return this._jsonp.request(itunesSearchUrl)
.map(res => {
console.log(res);
});
}

AngularJS $resource calls the wrong API URL when using method:POST

Not the easiest issue to put into a title.
Anyhow, my app is built on nodejs/expressjsand has an API set up for the url:
EDIT: The current code I'm using is:
$scope.updateProduct = $resource('/api/updateProduct/:product/:param/:value',{},{
query: {method:'GET'},
post: {method:'POST'},
save: {method:'PUT', params: {brand: '#brand', param:'#param', value:'#value'}},
remove: {method:'DELETE'}
});
$scope.updateProduct.save({
product : $scope.post._id,
param: 'likes',
value: $scope.user._id
});
At present it calls /api/updateProduct instead of /api/updateProduct/<product>/<param>/<value> like it's supposed to / like it does when I perform $scope.updateProduct.get().
In my console I see (as an example):
PUT /api/updateBrand/Quay%20Eyewear%20Australia/userTags/sunglasses,%20classic 200 30ms - 2.31kb
However, the API isn't actually accessed/nothing happens. Interestingly, if I go to localhost:5000/api/updateBrand/Quay%20Eyewear%20Australia/userTags/sunglasses,%20classic in my browser, it posts the correct data and updates the product in my database, so it's definitely an error with the way the $resource is being called.
As you can see in ngResource docs, $resource receive 3 parameters:
$resource(url[, paramDefaults][, actions]);
You are passing your action as a parameter.
The correct version would be:
$scope.updateProduct = $resource('/api/updateProduct/:product/:param/:value',{}, {'save':{method:'POST'}});
Note that it isn't even necessary, because when you use $resource you already create the default methods:
{
'get': {method:'GET'},
'save': {method:'POST'},
'query': {method:'GET', isArray:true},
'remove': {method:'DELETE'},
'delete': {method:'DELETE'}
};
First of all, your have defined the save() to have a parameter called "brand", but in your url template and in the call to save(), you are using "product". I guess it's a typo.
You say when you are using browser to visit the url, it works well; but when angular is make a PUT request to the same url, nothing is happening. This indicates that your backend is configure to process only GET requests for this particular url pattern. Therefore, you need to make sure that your backend is accepting PUT requests.
I was struggling with this issue and was able to pass parameters to the resource by doing the equivalent call below (notice the '$' before 'save').
$scope.updateProduct.$save({
product : $scope.post._id,
param: 'likes',
value: $scope.user._id
});
I also did not define a 'save' method in the resource. According to Angular docs:
"Calling these methods (meaning non-GET methods) invoke $http on the url template with the given method, params and headers. When the data is returned from the server then the object is an instance of the resource type and all of the non-GET methods are available with $ prefix. This allows you to easily support CRUD operations (create, read, update, delete) on server-side data."

Categories