Http 400 in appengine when using URLFetch with Http Method 'DELETE' - java

I've been unable to make a "DELETE" request using the code below :
URLFetchService fetchService = URLFetchServiceFactory.getURLFetchService();
URL posturl = new URL("http://www.example.com/comment?token=xxx");
HTTPResponse response = fetchService.fetch(new HTTPRequest(posturl, HTTPMethod.DELETE));
int responseCode = response.getResponseCode();
This is for Google Appengine. The 'DELETE' request is for the facebook graph API. The above code gives me a status code 400 - Bad Request.
This is for face4j an open source java library that I've built for the facebook graph API.

This isn't really an App Engine problem; it just means that the destination webserver wouldn't accept your request.
If you're actually trying to send a DELETE to example.com, that's your problem. If that's supposed to be a scrubbed URL, you've omitted the detail that would facilitate troubleshooting.

Related

how to create client TGT with java cxf

I'm new to the java rest CXF client. I will make various requests to a remote server, but first I need to create a Ticket Granting Ticket (TGT). I looked through various sources but I could not find a solution. The server requests that I will create a TGT are as follows:
Content-Type: text as parameter, application / x-www-form-urlencoded as value
username
password
I create TGT when I make this request with the example URL like below using Postman. (URL is example). But in the code below, I'm sending the request, but the response is null. Could you help me with the solution?
The example URL that I make a request with POST method using Postman: https://test.service.com/v1/tickets?format=text&username=user&password=pass
List<Object> providers = new ArrayList<Object>();
providers.add(new JacksonJsonProvider());
WebClient client = WebClient.create("https://test.service.com/v1/tickets?format=text&username=user&password=pass", providers);
Response response = client.getResponse();
You need to do a POST, yet you did not specify what your payload looks like?
Your RequestDTO and ResponseDTO have to have getters/setters.
An example of using JAX-RS 2.0 Client.
Client client = ClientBuilder.newBuilder().register(new JacksonJsonProvider()).build();
WebTarget target = client.target("https://test.service.com/v1/tickets");
target.queryParam("format", "text");
target.queryParam("username", "username");
target.queryParam("password", "password");
Response response = target.request().accept(MediaType.APPLICATION_FORM_URLENCODED).post(Entity.entity(yourPostDTO,
MediaType.APPLICATION_JSON));
YourResponseDTO responseDTO = response.readEntity(YourResponseDTO.class);
int status = response.getStatus();
Also something else that can help is if you copy the POST request from POSTMAN as cURL request. It might help to see the differences between your request and POSTMAN. Perhaps extra/different headers are added by postman?
Documentation: https://cxf.apache.org/docs/jax-rs-client-api.html#JAX-RSClientAPI-JAX-RS2.0andCXFspecificAPI
Similar Stackoverflow: Is there a way to configure the ClientBuilder POST request that would enable it to receive both a return code AND a JSON object?

Getting Access denied if call API without call the official website

I'm Benjamin, currently study in IT and doing a simple application for Final Year Project.
The simple application is calling Third Party API (An fashion products company) and returns product description, stock level and etc to users.
First, I don't have any official API documents and everything starts from scratch.
I have been using java - CloseableHttpClient to call an API with the method GET.
Coding works fine BUT I met an error that "no response" or Access Denied if I tried to call the API directly. (without any cookies or with existing cookies from the official website)
Then I tried with a browser(any) to hit the API link, it will return Access Denied
But when I tried with a browser and hit the official website without any login, and hit again the API then able to get responses.
I have been tried to passing the cookies that returned from the official website but still no responses when I call/hit the API link on java code or Postman.
Answer for why calling an API that doesn't have any official documentation as below:
This is an FYP in University, API is selected and provided by University Lecturer.
My code as below :
CloseableHttpClient httpClient = HttpClientBuilder.create()
.setDefaultCookieStore(cookieStoreNew)
.setUserAgent("Mozilla/5.0").build();
HttpGet getRequest = new HttpGet(url);
getRequest.addHeader("accept", "application/json");
getRequest.addHeader(HttpHeaders.USER_AGENT, "Mozilla/5.0");
getRequest.setConfig(requestConfig);
System.out.println("this is get request config : \n"+getRequest);
System.out.println("\n start execute");
HttpResponse response = httpClient.execute(getRequest);//it will stucked here and no reponses
System.out.println("\n end execute");
if (response.getStatusLine().getStatusCode() != 200) {
throw new RuntimeException("Failed : HTTP error code : "
+ response.getStatusLine().getStatusCode());
}
Please comment below if you have any idea or any advice and Appreciate your help.
This is not spoon feed, I have been researched for over 2 weeks.
Thanks
I have worked in such scenarios like yours when the written code needs to make any HTTP request to an API (third party).
As far as my experience says, there should be some issue of Authentication for your code.
As you said hitting the same API on browser also says "Access denied", some login credentials must be required by API with the GET request you are sending, so when creds are not found, API responds with "Access Denied"..
Could you check the http status code your getting in postman while you are hitting the API, it must be 401/403(Unauthorized).
if in postman http status code is 401/403 indeed, then Kindly ask your University Lecturer for any logins that might be required to hit the API.

IoT module GET request in Java

I'm trying to read a JSON response from a RESTful webserver running on an IoT module (Advantech WISE-4012). According to the documentation, any GET request should be made in this form
GET /ai_value/slot_0/ch_0
Any Java implementation of GET requests (Java libraries, Apache etc.), anyway, append to the end of the request the protocol signature HTTP/1.1. E.g:
GET http://192.168.0.14/ai_value/slot_0/ch_0 HTTP/1.1
Because of this (probably) i'm getting Error 400 (Bad request) on every client i tried so far. The only working method i've discovered was sending a simple request through the address bar on Google Chrome browser (sometimes i get a response, sometimes a get a bad request error either). How can i write a java implementation of a GET request plain and simple as described by the documentation? How can i test a custom GET request without HTTP/1.1 at the end? Every chrome extension i tried (Advanced REST Client, Postman) add the protocol version at the end, so i haven't had the chance to verify if that's why i'm getting a bad request error.
EDIT:
This is the response header from Advanced REST client
Connection: close
Content-Type: application/json
Server: WISE-4000/8.1.0020
While the source message is the following one:
GET /ai_value/slot_0/ch_0 HTTP/1.1
HOST: 192.168.0.14
The only mismatch between the documentation is the HTTP/1.1 signature as mentioned before. Adding the "accept: application/json" makes no difference either
After a bit of digging into the documentation, it looks like the default timeout (i.e. 720 seconds) is the one causing an issue. There doesn't seem to be any way to work it around (ideally, the system should reset the time after a successful request and we should only get 400 - or 403 ideally after 720 seconds of inactivity).
A couple of points I would like to recommend to the API developers for WISE-4012 (if they are in touch with you):
Add brief documentation for authentication and timeout (probably, more response codes and error messages with each error response)
Enable OAuth for API Access
As far as current implentation is conerned, I guess you need to do a basic auth and pass username/password with every request, Or add Authentication header with every API request to get successful response without any 400s.
Check if this helps.
HttpClient httpClient = HttpClients.createDefault();
URI reqUri = new URI(<uri>);
RequestBuilder requestBuilder = RequestBuilder.create("GET");
requestBuilder.setUri(reqUri);
requestBuilder.setHeader(<headerKey>, <headerValue>);
requestBuilder.setEntity(<entity_data>);
HttpUriRequest httpRequest = requestBuilder.build();
httpResponse = httpClient.execute(httpRequest);

Parsing the result of a PHP Web Service

I'm using a PHP Web Services that I'm consuming on an Android application.
The Web Services inserts data on a database and returns information from it.
How I can parse the result of using that Web Service to avoid errors?
In Android, I execute the post request by this way:
HttpResponse response = httpclient.execute(httpost);
What should I do on the Web Service to process possible errors?
Thanks!
As eduyayo and Deutro said. You can check status code of your response
int statusCode = response.getStatusLine().getStatusCode();
List of Status codes - HttpStatus codes and handle exceptions accordingly.
On your Server you should return different StatusCodes for different ErrorMessages.
In your client you can check for the error StatusCodes and update your UI according to the error you get.

Resumable upload to GCS from Android client using `upload_id` for auth

This is from the GCS Access Control documentation on signed URLs and it matches my use case exactly (the resumable upload scenario):
Note: If your users are only uploading resources (writing) to an
access-controlled bucket, you can use the resumable uploads
functionality of Google Cloud Storage, and avoid signing URLs or
requiring a Google account. In a resumable upload scenario, your
(server-side) code authenticates and initiates an upload to Google
Cloud Storage without actually uploading any data. The initiation
request returns an upload ID, which can then be used in a client
request to upload the data. The client request does not need to be
signed because the upload ID, in effect, acts as an authentication
token. If you choose this path, be sure to transmit the upload ID over
HTTPS.
I have a GAE instance which successfully authenticates and initiates a resumable upload to GCS. As expected, GCS returns my GAE server a response:
HTTP/1.1 200 OK
Location: https://www.googleapis.com/upload/storage/v1/b/<my-apps-default-bucket>/o?uploadType=resumable&name=<my-file-name>&upload_id=xa298sd_sdlkj2
Content-Length: 0
The GAE server hands the Android client the URL from the above location and the Android client uses this to try to PUT the file to GCS. Here is the basic code snippet used:
HttpClient client = new DefaultHttpClient();
String url = <URL-returned in Location-Header>; // exactly the URL returned in the GCS response above
Log.v("PUT URL", url);
HttpPut put = new HttpPut(url);
put.addHeader("Content-Type", "<my-file-mime-type>");
// Note that HttpPut adds the `Content_Length` based on the entity added. Doing it by hand will throw an Exception
MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create();
entityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
entityBuilder.addBinaryBody("file", new File("<path-to-my-file>"));
HttpEntity entity = entityBuilder.build();
put.setEntity(entity);
HttpResponse response = client.execute(put);
HttpEntity httpEntity = response.getEntity();
responseMsg = EntityUtils.toString(httpEntity);
Log.v("resultMsg", responseMsg);
Logs show the response from GCS for the above PUT is:
{
"error":{
"errors":[
{
"domain":"global",
"reason":"badRequest",
"message":"Invalid Upload Request"
}
],
"code":400,
"message":"Invalid Upload Request"
}
}
My question is to anyone who has gotten the resumable upload scenario to work for this use case: (1) Client asks server to initiate resumable upload, (2) server initiates upload and gets Location with upload_id, (3) server passes these to client, (4) client uses these to upload file to GCS directly with no additional authentication (no signed URL). Is there something I'm missing? According to the documentation it looks like this approach should be working. Does anyone have pointers or experience that could help me out?
Thanks.

Categories