Add Query Parameter to Every REST Request using Spring RestTemplate
Asked Answered
N

3

2

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;    
    }
}
Nakashima answered 20/3, 2018 at 21:28 Comment(1)
Doesnt rest template have parameters?Ytterbia
P
4

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;
    }
}
Perceptive answered 21/3, 2018 at 1:6 Comment(0)
W
5

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

Wixted answered 19/11, 2019 at 15:56 Comment(1)
there is already a Wrapper class in spring libraries. org.springframework.http.client.support.HttpRequestWrapperParishioner
P
4

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;
    }
}
Perceptive answered 21/3, 2018 at 1:6 Comment(0)
J
0

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();
    }
}
Jest answered 3/3, 2024 at 11:56 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.