I am experiencing a weird issue when working with RestTemplate. I'm using a certain REST API and there I want to update something using PUT.
Thus, in e.g. Postman I am sending this request:
PUT http://fake/foobar/c/123 with a certain body
This update via Postman is successful. If I now execute the same call in Java via a RestTemplate, I am getting a 405 Method Not Allowed:
HttpHeaders headers = createHeader();
HttpEntity<Offer> httpEntity = new HttpEntity<>(bodyEntity, headers);
String url = "http://fake/foobar/c/123"; //Created dynamically, but here pasted for sake of simplicity
RestTemplate restTemplate = new RestTemplate(...);
ResponseEntity<OfferResponse> response = restTemplate.exchange(url, HttpMethod.PUT, httpEntity, OfferResponse.class);
...
I compared the URL again and again. If I copy the URL logged in the console and copy it to Postman, I can do the update successfully. I also compared the headers and everything. Everything is equal to how it is done via Postman.
Is there any potential other reason for such a behavior (another reason than I am too stupid comparing the headers etc. and missing something)? Other PUT, POST calls etc. against this API are working fine, otherwise I would have assumed that there is a general problem with my usage of RestTemplate
Code 405 Method Not Allowed means the HTTP verb (GET, POST, PUT, etc.) you use against this end-point is known but not accepted by the API.
If you can't post the details of your API as #Dinesh Singh Shekhawat suggested, I will first try to use Postman Code feature and get an automatically generated code for Java (OkHTTP or UniRest) of the request. You can find this option on the right part below the Send button. Copy this code and try to perform the request.
Then compare this request with yours.
You can always use HttpPut instead of RestTemplate if it's not a requirement:
HttpClient client = HttpClientBuilder.create().build();
String url = "http://fake/foobar/c/123";
HttpHeaders headers = createHeader();
HttpEntity<Offer> httpEntity = new HttpEntity<>(bodyEntity, headers);
HttpPut httpPut = new HttpPut(url);
httpPut.setEntity(httpEntity);
HttpResponse response = client.execute(httpPut);
I was facing the same problem. Later I printed the request and URL in the logs.
I found that I was using a wrong endpoint.
Can you please try to print the URL and the request in the logs and check if those are expected and correct?
Just in case it helps someone else: I was encountering the same issue and for me it was just the issue of a trailing slash / on the URL. In insomnia (similar to postman) I had a trailing slash, in code I didn't. When I added the slash to my code everything worked.
failure: http://localhost:8080/api/files
success: http://localhost:8080/api/files/
Of course it could also be the other way around, so just double check the actual api definition.
Related
have to use akka library with java and i need to do a post request with body in it, a body like this: {"subjectId":961,"other":null}
In this application, I have some examples already written with get requests and parameters to those requestes. but now i need to send a post request with body in it.
The following snippet is correct? if not, can you tell me what i do wrong? thanks.
..
Http http = new Http((ExtendedActorSystem) context().system());
HttpRequest postRequest = HttpRequest.POST(url)
.withEntity(MediaTypes.APPLICATION_JSON.toContentType(),
"{\"subjectId\": 961, \"other\": null,}");
CompletionStage<HttpResponse> response = http.singleRequest(postRequest);
..
I am currently working on renewing youtrack api methods in the project since old youtrack api has been deprecated, and when I'm trying to send requsts such as:
https://youtrack.my.ru/api/admin/customFieldSettings/bundles/version/
https://youtrack.my.ru/api/issues?query=sampletext
and I am getting
400 HTTP method POST is not supported by this URL
Thr problem is not in the requsts itself, because i tryed using the same requests with the same bodies and headers via postman and it worked perfectly, so i assume it is something with my java restTemplate config, you can se samples of me sending requests below:
ResponseEntity<String> response = restTemplate.exchange(uri, HttpMethod.POST, versionsEntity, String.class);
logger.debug("Adding new version response status is {}", response.getStatusCode());
return response.getStatusCode() == HttpStatus.CREATED;
And this is how I add body to the requst (the body is the versionBundle object):
versionsEntity = new HttpEntity<>(new ObjectMapper().writeValueAsString(versionBundle), entity.getHeaders());
You can also see that youtrack api itself is perfectly ok with me using POST requst to update a bundle here: https://www.jetbrains.com/help/youtrack/devportal/operations-api-admin-customFieldSettings-bundles-version.html#update-VersionBundle-method
Any help is appreciated!
Somehow problem was resolved by creating new RestTemplate with autowired templateFactory, before i was autowiring RestTemplate, if someone can explain me why is this helped it would be great
I want to change data on a server via a put request, but I always get a 401 [no body] error. The response looks like the following:
I do not really understand why I get this error, because my body is not empty. My code looks like this and the values seem to be okay too. Does anyone have any idea what I'm doing wrong?
Postman Update:
The values are different right now (consent and authorisation) since its basically a new request but the values were correct before too so this change should not make a difference.
Looks like you are simply passing invalid authorization header, or maybe not passing it at all.
What happens is that you make a RestTemplate exchange call, then you get 401 from that request, and Spring propagates it and returns 500 - Internal Server Error, because there is no error handling in place.
EDIT: According to your screenshots, you are not replacing your path variables. Update the way you build your URL as listed below.
Map<String, String> pathVars = new HashMap<>(2);
pathVars.put("consent-id", consentId);
pathVars.put("authorisation-id", authorisationId);
UriComponents uri = UriComponentsBuilder.fromUri(mainLink)
.path("consents/{consent-id}/authorizations/{authorisation-id}")
.buildAndExpand(pathVars);
Verify if your authorization-id is correct
if the token has a type for example Bearer you must write so:
"Authorization": "Bearer rrdedzfdgf........."
and make sure that there is only one space between Bearer and the token
Often the problem comes from the browser locally;
if your site is online, save the part and deploy the last modifications of the site and make the test
otherwise if it is a mobile application test it on a smartphone and not a browser;
in case none of this works, do it with your backend, it works with this
I had a problem where the I would add an extra character to a password. And Insomnia(Or Postman) would return a JSON response from the server along with a 401 HTTP status code. But when I did the same thing inside a springboot app, when using catch(HttpServerErrorException e){System.out.prinln(e.getMessage());} the e.getMessage would have [no body]. I think that is a feature built in the HttpServerErrorException class where it doesn't provide the body for security purposes. Since whoever is requesting is not authorized they should not have access to it.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
HTTP GET with request body
I've read few discussions here which do not advocate sending content via HTTP GET. There are restrictions on the size of data that can be sent via clients (web browsers). And handling GET data also depends on servers. Please refer section Resources below.
However, I've been asked to test the possibility to send content via HTTP GET using RestTemplate. I refered few discussions on spring forum but they were not answered. (Please note sending data via http Post works fine). The discussion here suggests using POST instead.
dev env - JBoss AS 5.1, Spring 3.1.3
Client
#Test
public void testGetWithBody()
{
// acceptable media type
List<MediaType> acceptableMediaTypes = new ArrayList<MediaType>();
acceptableMediaTypes.add(MediaType.TEXT_PLAIN);
// header
HttpHeaders headers = new HttpHeaders();
headers.setAccept(acceptableMediaTypes);
// body
String body = "hello world";
HttpEntity<String> entity = new HttpEntity<String>(body, headers);
Map<String, Object> uriVariables = new HashMap<String, Object>();
uriVariables.put("id", "testFile");
// Send the request as GET
ResponseEntity<String> result = restTemplate.exchange(
"http://localhost:8080/WebApp/test/{id}/body",
HttpMethod.GET, entity, String.class, uriVariables);
Assert.assertNotNull(result.getBody());
}
Server #Controller
#RequestMapping(value = "/{id}/body", method = RequestMethod.GET)
public #ResponseBody
String testGetWithBody(#PathVariable String id,
#RequestBody String bodyContent)
{
return id + bodyContent;
}
The problem -
executing this test case returns 500 Internal Server Error. On debugging, I found that the controller is not hit.
Is it correct to understand that the RestTemplate provides the way to send data as request body, but the error occurs because the server could not handle the request body ?
If the request body sent via HTTP Get is not conventional why does RestTemplate provide the APIs to allow sending it ? Does this mean there are few servers capable of handling the Request body via GET ?
Resources - discussions on sending body via HTTP GET using RestTemplate at spring forum
http://forum.springsource.org/showthread.php?129510-Message-body-with-HTTP-GET&highlight=resttemplate+http+get
http://forum.springsource.org/showthread.php?94201-GET-method-on-RestTemplate-exchange-with-a-Body&highlight=resttemplate+http+get
Resources - General discussions on sending body via HTTP GET
get-with-request-body
is-this-statement-correct-http-get-method-always-has-no-message-body
get-or-post-when-reading-request-body
http-uri-get-limit
Is it correct to understand that the RestTemplate provides the way to send data as request body, but the error occurs because the server could not handle the request body ?
You can tell by looking at network traffic (does the request get sent with a request body and a GET method?) and at server logs (the 500 result you receive must have a server-side effect that gets logged, and if not, configure the server to do so).
If the request body sent via HTTP Get is not conventional why does RestTemplate provide the APIs to allow sending it ? Does this mean there are few servers capable of handling the Request body via GET ?
Because it is a generic class that also allows you to craft requests that can include a message body.
As stated in HTTP GET with request body:
In other words, any HTTP request message is allowed to contain a message body, and thus [a server] must parse messages with that in mind. Server semantics for GET, however, are restricted such that a body, if any, has no semantic meaning to the request. The requirements on parsing are separate from the requirements on method semantics.
A body on a GET cannot do anything semantically, because you are requesting a resource. It's like you tell the server: "Give me resource X, oh, and have some apples!". The server won't care about your apples and happily serve resource X - or throw an error because it doesn't like any offers in a request.
However, I've been asked to test the possibility to send content via HTTP GET
Please tell the one who requested this that this is a case that should not have to be tested, because no sensible implementation supports it.
Similar to the already existing question Apache HttpClient making multipart form post
want to produce a http request, holding a file and a key=val pair.
Currently the code looks like:
HttpPost post = new HttpPost("http://localhost/mainform.cgi/auto_config.htm");
HttpEntity ent = MultipartEntityBuilder.create()
.addTextBody("TYPE", "6",ContentType.TEXT_BINARY)
.addBinaryBody("upname", new File("factory.cfg"),ContentType.APPLICATION_OCTET_STREAM,"factory.cfg")
.build();
This is simply applied to HttpPost object as entity and passed to the client.
Which is sent to a linux-type device (blackbox) with a lighthttp service running. The problem is that when I send this request I do not see a response from the device(physical, and the HttpEntity always returns a default 200 OK).
Through Wireshark I've noticed two differences, on which i would really appreciate to get some help:
1. The multipart elements have an additional header(comparing to the original request) - Content-transfer-encoding, which i assume may be the reason of the fail.
2. Content length differs drastically.
So the first question would be - how to deal with the Encoding?
Found the point, on which it was failing. Needed this addition:
.addTextBody("TYPE", "6",ContentType.WILDCARD)
.setMode(HttpMultipartMode.BROWSER_COMPATIBLE).setCharset(Charset.forName("UTF-8"))