Spring - changing Content-type HTTP header - java

I am communicating with a JSON API using Robospice. This is how I set the headers for a POST request:
mHttpHeaders = new HttpHeaders();
mHttpHeaders.add("Content-Type", "application/json");
Log.d(Global.TAG, mHttpHeaders.toString());
The problem is that I get a header which looks like that: {Content-Type=[application/json]} where I need to send Content-Type:application/json (which seems to be the only header that my server accepts). I can't find any way to change it (tried with both add() and setContentType() methods), how do I do that?

You should try followings and it works for me. I'm using Spring rest template inside Robospice.
MediaType mediaType = new MediaType("application", "json");
List<MediaType> acceptableMediaTypes = new ArrayList<MediaType>();
acceptableMediaTypes.add(mediaType);
HttpHeaders headers = new HttpHeaders();
headers.setAccept(acceptableMediaTypes);

The output
{Content-Type=[application/json]}
you see in the Log statement is just the String returned by the toString() method, it's not the actual header sent. For example
public static void main(String[] args) throws Exception {
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Type", "application/json");
System.out.println(headers);
}
prints
{Content-Type=[application/json]}
If you are using the HttpClient and HttpRequestBase (HttpGet, HttpPost, etc.) correctly, the header will be sent just fine.

Related

How to send Gzip Request using RestTemplate?

I have the following code with large pojo (MyRequest) which I wanted to send in Gzip, but it's unable to hit the end-point that accept Gzip request. Am I creating Gzip request correctly? Do I need to send the pojo as a file?
MyRequest request = new MyRequest ();
HttpHeaders httpHeaders = HttpHeaders();
httpHeaders.add(HttpHeaders.CONTENT_ENCODING, "gzip");
httpHeaders.add(HttpHeaders.ACCEPT_ENCODING, "gzip");
httpHeaders.add(HttpHeaders.CONTENT_TYPE, "gzip");
HttpEntity<byte[]> entity = new HttpEntity<>(compress(request), headers);
ResponseEntity<MyResponse> response = restTemplate.postForEntity(url, entity, MyResponse.class);
public static Byte[] compress(byte[] body) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try (GZIPOutputStream gzipOutputStream = new GZIPOutputStream(baos)) {
gzipOutputStream.write(body);
}
return baos.toByteArray();
}
Kindly share an example of Gzip encoding using RestTemplate, thanks
accept-encoding: gzip, deflate, br
Is for http clients to make requests to a server and expect an http response that is:
content-encoding: gzip
To what you are doing see this answer: https://serverfault.com/a/56707

Problem with spring RestTemplate POST request

Trying to make a post call on one of our servers, but getting 400 BAD_REQUEST all the time
static void postUserToken()
{
final String url = "SERVER ADDRESS";
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
headers.setContentType(MediaType.APPLICATION_JSON);
MultiValueMap<String, String> requestBody= new LinkedMultiValueMap<>();
requestBody.add("userName", "TESTUSER");
requestBody.add("password", "TESTPASSWORD");
requestBody.add("auth", "secEnterprise");
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(requestBody, headers);
ResponseEntity<String> response = restTemplate.postForEntity(url, request, String.class );
System.out.println(response);
}
get request to the same address works, post request via Postman works fine with the same body and headers
what am I missing ?
EDIT
calls from postman
POST /api/call/ HTTP/1.1
Host: SEREVERADDRESS:6405
Content-Type: application/json
Accept: application/json
User-Agent: PostmanRuntime/7.15.0
Cache-Control: no-cache
Postman-Token: token1,token2
Host: SEREVERADDRESS:6405
accept-encoding: gzip, deflate
content-length: 92
Connection: keep-alive
cache-control: no-cache
{
"password": "PASSWORD",
"auth": "secEnterprise",
"userName": "USER"
}
in response I get an object like this {"token":"longtoken"}
You are using a MultiValueMap however the json you send from postman looks like a simple Map.
This will produce {"key1":["val1"]} instead of {"key1":"val1"}
The problem might be in the
headers.setContentType(MediaType.APPLICATION_JSON);
Try using headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); or convert your data to a proper JSON.
More on this: https://www.baeldung.com/rest-template (4.4. Submit Form Data)
As far as I understand the problem and since I do not know your rest call details, I provide below the approach you can try.
Remove the following line.
requestBody.add("auth", "secEnterprise");
Add the line
headers.setHeader("auth", "secEnterprise");
If you are using other version of Apache Http Client, you can use the following code snippet.
HttpPost httpPost = new HttpPost(url);
httpPost.addHeader("header-name" , "header-value");

How to make an Okhttp Request with "Content-type:application/x-www-form-urlencoded"?

I have an api requirement of Sending following parameters in header-
Content-Type - application/x-www-form-urlencoded
authKey- (Session token)
and following parameters in body(form day i.e key-value pair)
storeId -1
type -Product
CategoryId -324
But whenever I hit this api, I am always getting 401(UnAuthorized) error.
I have tried using MultipartRequest body and formBody, I know this is nothing to do with the body(Its the header where I need to send the Content-Type and authKey). Below is my code-
Request.Builder requestBuilder = new Request.Builder();
requestBuilder.addHeader("Content-Type", "application/x-www-form-urlencoded");
requestBuilder.addHeader("authKey",AppSharedPref.getTokenMobikul(context));
RequestBody formbody = new FormBody.Builder().add("CategoryId",bodyparms.get(0)).
add("type",bodyparms.get(1)).build();
requestBuilder.post(formbody);
The Same api is giving Response with retrofit library So how to achieve this using Okhttp.
Might this will help
FormBody.Builder formBuilder = new FormBody.Builder()
.add("key", "value");
// add more parameter as follow:
formBuilder.add("mobile", "9999999999");
RequestBody formBody = formBuilder.build();
Request request = new Request.Builder()
.url("https://www.hittheserver.com")
.post(formBody)
.build();

How to return TIFF image from remote api using multiple header parameters

I'm creating a spring application to access a remote API that returns a TIFF image. the api is expecting a few parameters send in the header. I'm attempting with the following code from examples I've found.. but when I return the ResponseEntity respond, it's of 0 length and the byte[] respond is null.
{Content-Length=[0], Content-Type=[application/octet-stream], Server=[Microsoft-IIS/7.5], X-Powered-By=[ASP.NET], Date=[Wed, 19 Aug 2015 15:14:17 GMT]}
List<HttpMessageConverter<?>> messageConverters = new ArrayList<HttpMessageConverter<?>>();
messageConverters.add(new ByteArrayHttpMessageConverter());
RestTemplate restTemplate = new RestTemplate(messageConverters);
HttpHeaders headers = new HttpHeaders();
headers.set("Accept", "application/octet-stream");
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl("http://webservices.imagestorehouse.com/GetData.svc/getDocs")
.queryParam("token", "a80d4978c12549dbafcd1922c1efdaa5")
.queryParam("company_id", "SW1112b")
.queryParam("document", "1" )
.queryParam("field_1", "2627594")
.queryParam("field_4", "028000");
HttpEntity<String> entity = new HttpEntity<String>(headers);
//ResponseEntity<byte[]> respond = restTemplate.execute(builder.build().encode().toUri(), HttpMethod.GET, entity, byte[].class);
byte[] respond = restTemplate.getForObject(builder.build().encode().toUri(), byte[].class);
You need to add few more parameters in response header.
header.setContentLength(respond.length);
//Also set content type accordingly
//header.setContentType(new MediaType("application", "xml"));

Making authenticated POST requests with Spring RestTemplate for Android

I have a RESTful API I'm trying to connect with via Android and RestTemplate. All requests to the API are authenticated with HTTP Authentication, through setting the headers of the HttpEntity and then using RestTemplate's exchange() method.
All GET requests work great this way, but I cannot figure out how to accomplish authenticated POST requests. postForObject and postForEntity handle POSTs, but have no easy way to set the Authentication headers.
So for GETs, this works great:
HttpAuthentication httpAuthentication = new HttpBasicAuthentication("username", "password");
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.setAuthorization(httpAuthentication);
HttpEntity<?> httpEntity = new HttpEntity<Object>(requestHeaders);
MyModel[] models = restTemplate.exchange("/api/url", HttpMethod.GET, httpEntity, MyModel[].class);
But POSTs apparently don't work with exchange() as it never sends the customized headers and I don't see how to set the request body using exchange().
What is the easiest way to make authenticated POST requests from RestTemplate?
Ok found the answer. exchange() is the best way. Oddly the HttpEntity class doesn't have a setBody() method (it has getBody()), but it is still possible to set the request body, via the constructor.
// Create the request body as a MultiValueMap
MultiValueMap<String, String> body = new LinkedMultiValueMap<String, String>();
body.add("field", "value");
// Note the body object as first parameter!
HttpEntity<?> httpEntity = new HttpEntity<Object>(body, requestHeaders);
ResponseEntity<MyModel> response = restTemplate.exchange("/api/url", HttpMethod.POST, httpEntity, MyModel.class);
Slightly different approach:
MultiValueMap<String, String> headers = new LinkedMultiValueMap<String, String>();
headers.add("HeaderName", "value");
headers.add("Content-Type", "application/json");
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
HttpEntity<ObjectToPass> request = new HttpEntity<ObjectToPass>(objectToPass, headers);
restTemplate.postForObject(url, request, ClassWhateverYourControllerReturns.class);
I was recently dealing with an issue when I was trying to get past authentication while making a REST call from Java, and while the answers in this thread (and other threads) helped, there was still a bit of trial and error involved in getting it working.
What worked for me was encoding credentials in Base64 and adding them as Basic Authorization headers. I then added them as an HttpEntity to restTemplate.postForEntity, which gave me the response I needed.
Here's the class I wrote for this in full (extending RestTemplate):
public class AuthorizedRestTemplate extends RestTemplate{
private String username;
private String password;
public AuthorizedRestTemplate(String username, String password){
this.username = username;
this.password = password;
}
public String getForObject(String url, Object... urlVariables){
return authorizedRestCall(this, url, urlVariables);
}
private String authorizedRestCall(RestTemplate restTemplate,
String url, Object... urlVariables){
HttpEntity<String> request = getRequest();
ResponseEntity<String> entity = restTemplate.postForEntity(url,
request, String.class, urlVariables);
return entity.getBody();
}
private HttpEntity<String> getRequest(){
HttpHeaders headers = new HttpHeaders();
headers.add("Authorization", "Basic " + getBase64Credentials());
return new HttpEntity<String>(headers);
}
private String getBase64Credentials(){
String plainCreds = username + ":" + password;
byte[] plainCredsBytes = plainCreds.getBytes();
byte[] base64CredsBytes = Base64.encodeBase64(plainCredsBytes);
return new String(base64CredsBytes);
}
}
Very useful
I had a slightly different scenario where I the request xml was itself the body of the POST and not a param. For that the following code can be used - Posting as an answer just in case anyone else having similar issue will benefit.
final HttpHeaders headers = new HttpHeaders();
headers.add("header1", "9998");
headers.add("username", "xxxxx");
headers.add("password", "xxxxx");
headers.add("header2", "yyyyyy");
headers.add("header3", "zzzzz");
headers.setContentType(MediaType.APPLICATION_XML);
headers.setAccept(Arrays.asList(MediaType.APPLICATION_XML));
final HttpEntity<MyXmlbeansRequestDocument> httpEntity = new HttpEntity<MyXmlbeansRequestDocument>(
MyXmlbeansRequestDocument.Factory.parse(request), headers);
final ResponseEntity<MyXmlbeansResponseDocument> responseEntity = restTemplate.exchange(url, HttpMethod.POST, httpEntity,MyXmlbeansResponseDocument.class);
log.info(responseEntity.getBody());

Categories