How to change response body in intercept (Using retrofit 2) - java

I read thousand of answers and try to a lot of way but doesn't work.
I really need to change response body when get "401". Because server response is different from other general response when unauthorized.
I'm using retrofit 2. To catch response i'm using Interceptor:
Request original = chain.request();
Request.Builder requestBuilder = original.newBuilder()
.header("authorization", getAccessToken(context));
Request request = requestBuilder.build();
Response response= chain.proceed(request);
if (response.code()==401) {
MediaType contentType = response.body().contentType();
ResponseBody body = ResponseBody.create(contentType, CommonFunctions.getUnAuthorizedJson(context).toString());
return response.newBuilder().body(body).build();
}else{
return response;
}
But still body doesn't change on client.enque method.

You can change body in this way, but Retrofit will eventually see 401 and throw HttpException with standart message, what can be misleading
check that you get your body right:
val errorConverter: Converter<ResponseBody, ErrorResponse> =
retrofit.responseBodyConverter(
ErrorResponse::class.java,
emptyArray()
)
val errorResponse = httpException
.response()
?.errorBody()
?.let (errorConverter::convert)

Related

MockServer unexpectedly responds with empty body

Let's see a test, which is using MockServer (org.mock-server:mockserver-netty:5.10.0) for mocking responses.
It is expected that the response body will be equal to string "something".
Nevertheless, this test fails, because the response body is an empty string.
#Test
void test1() throws Exception {
var server = ClientAndServer.startClientAndServer(9001);
server
.when(
request().withMethod("POST").withPath("/checks/"),
exactly(1)
)
.respond(
response()
.withBody("\"something\"")
.withStatusCode(205)
.withHeader("Content-Type", "application/json")
);
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("http://localhost:9001/checks/"))
.POST(BodyPublishers.noBody())
.build();
HttpResponse<String> response =
HttpClient.newHttpClient().send(request, BodyHandlers.ofString());
assertEquals(205, response.statusCode());
assertEquals("something", response.body()); // fails
}
How to make the response body be equal to the string provided in response().withBody(...)?
The problem is on the client side. It drops content.
Why!?
Because, HTTP 205 is RESET_CONTENT.
This status was chosen accidentally for test as "somenthing different from HTTP 200", and unfortunately caused this behaviour.
Looks like it is very popular "accidental" mistake (i.e. here), although it is strictly in accordance with the HTTP spec.

Okhttp3: Need help to use HeaderInterceptor

I would like to use a global header for all my requests. Therefore I have implemented the following class:
public class HeaderInterceptor {
public Response intercept(Chain chain) throws IOException {
Request request = chain.request()
.newBuilder()
.method("GET", null)
.addHeader("Accept", "application/json")
.addHeader("Basic ", "abcdefghi123456789")
.build();
Response response = chain.proceed(request);
return response;
}
}
Now I would like to do the following in the main()-method:
public static void main(String[] args) throws Exception {
OkHttpClient httpClient = new OkHttpClient.Builder().addInterceptor(MyInterceptor).build();
Request reqAllProjects = new Request.Builder()
.url("https://example.com/projects")
.build();
Response resAllProjects = httpClient.newCall(reqAllProjects).execute();
String responseData = resAllProjects.body().string();
System.out.println(responseData);
}
I'm not sure now how to use my HeaderInterceptor. I guess I'll have to enter it here, right?
OkHttpClient httpClient = new OkHttpClient.Builder().addInterceptor(??MyInterceptor??).build();
I tried something like this: addInterceptor(HeaderInterceptor.intercept()) but this is not working...
Can someone help me please? And does the rest of it look fine? Many thanks in advance!
The interceptor class that you have created doesn't seem to be implementing the Interceptor interface. You need to implement as below
public class HeaderInterceptor implements Interceptor {
#Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request request = chain.request()
.newBuilder()
.addHeader("Accept", "application/json")
.addHeader("Basic ", "abcdefghi123456789")
.build();
Response response = chain.proceed(request);
return response;
}
}
Do note that you should not be modifying the method and body of the request as .method("GET", null) unless you actually need so, as it can result in all the HTTP requests made by the client to make GET requests with null body.
Then add the interceptor while building the client as below
OkHttpClient httpClient = new OkHttpClient.Builder()
.addInterceptor(new HeaderInterceptor()).build();
Have a look at the OkHttp documentation for more info.
Have you checked this question : Okhttp3: Add global header to all requests error
It should be something like
.addInterceptor(new Interceptor())

Unable to set Test.APIKeyAuthToken

This is my code:
public static final String API_TOKEN = "safasfasdfesareasdadasd";
public static final String APIKeyAuthToken = "Auth-Token";
But the Auth-Token is not being found in the header request.
public Response intercept(Chain chain) throws IOException {
Request original = chain.request();
Request.Builder requestBuilder = original.newBuilder()
.addHeader("Accept", "application/json")
.addHeader("Content-Type", "application/json");
requestBuilder.addHeader(Test.APIKeyAuthToken, Test.API_TOKEN);
Request request = requestBuilder.build();
return chain.proceed(request);
}
Despite it is rather unclear which API you are even talking about - and what you might mean with "not working" (this is not an error description at all) ...the HTTP header probably should look alike:
.addHeader("Authorization", API_TOKEN)
Just see the API documentation, which string-format is actually being expected... because "not working" might possibly mean, just sending some random header, which the API doesn't accept.

Content type : "Application/Json" issue with retrofit 2.2 while calling cake php apis

My Api is accepting Content-Type application/json as headers. I set Header perfectly as mentioned in Retrofit Docs.
#Headers("Content-Type: application/json")
#POST("user/classes")
Call<playlist> addToPlaylist(#Body PlaylistParm parm);
I also tried by setting content type in authentication interceptor class:
public class AuthenticationInterceptor implements Interceptor {
private String authToken;
public AuthenticationInterceptor(String token) {
this.authToken = token;
}
#Override
public Response intercept(Chain chain) throws IOException {
Request original = chain.request();
Request.Builder builder = original.newBuilder()
.addHeader("Content-type","application/json")
.addHeader("Authorization", authToken);
Request request = builder.build();
return chain.proceed(request);
}
}
But in Request Log it is Returning Content-Type txt/html.So how i should fix this issue? This api works fine in POSTMAN
I tried with all possible ways but it's not working with cake php web services.
Any help would be appreciated.

org.springframework.web.client.HttpClientErrorException: 415 null(Spring Resttemplate)

I try to get list of entity with using rest template, but I get 415 error in line:
ResponseEntity<List<ResponseOrderDto>> responseEntity = rest.exchange
My implementation:
RestTemplate rest = new RestTemplate();
rest.getInterceptors().add((request, body, execution) -> {
ClientHttpResponse response = execution.execute(request,body);
response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
response.getHeaders().add("Bearer", contentToken);
return response;
});
ResponseEntity<List<ResponseOrderDto>> responseEntity = rest.exchange(
ORDER_SERVICE_URL + "/by-user",
HttpMethod.GET,
null,
new ParameterizedTypeReference<List<ResponseOrderDto>>() {
});
How fix this error?
415 means unsupported content type, so the Content-type header is not correctly set.
Based on your code, I think that the request needs JSON Content-Type header, but you set the content-type header on the response instead of the request.
Change your interceptor to be something like this:
rest.getInterceptors().add((request, body, execution) -> {
request.getHeaders().setContentType(MediaType.APPLICATION_JSON);
request.getHeaders().add("Bearer", contentToken);
ClientHttpResponse response = execution.execute(request, body);
return response;
});
To set the headers at the right time to the request

Categories