How to send Entity in API DELETE with HTTP-CLIENT - java

I have to call a DELETE Method inside one of the APIS of a client.
This shouldn´t be a problem but I am struggling with the framework that my company currently uses and I hope I can get some info that hopefully will help me solve the problem:
First thing first.
1: The api doesn´t work if I do the call sending the params as URL:
2: It works completely OK if I send the params inside the body as x-www-form-urlencoded but not form-data or raw
The documentation of the method inside the API told us the following: (Important to Look to IDEtapa)
I have to do this call in JAVA (JAVA 8)
currently my company uses HTTP_CLIENT as the main framework for APICalls.
My code:
The build of the Data (Currently I build both, as Entity and as Params for you to view I´ve tried with each one of them indepently):
Map datosApi = new HashMap<>();
datosApi.put(Constants.URL, anular_cita);
Map headers = new HashMap<>();
headers.put(Constants.AUTHORIZATION, params.get("token_autorizacion"));
headers.put("Content-Type", "application/json");
headers.put("entity_charset", "UTF-8");
datosApi.put(Constants.HEADERS, headers);
JSONObject entity = new JSONObject();
Map param = new HashMap();
param.put(Constants.ID_CENTRO, consul);
param.put("IdAsistencia", propiedades[0]);
param.put("IdCapitulo", propiedades[1]);
param.put("IdEtapa", Integer.valueOf(propiedades[2]));
entity.put(Constants.ID_CENTRO, consul);
entity.put("IdAsistencia", propiedades[0]);
entity.put("IdCapitulo", propiedades[1]);
entity.put("IdEtapa", Integer.valueOf(propiedades[2]));
datosApi.put("entity", entity.toString());
datosApi.put("entity_mime_type", "application/json");
datosApi.put("entity_charset", "UTF-8");
datosApi.put("params", param);
String anularCita = APIDao.callAPIDelete(datosApi);
The preparation for my call to the framework:
public static String callAPIDelete(Map in) {
String contentString = "";
Map res = new HashMap<>();
try {
res = XWM.execute("delete#http_client", in);
byte[] content = (byte[]) res.get("content");
contentString = new String(content, StandardCharsets.UTF_8);
And inside our framework we have this:
if (StringUtils.equals(StringUtils.trim(method), "delete"))
{
StringBuilder requestUrl = new StringBuilder(url);
if (formparams != null)
{
if (requestUrl.indexOf("?")==-1) requestUrl.append("?");
else requestUrl.append("&");
requestUrl.append(URLEncodedUtils.format(formparams, charset));
}
if (entityRequest != null)
{
log.error("Param 'entity' no puede usarse en get (se ignora)");
}
HttpDelete delete = new HttpDelete(requestUrl.toString());
delete.setConfig(requestConfig);
uriRequest = delete;
}
}
}
}
// Headers
if (headers != null)
{
for (String h: headers.keySet()) uriRequest.addHeader(h, headers.get(h));
}
// Ejecutamos método
log.info("Executing request " + uriRequest.getRequestLine());
CloseableHttpResponse response = null;
if (!preemtiveAuth || credsProvider == null)
{
response = httpclient.execute(uriRequest);
}
As you can see, in the delete method, we ignore the entity that i´ve built in the first patch of code.
The HTTPDelete Class is APACHE, the url with info of the class is the following:
https://www.javadoc.io/doc/org.apache.httpcomponents/httpclient/4.5.2/org/apache/http/client/methods/HttpDelete.html
The question can be divided in two:
1: Can we send the Entity in a Delete Call? I have found a few info about this in the following places:
Is an entity body allowed for an HTTP DELETE request?
https://web.archive.org/web/20090213142728/http://msdn.microsoft.com:80/en-us/library/cc716657.aspx
https://peterdaugaardrasmussen.com/2020/11/14/rest-should-you-use-a-body-for-your-http-delete-requests/
I assume that in order to do it, i would need a new HttpDelete that would allow us to use entity, if possible, could you give me some examples of this?
2: For what i understand of the links i posted above, while using entity in Delete calls is not forbidden is something that is not encouraged, Should I just talk with the people who made the API and ask them to change their configuration to allow us to send the info by params? (It is not personal or sensible info, just a bunch of IDs)
Thank you so much for your attention and my apologies for any typo or format mistake, still learning how to make good posts.
EDIT: i have found this answer setEntity in HttpDelete that more or less solve the first issue about if its, posible to send an Entity in a Delete call, but still, don´t now if it should be better to ask them to change their method

As told in the coments by Ewramner and VoiceOfUnreason and in the edits:
1: The answer about how to make this was found in an older post of StackOverflow: setEntity in HttpDelete
2: The answer about "Should I just talk with the people who made the API and ask them to change their configuration to allow us to send the info by params?" was answered by both of them. While it´s not forbidden, it´s something thats not recommended.
My course of action will be:
1: Talk with the people responsible for the API to give them info about this situation.
2: Ask our Architecture team to create a new method that will allow us to do HttpDelete calls with an entity body, just in case that we have to make more API calls like this one.
With this i think all my answers are solved.
Again, Thank you.

Related

Github api CREATEPULLREQUEST (Java api )

org.eclipse.egit.github.core.client.RequestException: Invalid request. "base", "head" weren't supplied. (422)
Source code
pullRequestService = new PullRequestService(gitHubClient);
PullRequest request=new PullRequest();
request.setTitle("a fix");
request.setBody("this is a fix");
request.setHead(new PullRequestMarker().setRef("testBranch"));
request.setBase(new PullRequestMarker().setRef("master"));
pullRequestService.createPullRequest(repo,request);
testBranch Branch is created in my repo.
not able to create pull request through java api
I am not an expert of github api, but by checking the code, I suspect you should call setLabel() instead of setRef(), as the PullRequestService works with the label value as base and head:
String base = baseMarker.getLabel();
if (base != null)
params.put(PR_BASE, base);
Repo
I encoutered same error when tried creating pull request using egit.github.core api. Finally below code worked for me.
PullRequestService pullRequestService = new PullRequestService(client);
pullRequestService.getClient().setCredentials("<userid>", "<password>");
RepositoryId repo = RepositoryId.createFromId("<owenerName>" + "/" + "repoName");
PullRequest request = new PullRequest();
request.setTitle("Please merge");
request.setBody("Please merge");
request.setHead(new PullRequestMarker().setRef("<branchName>").setLabel("< branchName >"));
request.setBase(new PullRequestMarker().setRef("master").setLabel("master"));
pullRequestService.createPullRequest(repo,request);
Just make sure branch exists and has commit pushed to it.

RapidApi Android

I am messing around with RapidAPI and i dont undertand the code they give.
Could someone give me a teardown? It says in order to access api i have to write the following code
Map<String, Argument> body = new HashMap<String, Argument>();
body.put("ParameterKey1", new Argument("data", "ParameterValue1"));
body.put("ParameterKey2", new Argument("data", "ParameterValue2"));
try {
Map<String, Object> response = connect.call("APIName", "FunctionName", body);
if(response.get("success") != null) { }
what are parameter keys 1 and 2, the data, and the parameter values
edit1:this is the code snippet i want to use in android studio
HttpResponse<JsonNode> response = Unirest.get("https://spoonacular-recipe-
food-nutrition-v1.p.mashape.com/recipes/search?
diet=vegetarian&excludeIngredients=coconut&instructionsRequired=
false&intolerances=egg%2C+gluten&limitLicense=false&number=
10&offset=0&query=burger&type=main+course")
.header("X-Mashape-Key",
"Xxxxxx")
.header("X-Mashape-Host", "spoonacular-recipe-food-nutrition-
v1.p.mashape.com")
.asJson();
Your example code is using this https://github.com/zeeshanejaz/unirest-android. If you want to use that snippet you could start with that.

How to perform Amazon Cloud Search with .net code?

I am learning Amazon Cloud Search but I couldn't find any code in either C# or Java (though I am creating in C# but if I can get code in Java then I can try converting in C#).
This is just 1 code I found in C#: https://github.com/Sitefinity-SDK/amazon-cloud-search-sample/tree/master/SitefinityWebApp.
This is 1 method i found in this code:
public IResultSet Search(ISearchQuery query)
{
AmazonCloudSearchDomainConfig config = new AmazonCloudSearchDomainConfig();
config.ServiceURL = "http://search-index2-cdduimbipgk3rpnfgny6posyzy.eu-west-1.cloudsearch.amazonaws.com/";
AmazonCloudSearchDomainClient domainClient = new AmazonCloudSearchDomainClient("AKIAJ6MPIX37TLIXW7HQ", "DnrFrw9ZEr7g4Svh0rh6z+s3PxMaypl607eEUehQ", config);
SearchRequest searchRequest = new SearchRequest();
List<string> suggestions = new List<string>();
StringBuilder highlights = new StringBuilder();
highlights.Append("{\'");
if (query == null)
throw new ArgumentNullException("query");
foreach (var field in query.HighlightedFields)
{
if (highlights.Length > 2)
{
highlights.Append(", \'");
}
highlights.Append(field.ToUpperInvariant());
highlights.Append("\':{} ");
SuggestRequest suggestRequest = new SuggestRequest();
Suggester suggester = new Suggester();
suggester.SuggesterName = field.ToUpperInvariant() + "_suggester";
suggestRequest.Suggester = suggester.SuggesterName;
suggestRequest.Size = query.Take;
suggestRequest.Query = query.Text;
SuggestResponse suggestion = domainClient.Suggest(suggestRequest);
foreach (var suggest in suggestion.Suggest.Suggestions)
{
suggestions.Add(suggest.Suggestion);
}
}
highlights.Append("}");
if (query.Filter != null)
{
searchRequest.FilterQuery = this.BuildQueryFilter(query.Filter);
}
if (query.OrderBy != null)
{
searchRequest.Sort = string.Join(",", query.OrderBy);
}
if (query.Take > 0)
{
searchRequest.Size = query.Take;
}
if (query.Skip > 0)
{
searchRequest.Start = query.Skip;
}
searchRequest.Highlight = highlights.ToString();
searchRequest.Query = query.Text;
searchRequest.QueryParser = QueryParser.Simple;
var result = domainClient.Search(searchRequest).SearchResult;
//var result = domainClient.Search(searchRequest).SearchResult;
return new AmazonResultSet(result, suggestions);
}
I have already created domain in Amazon Cloud Search using AWS console and uploaded document using Amazon predefine configuration option that is movie Imdb json file provided by Amazon for demo.
But in this method I am not getting how to use this method, like if I want to search Director name then how do I pass in this method as because this method parameter is of type ISearchQuery?
I'd suggest using the official AWS CloudSearch .NET SDK. The library you were looking at seems fine (although I haven't look at it any detail) but the official version is more likely to expose new CloudSearch features as soon as they're released, will be supported if you need to talk to AWS support, etc, etc.
Specifically, take a look at the SearchRequest class -- all its params are strings so I think that obviates your question about ISearchQuery.
I wasn't able to find an example of a query in .NET but this shows someone uploading docs using the AWS .NET SDK. It's essentially the same procedure as querying: creating and configuring a Request object and passing it to the client.
EDIT:
Since you're still having a hard time, here's an example. Bear in mind that I am unfamiliar with C# and have not attempted to run or even compile this but I think it should at least be close to working. It's based off looking at the docs at http://docs.aws.amazon.com/sdkfornet/v3/apidocs/
// Configure the Client that you'll use to make search requests
string queryUrl = #"http://search-<domainname>-xxxxxxxxxxxxxxxxxxxxxxxxxx.us-east-1.cloudsearch.amazonaws.com";
AmazonCloudSearchDomainClient searchClient = new AmazonCloudSearchDomainClient(queryUrl);
// Configure a search request with your query
SearchRequest searchRequest = new SearchRequest();
searchRequest.Query = "potato";
// TODO Set your other params like parser, suggester, etc
// Submit your request via the client and get back a response containing search results
SearchResponse searchResponse = searchClient.Search(searchRequest);

java axis web service client setMaintainSession on multiple services (cookies?)

I'm implementing a client to a web service (and the guys maintaining the web service have been a litte unresponsive..) I've used axis and WSDL2Java to generate java classes and I can call their login-method on their authentication-service ok, and get a sessionId back (eg z4zojhiqkw40lj55kgtn1oya). However, it seems that i cannot use this sessionId as a parameter anywhere. Even a call to their hasSession()-method directly after login returned false. I managed to solve this by setting setMaintainSession(true) on the Locator-object for this service. But the problem is, that this first service, the Authentication-service, is only used for authentification. If I then call setMaintainSession(true) on eg ProductServiceLocator, and call some method on it, I will get an error because of unauthenticated session. I have to find a way to share the session between the services on the client side.
Looking on their php code example-it seeems like they are storing the session in a cookie. How can I mimic this behaviour in my java client?
php-code:
$authentication = new SoapClient ( "https://webservices.24sevenoffice.com/authenticate/authenticate.asmx?wsdl", $options );
// log into 24SevenOffice if we don't have any active session. No point doing this more than once.
$login = true;
if (!empty($_SESSION['ASP.NET_SessionId'])){
$authentication->__setCookie("ASP.NET_SessionId", $_SESSION['ASP.NET_SessionId']);
try{
$login = !($authentication->HasSession()->HasSessionResult);
}
catch ( SoapFault $fault ) {
$login = true;
}
}
if( $login ){
$result = ($temp = $authentication->Login($params));
// set the session id for next time we call this page
$_SESSION['ASP.NET_SessionId'] = $result->LoginResult;
// each seperate webservice need the cookie set
$authentication->__setCookie("ASP.NET_SessionId", $_SESSION['ASP.NET_SessionId']);
// throw an error if the login is unsuccessful
if($authentication->HasSession()->HasSessionResult == false)
throw new SoapFault("0", "Invalid credential information.");
}
My code is the following:
AuthenticateLocator al = new AuthenticateLocator();
al.setMaintainSession(true);
Credential c = new Credential(CredentialType.Community,username,password,guid);
AuthenticateSoap s = al.getAuthenticateSoap();
String sessionId = s.login(c);
System.out.println("Session id was: "+sessionId);
System.out.println("Has Session: "+s.hasSession()); //Hooray, now works after setMaintainSession(true)
//And now trying to call another Service
CompanyServiceLocator cl = new CompanyServiceLocator();
cl.setMaintainSession(true);
CompanyServiceSoap css = cl.getCompanyServiceSoap();
css.getCountryList(); //FAILS!
So what can I do to make this work?
Hooray, I finally solved it myself :-D
Thanx a lot to the excellent article at http://www.nsftools.com/stubby/ApacheAxisClientTips.htm
I had to do the following with my code to make it work:
CompanyServiceLocator cl = new CompanyServiceLocator();
cl.setMaintainSession(true);
CompanyServiceSoap css = cl.getCompanyServiceSoap();
((Stub)css)._setProperty(HTTPConstants.HEADER_COOKIE, "ASP.NET_SessionId="+sessionId); //New line that does the magic
css.getCountryList(); //SUCCESS :-D
Operating in the high-level abstraction of the autogenerated classes, it was unknown to me that casting the service classes to Stub would expose more methods and properties that could be set. Good to know for later I guess :-)

Blogger JSON API add a post

I want to add post to my blog using Blogger API. I successfully got rights to use Blogger API and activated them in Google API console. I used this tutorial to obtain access_token. I found this question , so before ever request I obtain new request_token.
When I make first request to add post, I got en error: 401 "message": "Invalid Credentials", "location": "Authorization".
When I make second request to add post with new token, I got error: 403 "message": "Daily Limit Exceeded. Please sign up"
Code for my request is:
final JSONObject obj = new JSONObject();
obj.put("id", mUserID);
final JSONObject requestBody = new JSONObject();
requestBody.put("kind", "blogger#post");
requestBody.put("blog", obj);
requestBody.put("title", msg[0]);
requestBody.put("content", msg[0] + " " + msg[1]);
final HttpPost request = new HttpPost("https://www.googleapis.com/blogger/v3/blogs/" + mUserID + "/posts");
request.addHeader("Authorization", "Bearer " + mToken);
request.addHeader("Content-Type", "application/json");
request.setEntity(new StringEntity(requestBody.toString()));
final HttpResponse response = mHttpClient.execute(request);
final HttpEntity ent = response.getEntity();
Log.i(SocialPoster.LOG, EntityUtils.toString(ent));
ent.consumeContent();
UPDATE
Solution was found: simply adding "?key={MY_API_KEY}" to request's URL solved the problem
The Tutorial site you linked states
"The API Key is mandatory as it identifies your application and therefore allows the API to deduct quota and use the quota rules defined for your project. You need to specify the API Key on your Tasks service Object."
useTasksAPI(String accessToken) {
// Setting up the Tasks API Service
HttpTransport transport = AndroidHttp.newCompatibleTransport();
AccessProtectedResource accessProtectedResource = new GoogleAccessProtectedResource(accessToken);
Tasks service = new Tasks(transport, accessProtectedResource, new JacksonFactory());
service.accessKey = INSERT_YOUR_API_KEY;
service.setApplicationName("Google-TasksSample/1.0");
// TODO: now use the service to query the Tasks API
}
Sounds to me like you are missing the API key, using it wrong, misplaced it in your code or supplied it to the service in the wrong way.
I haven't looked over the code here, but this is Google's sample code for what you are trying to do. Test your API key with this code.

Categories