How to pass parameter using Ext.Ajax.request when method type is DELETE - rest

I am trying to send use Ext.Ajax.request method to delete some data on server. My request method looks as below :
Ext.Ajax.request({
url: '/myserver/restful/service/delete',
method: 'DELETE',
headers: {
'Content-Type': 'application/json'
},
params: {
userId: 12345
}
});
On my jersey server I have written which looks like as below :
#Path("/delete")
#DELETE
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public Response deleteUser(final String userId) {
System.out.println("user id = " + userId);
return Response.ok().entity("success").build();
}
This method prints out user id in following format :
user id = userId=12345
So my expected value for userId is 12345 but it is giving me userId=12345. As I am newbie to jersey thing, I am not able to decide what to do now.
Can anyone please tell what is going wrong?

Not sure about what's going wrong in Jersey, but... if you are trying to use DELETE with a request body you're on the wrong track anyway. Don't. The only relevant parameter for DELETE should be the request URI it's being applied to.

#Julian is correct you really shouldn't have params with an HTTP DELETE verb.
Try this:
#Path("/delete/{userId}
Then inside of your method:
#PathParam("userId") String userId
And then when you call your service change your url to : delete/(userId) (without the parens) and remove the params.

Related

Calling API from Saleforce is giving error code 500

I have a REST API to callout from Salesforce.
The authorization of the API is through access token.
I am able to get the access token through POST request in Salesforce. Also tested from Postman through that token and able to get a successful response.
I am using the below code to callout the API using the access token:
String endpoint_x = '*****';//Putting my endpoint here
Http httpObject;
HttpResponse response;
String accessToken;
accessToken = MyUtilityClass.getAccessToken();
jsonBody = json.serializePretty('', true);//Yes, My JSON is empty
HttpRequest request = new HttpRequest();
request.setEndpoint(endpoint_x);
request.setHeader('Authorization', 'Bearer '+accessToken);
request.setMethod('POST');
request.setBody(jsonBody);
httpObject = new Http();
response = httpObject.send(request);
System.debug('Response=' + response);
Getting Response value as below:
System.HttpResponse[Status=Internal Server Error, StatusCode=500]
I have tried putting '{}' in the Jsonbody. Added 'Content-Type' in header but nothing worked.
Where should I lookout for this?
In the Postman, I was not putting anything in the body, and getting a successful response.
To get the same behaviour, I was using empty string in Apex, like this:
jsonBody = json.serializePretty('', true);
But the parser was not working correctly.
To solve this, I created a class without any field:
class ClassForEmptyBody{
}
And used object of that class in the serializer:
ClassForEmptyBody classForEmptyBodyObject = new ClassForEmptyBody();
jsonBody = json.serializePretty(classForEmptyBodyObject , true);
Why are you passing json body if nothing is in there. Just skip setbody code and try.

How to send a POST request with Content-Type "application/x-www-form-urlencoded"

I am trying to send a POST request from my TornadoFX application to my nodejs server.
That's how i send my request to the server:
val api: Rest by inject()
api.baseURI = "http://localhost:5000/"
api.post("api/register", userModel) {
it.addHeader("Content-Type", "application/x-www-form-urlencoded")
}
My UserModel looks like this:
class UserModel : JsonModel {
val nameProperty = SimpleStringProperty("")
var name by nameProperty
val emailProperty = SimpleStringProperty("")
var email by emailProperty
override fun toJSON(json: JsonBuilder) {
with(json) {
add("name", name)
add("email", email)
}
}
}
Printing the request body on my node server i get following:
[Object: null prototype] {
'{"name":"Test","email":"test#test.org"}': ''
}
When i send a request via Postman i get the following body:
[Object: null prototype] {
name: 'Test',
email: 'test#test.org'
}
And that's what i'm trying to produce with TornadoFX without success.
I am grateful for any help!
You are correctly setting the Content-Type header, but you're pushing a JsonModel as your data, and consequently the framework will convert it to a JSON structure by calling toJSON() on it. The application/x-www-form-urlencoded content type expects an URL encoded piece of data, so you need to convert your data into an url encoded string. I suggest adding a function to your domain model like this:
fun toURLEncoded() =
"name=${name.urlEncoded}&email=${email.urlEncoded}".byteInputStream(StandardCharsets.UTF_8)
This example uses an extension function called urlEncoded to avoid clutter. You can define that extension function like this for example:
fun Any.urlEncoded(): String = URLEncoder.encode(toString(), "UTF-8")
Now you just have to call api.post("api/register", userModel.toURLEncoded()) and you should be good to go.

PUT request returning a 400 Bad Request Error

I am doing a PUT request to RESTfull service which changes password of a user. For the time being I have just hardcoded values of new and old password in my AJAX test my service. However it is giving me a 400 error.
AJAX call
$.ajax({
type: "PUT",
url: "api/teachers/"+user,
data: {"old":"123","new":"qwe"},
contentType: "application/json",
success: function(data,status)
{
datax = data;
alert(data+status);
ko.applyBindings(new AddMarkSheetKo(data));
},
error: function(XMLHttpRequest, textStatus, errorThrown)
{
alert(XMLHttpRequest+textStatus+ errorThrown);
// error handler here
}
});
Restful function:
#PUT
#Path("/{name}")
#Consumes(MediaType.APPLICATION_JSON)
public Response changePwd(#PathParam ("name")String name,#QueryParam ("old") String old, #QueryParam("new") String nw){
System.out.println("entered function"+old+nw);
Teacher t = DataAccessUtil.getByName(Teacher.class, name);
if(t.getPassword().equals(old)){
t.setPassword(nw);
DataAccessUtil.update(t);
return Response.ok().build();
}
else{
return Response.status(Status.BAD_REQUEST).entity("Wrong password !!!").build();
}
//return reposnse;
}
This information might be useful that on the console it prints
entered functionnullnull
So it the restfull function is called however it is not receiving the query parameters.
Any help would be really appreciated!
First, you could replace the #QueryParam annotations with #FormParam ones to retrieve the 'new' and 'old' parameters of the PUT request. Then, you should remove the #Consumes("application/json") annotation and contentType:application/json from your server and browser side code, and finally replace the submitted data in JSON format into something like 'new=qwe&old=123'.
If you want to stay with a content in JSON format, you should probably map the incoming body with an entity (ie, a Java class annotated with JAXB annotations), so that the JAX-RS implementation you use could unmarshall the incoming JSON content into a Java object.
HTH.

504 error accessing Kinvey handshake(Rest api)

I have been trying to get the Kinvey handshake for the REST api to work for a while now but have not had any luck. I am using libgdx's net class to send the http request. Wverytime I send the request I get a 504(Gateway Timeout) error. I am following the instructions on the website so I am not sure why I would get that error.
Here is my attempt:
HttpRequest request = new HttpRequest(HttpMethods.GET);
request.setHeader("GET", "/appdata/:App_key");
request.setHeader("Host:", "baas.kinvey.com");
String authHeader = "Basic " + Base64Coder.encodeString("App_key:App_secret");
request.setHeader("Authorization:", authHeader);
request.setUrl("https://baas.kinvey.com/appdata/App_key");
System.out.println("HTTP REQUEST: " + request.getHeaders());
responseListener listener = new responseListener() {
public void handleHttpResponse (HttpResponse httpResponse) {
HttpStatus status = httpResponse.getStatus();
if (status.getStatusCode() >= 200 && status.getStatusCode() < 300) {
System.out.println("HTTP SUCCESS!");
} else {
System.out.println("HTTP ERROR: " + status.getStatusCode());
}
System.out.println("HTTP :" + httpResponse.getResultAsString());
}
#Override
public void failed(Throwable t) {
t.printStackTrace();
System.out.println("REQUEST FAILED!" +t.getMessage());
super.failed(t);
}
};
Gdx.net.sendHttpRequest(request, listener);
As far as I can tell, there is something wrong with the header. I have tested the Url which takes me to a login screen. The login works after I put in the App key as the user name and the Master secret as the password. Is there something obviously wrong? Is there a way I can debug this further?
I'm an engineer at Kinvey and can help you out with this.
A couple things:
first, there are some extra headers there that you don't need. While they might not be the cause of the issue, it is still safe to remove:
request.setHeader("GET", "/appdata/:App_key");
request.setHeader("Host:", "baas.kinvey.com");
Note that GET is set when you create the HttpRequest, and Host is set when you define the URL.
Second, get rid of the colon after "authorization" when setting your header, make it look like this:
request.setHeader("Authorization", authHeader);
Also, you mention that it works with your master secret but not with your app secret? Can you ensure that you are base64 encoding both?
One last thing-- ensure that you replace App_Key with your actual app key, in the URL as well as in the headers.

How to construct a REST API that takes an array of id's for the resources

I am building a REST API for my project. The API for getting a given user's INFO is:
api.com/users/[USER-ID]
I would like to also allow the client to pass in a list of user IDs. How can I construct the API so that it is RESTful and takes in a list of user ID's?
If you are passing all your parameters on the URL, then probably comma separated values would be the best choice. Then you would have an URL template like the following:
api.com/users?id=id1,id2,id3,id4,id5
api.com/users?id=id1,id2,id3,id4,id5
api.com/users?ids[]=id1&ids[]=id2&ids[]=id3&ids[]=id4&ids[]=id5
IMO, above calls does not looks RESTful, however these are quick and efficient workaround (y). But length of the URL is limited by webserver, eg tomcat.
RESTful attempt:
POST http://example.com/api/batchtask
[
{
method : "GET",
headers : [..],
url : "/users/id1"
},
{
method : "GET",
headers : [..],
url : "/users/id2"
}
]
Server will reply URI of newly created batchtask resource.
201 Created
Location: "http://example.com/api/batchtask/1254"
Now client can fetch batch response or task progress by polling
GET http://example.com/api/batchtask/1254
This is how others attempted to solve this issue:
Google Drive
Facebook
Microsoft
Subbu Allamaraju
I find another way of doing the same thing by using #PathParam. Here is the code sample.
#GET
#Path("data/xml/{Ids}")
#Produces("application/xml")
public Object getData(#PathParam("zrssIds") String Ids)
{
System.out.println("zrssIds = " + Ids);
//Here you need to use String tokenizer to make the array from the string.
}
Call the service by using following url.
http://localhost:8080/MyServices/resources/cm/data/xml/12,13,56,76
where
http://localhost:8080/[War File Name]/[Servlet Mapping]/[Class Path]/data/xml/12,13,56,76
As much as I prefer this approach:-
api.com/users?id=id1,id2,id3,id4,id5
The correct way is
api.com/users?ids[]=id1&ids[]=id2&ids[]=id3&ids[]=id4&ids[]=id5
or
api.com/users?ids=id1&ids=id2&ids=id3&ids=id4&ids=id5
This is how rack does it. This is how php does it. This is how node does it as well...
There seems to be a few ways to achieve this. I'd like to offer how I solve it:
GET /users/<id>[,id,...]
It does have limitation on the amount of ids that can be specified because of URI-length limits - which I find a good thing as to avoid abuse of the endpoint.
I prefer to use path parameters for IDs and keep querystring params dedicated to filters. It maintains RESTful-ness by ensuring the document responding at the URI can still be considered a resource and could still be cached (although there are some hoops to jump to cache it effectively).
I'm interested in comments in my hunt for the ideal solution to this form :)
You can build a Rest API or a restful project using ASP.NET MVC and return data as a JSON.
An example controller function would be:
public JsonpResult GetUsers(string userIds)
{
var values = JsonConvert.DeserializeObject<List<int>>(userIds);
var users = _userRepository.GetAllUsersByIds(userIds);
var collection = users.Select(user => new { id = user.Id, fullname = user.FirstName +" "+ user.LastName });
var result = new { users = collection };
return this.Jsonp(result);
}
public IQueryable<User> GetAllUsersByIds(List<int> ids)
{
return _db.Users.Where(c=> ids.Contains(c.Id));
}
Then you just call the GetUsers function via a regular AJAX function supplying the array of Ids(in this case I am using jQuery stringify to send the array as string and dematerialize it back in the controller but you can just send the array of ints and receive it as an array of int's in the controller). I've build an entire Restful API using ASP.NET MVC that returns the data as cross domain json and that can be used from any app. That of course if you can use ASP.NET MVC.
function GetUsers()
{
var link = '<%= ResolveUrl("~")%>users?callback=?';
var userIds = [];
$('#multiselect :selected').each(function (i, selected) {
userIds[i] = $(selected).val();
});
$.ajax({
url: link,
traditional: true,
data: { 'userIds': JSON.stringify(userIds) },
dataType: "jsonp",
jsonpCallback: "refreshUsers"
});
}