HTTP POST is not working with Webclient but working with RestTemplate - http-post

I am getting Error while making POST calls with webclient as below
org.springframework.web.reactive.function.client.WebClientRequestException: An existing connection was forcibly closed by the remote host; nested exception is java.io.IOException: An existing connection was forcibly closed by the remote host
But same request working fine with restetemplate, both code as below
RestTemplate restTemplate = new RestTemplate();
final String baseUrl = "https://somehost/rest/v1/leads.json";
URI uri = null;
try {
uri = new URI(baseUrl);
} catch (URISyntaxException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", "Bearer 39131a98-7a53-497f-8e04-ca08c35a7775:sj");
HttpEntity<Lead> request = new HttpEntity<>(convertToLead(consent), headers);
ResponseEntity<LeadResponse> result = restTemplate.postForEntity(uri, request, LeadResponse.class);
System.out.println(result.getBody().toString());
Failed with Webclient code
ResponseEntity<Response> leadResponse = marketoWebClient.post().uri("/leads.json").bodyValue(lead).exchange()
.flatMap(clientResponse -> clientResponse.toEntity(LeadResponse.class).doOnSuccess(response -> {
if (clientResponse.statusCode().isError()) {
logger.debug("Error Details = {} {}", clientResponse.statusCode(), response);
}
})).block();

Related

How to receive an InputStream as #RequestBody in a #PostMapping method in SpringBoot

I am sending an ArrayList object through WebClient in an HTTP POST request after converting it into an InputStream:
List<MyObject> myObjectList = // some data
ByteArrayOutputStream byteOutStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutStream = new ObjectOutputStream(byteOutStream);
objectOutStream.writeObject(myObjectList );
objectOutStream.flush();
objectOutStream.close();
byte[] byteArray = byteOutStream.toByteArray();
InputStream inputStream = new ByteArrayInputStream(byteArray);
WebClient client = WebClient.builder()
.baseUrl(URL)
.exchangeStrategies(ExchangeStrategies.builder()
.codecs(configure -> configure.defaultCodecs().maxInMemorySize(64 * 1024 * 1024))
.build())
.build();
Mono<HttpStatus> response = client
.post()
.uri(URI)
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_OCTET_STREAM_VALUE)
.body(BodyInserters.fromResource(new InputStreamResource(inputStream)))
.exchangeToMono(clientResponse -> Mono.just(clientResponse.statusCode()));
HttpStatus status = response.block();
And at the server side, I am handling this request this way:
#PostMapping(value = "/data", consumes = MediaType.APPLICATION_OCTET_STREAM_VALUE)
public ResponseEntity<Void> saveData(#RequestBody InputStream inputStream) {
try (ObjectInputStream objectInputStream = new ObjectInputStream(inputStream)) {
List<MyObject> myObjectList = (List<MyObject>) objectInputStream.readObject();
LOGGER.info("Payload received : {}", myObjectList);
return new ResponseEntity<>(HttpStatus.OK);
} catch (Exception e) {
LOGGER.error(e.getMessage());
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
}
But after implementing this, I am getting this error:
[org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/octet-stream;charset=UTF-8' not supported]
PS: I am converting the ArrayList into an InputStream due to it's large size which is causing java.lang.OutOfMemoryError: Direct buffer memory
First, I tried sending the entire List<> in a request but got OutOfMemoryError. Secondly, using the streaming approach I am getting this error
[org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/octet-stream;charset=UTF-8' not supported]

Jetty httpclient add proxy socks4

When i'm trying to send request via jetty httpClient with new Socks4Proxy(socksHost, socksPort); received: java.util.concurrent.ExecutionException: java.io.IOException: SOCKS4 tunnel failed with code 91
HttpClient httpClient = new HttpClient();
ProxyConfiguration proxyConfig = httpClient.getProxyConfiguration();
Socks4Proxy proxy = new Socks4Proxy(socksHost, socksPort);
proxyConfig.getProxies().add(proxy);
httpClient.start();
String url = config.getProperty(stringUrl);
Request request = httpClient.newRequest(url);
request.method(HttpMethod.GET);
request.onResponseContent(new BufferingResponseListener() {
#Override
public void onComplete(Result result) {
String s = getContentAsString();
logger.debug("Received http response message: '{}', status: '{}'", s, result.getResponse().getReason());
}
});
try {
request.send();
} catch (Exception e) {
throw new RuntimeException(e);
}
Per https://www.openssh.com/txt/socks4.protocol
Your 91 status means that request was rejected or failed. The user or source program is not authorized to access the proxy server.
Perhaps your SOCKS4 proxy has an authentication requirement.

Spring RestTemplate Connection Timeout

Any help or hint would be greatly appreciated it.
I tried the below RestTemplate code in Eclipse and Intellij and I get the same connection timeout error. If I run it on a browser I am able to connect.
enter image description here
org.springframework.web.client.ResourceAccessException: I/O error on GET request for "https://registry-relationship-dev.api.non-prod-uw2.hponecloud.io/ocrel-registry/v2/node/sub.node.0025s": Connection timed out: connect; nested exception is java.net.ConnectException: Connection timed out: connect
try {
String tempUrl = registryUrl;
if (roleInput.getNodeId() != null) {
tempUrl = tempUrl + roleInput.getNodeId();
}
URI uri = new URI(tempUrl);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("Authorization",auth);
headers.set("Content-Type","application/json");
HttpEntity<String> entity = new HttpEntity<String>("parameters",headers);
RestTemplate restTemplate = new RestTemplate();
// ResponseEntity<String> response = restTemplate.exchange(tempUrl,HttpMethod.GET, entity,String.class);
ResponseEntity<NodeModel> response1 = restTemplate.exchange(tempUrl,HttpMethod.GET, entity,NodeModel.class);
NodeModel response = restTemplate.getForObject("https://registry-relationship-dev.api.non-prod-uw2.hponecloud.io/ocrel-registry/v2/node/sub.node.0025s",NodeModel.class);
System.out.println("response from registry:"+response);
}
log.info("createRole,After call authLibService.validateToken(auth):"+auth);
} catch (Exception e) {
log.error("Failed to check permission, createRole getMessage error: {}", e.getMessage());
log.error("Failed to check permission, createRole getStackTrace error: {}", e.getStackTrace());
return new ResponseEntity<>(HttpStatus.UNAUTHORIZED);
}

Spring boot RestTemplate upload file to SharePoint online but file is corrupted

There is a RestController and I try to upload a MultiPartFile to SharePointOnline using, the SharePoint REST API I'm also using proxy due to corporate restrictions.
#Override
public ResponseEntity uploadFile(MultipartFile file) throws ApiException, IOException {
RestTemplate restTemplate = createBasicRestTemplate();
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
body.add("file",file.getResource());
HttpHeaders header = new HttpHeaders();
header.setContentType(MediaType.MULTIPART_FORM_DATA);
HttpEntity<MultiValueMap<String, Object>> uploadBodyEntity = new HttpEntity<>(body, header);
ResponseEntity<String> response = restTemplate.exchange(BASE_URL, HttpMethod.POST,
uploadBodyEntity, String.class);
return response;
}
public RestTemplate createBasicRestTemplate() {
RestTemplate restTemplate = new RestTemplateBuilder(new ProxyCustomizer()).build();
return restTemplate;
}
#Override
public void customize(RestTemplate restTemplate) {
HttpHost proxy = new HttpHost(PROXY_HOST, PROXY_PORT);
HttpClient httpClient = HttpClientBuilder.create()
.setRoutePlanner(new DefaultProxyRoutePlanner(proxy) {
#Override
public HttpHost determineProxy(HttpHost target, HttpRequest request, HttpContext context) throws HttpException {
return super.determineProxy(target, request, context);
}
})
.build();
restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory(httpClient));
}
The file upload is success, but it's cannot be opened. For example if upload a txt it will looks like this:
--raF_ORlUJptia2_av7ppLBeeMcGf5BUr
Content-Disposition: form-data; name="file"; filename="test.txt"
Content-Type: text/plain
Content-Length: 159
--38dc5323d6b92b5c14c33fade0178306
Content-Disposition: form-data; name="file"; filename="test.txt"
blablalblalalal
--38dc5323d6b92b5c14c33fade0178306--
--raF_ORlUJptia2_av7ppLBeeMcGf5BUr--
If I upload an xlsx it's simply just not open, it shows 'File Format and Extension Don't Match' error.
I try to convert the MultiPartFile to simple File with this method:
public File convertFile(MultipartFile file) {
File convFile = new File(file.getOriginalFilename());
try {
convFile.createNewFile();
FileOutputStream fos = new FileOutputStream(convFile);
fos.write(file.getBytes());
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
return convFile;
}
and change the controller to:
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
body.add("file",convertFile(file));
But the same thing happens.
How can I upload file with RestTemplate?
This is a sample request to the SharePoint REST API and based on documentation the endpoint should receive a array buffer
POST https://{site_url}/_api/web/GetFolderByServerRelativeUrl('/Folder Name')/Files/add(url='a.txt',overwrite=true)
Authorization: "Bearer " + accessToken
Content-Length: {length of request body as integer}
X-RequestDigest: "{form_digest_value}"
"Contents of file"
This is what i can see in the https log: http log
Solution was to remove MultiValueMap and replace with:
HttpEntity<byte[]> entity = new HttpEntity<>(file.getBytes(), spoHelperService.createAuthHeader(authToken));
ResponseEntity<SpoUploadResponse> response = restTemplate.exchange(uploadFileUrl, HttpMethod.POST,
entity, SpoUploadResponse.class);

Handle HttpClientErrorException$BadRequest: 400 Bad Request in Cucumber RestTemplate

Hi I have written a Cucumber test case where i send a POST request with an XML body, output of that request is 400 Error with an XML body, which is expected and when i throw the request i get that too, but what i get is below:
org.springframework.web.client.HttpClientErrorException$BadRequest: 400 Bad Request
at org.springframework.web.client.HttpClientErrorException.create(HttpClientErrorException.java:79)
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:97)
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:79)
at org.springframework.web.client.ResponseErrorHandler.handleError(ResponseErrorHandler.java:63)
at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:777)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:735)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:709)
at org.springframework.web.client.RestTemplate.postForEntity(RestTemplate.java:462)
at uk.co.argos.services.order.StepDefinations.TestMethods.POSTrestTemplatewithXML(TestMethods.java:147)
at uk.co.argos.services.order.StepDefinations.StepDefs.user_hits_the_getSlot_request_with_OrderEnricher_with_and_and(StepDefs.java:118)
at ✽.Given User hits the getSlot request with OrderEnricher with "2020-40-32" and "150" and "MK92NW"(OrderEnricher_Negative.feature:5)
And my test step failes with bad request, But ideally that is my expected and i want to pass my test step & scenario, not sure how should i handle it, i have tried applying multiple things. Can anyone help please?
public static ResponseEntity<String> POSTrestTemplatewithXML(URI uri, String XMLforPOST){
ResponseEntity<String> responseEntity = null;
try {
RestTemplate restTemplate=new RestTemplate();
List<HttpMessageConverter<?>> messageConverters=new ArrayList<HttpMessageConverter<?>>();
messageConverters.add(new StringHttpMessageConverter());
restTemplate.setMessageConverters(messageConverters);
HttpHeaders headers=new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_XML);
HttpEntity<String> request=new HttpEntity<String>(XMLforPOST, headers);
responseEntity=restTemplate.postForEntity(uri, request, String.class);
}
catch (Exception e){
System.out.println("RESPONSE-" +responseEntity);
byte[] bytes = ((HttpClientErrorException.BadRequest)e).getResponseBodyAsByteArray();
assertTrue(true);
//Convert byte[] to String
String s = new String(bytes);
System.out.println(s);
e.printStackTrace();
}
return responseEntity;
}
Please update your catch method like following :
try{
//your code
} catch (HttpClientErrorException e){
//your code
}

Resources