REST API Endpoint for Retrieving Empty Object - angularjs

I have a REST API endpoint for creating an empty object. What is the "standard" url scheme for this GET method? I'm currently using a factory in an angularjs app to make the call to the server.
Right now I have the following scheme:
GET
Item/new/
My $resource:
ngServices.factory("TESTfactory", function ($resource) {
return $resource("testNewItem/new", {}, {
create: {method: 'GET'}
}
}
A successful call to the above resource:
$scope.newItem = TESTfactory.newItem.create();
Any other suggestions would be much appreciated.
I've looked at the following links, which did not specifically list a url scheme for getting empty objects:
REST API Overview
Quick Reference section in this doc

A GET method should never create something. GET is supposed to be nullipotent, which means that it should have no side-effects. Creating a resource is certainly a side effect.
So, the standard http call would be
POST
Items/create
or
POST
Items/new
or better yet just
POST
Items/

Related

GET call failing in AngularJS resource - Strange data result

I have a simple angular resource that I've defined as below:
CompanyService.factory('CompanyService',
function ($resource) {
return $resource('https://baseurl.com/api/values/');
}
);
I then have a controller that calls that resource passing in a success and fail function:
.controller('companyList', function($scope, CompanyService) {
$scope.companies = CompanyService.query(
function(data) {
console.log(data);
return data;
},
function(error){
console.log("Error:");
console.log(error);
}
);
The rest API is a .NET MVC Web API that is extremely basic. I've configured it to return JSON and it simply returns an array of two objects like below. I've also enabled CORS so my angular app, which is hosted in a different domain, can call the api.
[{ID:1, Name:"TEST1"}, {ID:2, Name:"TEST2"}]
I've tested the REST call using jquery and just straight call through browser. All was functional (including the cross site scripting when calling from my angular app just using a straight JavaScript HTTP call).
When I try to call the api from my controller however, it always ends up in the error function. The error object contains a data property that is always populated with the string "resource is required|resource is required|undefined"
When I check the network I see no call to the values end point. It's as if the call is failing before ever being made.
If I change out the url to point to some sample REST api like https://jsonplaceholder.typicode.com/users/ it works fine and I'm able to see the call to "users" in the network traffic, which makes me think there is something wrong with my C# REST endpoint, however all my tests to call the REST endpoint outside of angular work successfully.
Can anyone help? I can't find anyone reporting this issues before anywhere on the net.
should the code be the one below? i didn't test it, just guess.
myModule.factory('CompanyService',
function ($resource) {
return $resource('https://baseurl.com/api/values/');
}
)
.controller('companyList', function($scope, CompanyService) {
CompanyService.query(
function(data) {
$scope.companies = data;
console.log(data);
return data;
},
function(error){
console.log("Error:");
console.log(error);
}
);
I ended up rebuilding my angular app from scratch. My first app was from the angular-seed github and had a handful of libraries already added in for testing and other things. One of those things is was was leading to this error as once I started a new project completely from scratch and added in angular and my REST call things worked perfectly. I've already spent too much time working through this so not going to spend any more time identifying exactly what it is but in case anyone else runs into the problem I did want to answer this one and close the book on it.

Trouble accessing remote JSON in AngularJS

So, I have been working on this exercise and I'm down to one final problem.
The JSON is on a different server. If I use a plain old $http.get then it doesn't allow the cross-server request. When I switch and use $http.jsonp I get to the file but it claims an unexpected ":" right away. I've validated their JSON so I'm not sure what's going on.
This is the current implementation of the call:
app.factory('users', ['$http', function($http) {
return {
callExternalJson: function() {
return $http.jsonp('http://applicant.pointsource.us/api/testUser/577ebf34f62a2d8f3c05d9c0?callback=JSON_CALLBACK').then( function(response) {
return response;
});
}
}
}]);
How do I get that remote JSON file?
Something to note: that remote JSON changes every time you hit it.
I also tried a different way of using jsonp that I've used in the past to access other RESTful APIs and got the same result of it choking on their first colon.
The problem isn't your code, but instead the server.
Try replacing the URL with this Test URL that supports JSONP. http://ip.jsontest.com/?callback=JSON_CALLBACK

How to call App Engine Endpoints with the JavaScript library in promises mode

I have a web application which calls several App Engine Endpoints with the Google API JavaScript client library.
I am currently changing this application from callback mode to promises mode, as recommended by Google (https://developers.google.com/api-client-library/javascript/features/promises#using-promises) and I am encountering a problem. Note that the app works well with the callback mode.
My problem with the promises mode is to find what is the correct path argument to use when calling the request method:
JavaScrit code:
var params = {'webSafeKeyParent’: ‘neN4fm15xW52b2ljZXMtb19saW5lmlYLEglBY1NFwpRpdHkYgICAgQj97AoM’};
gapi.client.request({
'path': 'https://myappenginename.appspot.com/_ah/api/customerApi/v1/?????????',
'params': params
}).then(function(response) {
// Handle response
}, function(reason) {
// Handle error
});
Endpoint definition in "customerApi":
#ApiMethod(
name = "listByParent",
path = "customerByParent/{webSafeKeyParent}",
httpMethod = ApiMethod.HttpMethod.GET,
scopes = {Constants.EMAIL_SCOPE},
clientIds = {Constants.WEB_CLIENT_ID, com.google.api.server.spi.Constant.API_EXPLORER_CLIENT_ID},
audiences = {Constants.ANDROID_AUDIENCE})
public List<Customer> listByParent(final User user, #Named("webSafeKeyParent") final String webSafeKeyParent, #Nullable #Named("cursor") String cursor, #Nullable #Named("limit") Integer limit) throws UnauthorizedException {
For few of my endpoints it works by including in the path argument of the JavaScript request method, the values of "path" and "name" as declared in the #ApiMethod annotation.
i.e. for the above endpoint, the following path works:
https://myappenginename.appspot.com/_ah/api/customerApi/v1/customerByParent/listByParent
Strangely enough this does NOT work for some other endpoints of the same kind. I receive either a 404 HTTP error or a 503 one.
I've also tried with the paths displayed under "Request" when you query the endpoints with the APIs Explorer but without success....
Is there any detailed documentation on how to call App Engine Endpoints with promises, with the Google API JavaScript client library? I have not found any. Do you have some advice to share please?
Thanks in advance
Actually the request method DOES work ALL THE TIME with the "path" argument composed of the values of "path" and "name" as declared in the #ApiMethod annotation...
It was a mistake on my side if it didn't work for some endpoints. Don't know which mistake, however.
Note that I have noticed that it is very important to pass to the JavaScript request method the correct httpMethod of the App Engine Endpoints. By default the request methid assumes that it is a GET. In case your Endpoint has httpMethod= ApiMethod.HttpMethod.POST in the #ApiMethod annotation, you shall pass the argument 'method': 'POST', as detailed in the doc: https://developers.google.com/api-client-library/javascript/reference/referencedocs#gapiclientrequestargs

How to pass body payload to angular $resource DELETE call

I have standard angular $resource configured as such
angular.module('client.resources')
.factory('ProjectSubjectResource',['$resource',
function ($resource) {
release: {
method: 'DELETE',
isArray: false
}
});
}]);
and I am calling this method as
ProjectSubjectResource.release({projectId: projectId, subjectId: 0},{ subjectIds: subjectIdArray})
where subjectIdArray is array of objects:
[{subject1: 213123}, {subject2: 3131}]
However, body of request does not contain that array. I suspect that DELETE request is the problem, as renaming method call to e.g. PUT makes difference.
Can I allow body of DELETE request somehow?
Take a look at this answer.
The body of a request for a DELETE is ignored. You will have to use POST to do what you want, or describe the data you are sending with the URL.
UPDATE: DELETE requests can have a body since Angular 1.6.4; check denisazevedo's answer for additional info.
Starting on Angular 1.6.4, the hasBody action configuration was added.
You can now have:
deleteSomething: {
method: 'DELETE',
hasBody: true
}
hasBody - {boolean} - allows to specify if a request body should be
included or not. If not specified only POST, PUT and PATCH requests
will have a body.
Reference

Making calls from the Javascript client library with #Named and unnamed parameters makes no sense

I have a Cloud Endpoints method that looks like this:
//HTTP POST
#ApiMethod(name = "hylyts.insert")
public Hylyt insertHylyt(#Named("url") String url, Hylyt hylyt, User user)
throws OAuthRequestException{
log.info("Trying to save hylyt '"+hylyt+"' with id '"+hylyt.getId());
if (user== null) throw new OAuthRequestException("Your token is no good here.");
hylyt.setArticle(getArticleKey(url, user));
ofy().save().entity(hylyt);
return hylyt;
}
I call it from the Javascript Client Library using this:
gapi.client.hylytit.hylyts.insert({PARAMS}).execute(callback);
Now, if I structure {PARAMS} as suggested in the docs (second example),
{
'url': url,
'resource': {
'hylyt': {
'contentType': 'application/json',
'data': hylyt
}
}
}
I get a null object in the endpoint (not to mention that the whole point of this library is to make these calls simple, which this structure clearly violates).
When I structure {PARAMS} as these answers suggest,
{
'url': url,
'resource': hylyt
}
I get a null object in the endpoint again. The correct syntax is this:
{
'url': url,
'id': hylyt.id
'text': hylyt.text
}
Which just blows my mind. Am I doing this all wrong? Is this a bug? Is it only happening because gapi is also passing the auth token in the background?
Yes, I could use the request syntax instead, but, again, why even use the library if it's just as complex as making the XHRs in pure javascript? I wouldn't mind the complexity if Google explained in the docs why things are happening. But the docs, paraphrased, just say use these methods and the auth, CORS, and XHR magic will happen behind closed doors.
Is the API method correctly recognized as POST method?
The resource parameter which is sent as POST body won't work correctly in a GET request.
The way it looks you are actually sending a GET request with the Hylyt properties in the query string.
To make sure you can change the method annotation to this:
#ApiMethod(name = "hylyts.insert", httpMethod = HttpMethod.POST)
Yup, agreed it's a bug. caused me great pains as well.
So i guess the work around is to create a combined object to pass to your api all named and un named parameters. Rather than hardcode each.. a quick loop might be better.
var param = {};
param["url"] = url;
for (var prop in hylyt) {
param[prop] = hylyt[prop];
}
gapi.client.hylytit.hylyts.insert(param).execute(callback);
That mashing together of parameters / objects can become a slick function if you really want.. but it's a band aid for what I'd consider a defect.
I see in the related question (cloud endpoints resource attribute for transmitting named params & body not working), you actually logged a defect.. Good stuff. Though there still appears no movement on this one. fingers crossed for someday!
The bug has been resolved. The correct syntax is
gapi.client.hylytit.hylyts.insert({url: url}, hylyt).execute(callback);

Resources