Reputation: 1019
Is there a way to add a query parameter to every HTTP request performed by RestTemplate
in Spring?
The Atlassian API uses the query parameter os_authType
to dictate the authentication method so I'd like to append ?os_authtype=basic
to every request without specifying it all over my code.
Code
@Service
public class MyService {
private RestTemplate restTemplate;
@Autowired
public MyService(RestTemplateBuilder restTemplateBuilder,
@Value("${api.username}") final String username, @Value("${api.password}") final String password, @Value("${api.url}") final String url ) {
restTemplate = restTemplateBuilder
.basicAuthorization(username, password)
.rootUri(url)
.build();
}
public ResponseEntity<String> getApplicationData() {
ResponseEntity<String> response
= restTemplate.getForEntity("/demo?os_authType=basic", String.class);
return response;
}
}
Upvotes: 2
Views: 4412
Reputation: 713
Using Spring Boot 3.2.x
@Service
public class MyService {
private final RestTemplate restTemplate;
public MyService(
RestTemplateBuilder restTemplateBuilder,
@Value("${api.username}") final String username,
@Value("${api.password}") final String password,
@Value("${api.url}") final String url) {
// inject "os_authType" query parameter in every request
ClientHttpRequestInterceptor interceptor = (request, body, execution) -> {
HttpRequest modifiedRequest = new HttpRequestWrapper(request) {
@Override
public URI getURI() {
return ForwardedHeaderUtils.adaptFromForwardedHeaders(request.getURI(), request.getHeaders())
.queryParam("os_authType", "basic")
.build(true)
.toUri();
}
};
return execution.execute(modifiedRequest, body);
};
// consider using the new RestClient instead RestTemplate in Srping Boot 3.2.x
restTemplate = restTemplateBuilder
.interceptors(interceptor)
.basicAuthentication(username, password)
.rootUri(url)
.build();
}
}
Upvotes: 0
Reputation: 3766
For the ones interested in logic to add a query parameter, as HttpRequest is immutable a wrapper class is needed.
class RequestWrapper {
private final HttpRequest original;
private final URI newUriWithParam;
...
public HttpMethod getMethod() { return this.original.method }
public URI getURI() { return newUriWithParam }
}
Then in your ClientHttpRequestInterceptor
you can do something like
public ClientHttpResponse intercept(
request: HttpRequest,
body: ByteArray,
execution: ClientHttpRequestExecution
) {
URI uri = UriComponentsBuilder.fromUri(request.uri).queryParam("new-param", "param value").build().toUri();
return execution.execute(RequestWrapper(request, uri), body);
}
Update
Since spring 3.1 wrapper class org.springframework.http.client.support.HttpRequestWrapper
is available in spring-web
Upvotes: 5
Reputation: 806
You can write custom RequestInterceptor that implements ClientHttpRequestInterceptor
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
public class AtlassianAuthInterceptor implements ClientHttpRequestInterceptor {
@Override
public ClientHttpResponse intercept(
HttpRequest request, byte[] body, ClientHttpRequestExecution execution)
throws IOException {
// logic to check if request has query parameter else add it
return execution.execute(request, body);
}
}
Now we need to configure our RestTemplate
to use it
import java.util.Collections;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.web.client.RestTemplate;
@Configuration
public class MyAppConfig {
@Bean
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate(clientHttpRequestFactory());
restTemplate.setInterceptors(Collections.singletonList(new AtlassianAuthInterceptor()));
return restTemplate;
}
}
Upvotes: 4