How to Send an HTTP Header With Every Request With Spring RestTemplate

 

In Know Which Apps Are Hitting Your Web Service, I showed how to write a servlet filter that enforces the existence of a special HTTP request header.

From a client perspective, it would be nice to send this header automatically, instead of having to set the header manually with every request. This post shows how we can use Spring’s RestTemplate and ClientHttpRequestInterceptor to accomplish this.

First we need to implement a ClientHttpRequestInterceptor:

package com.myapp.connector;

import java.io.IOException;
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 XUserAgentInterceptor implements ClientHttpRequestInterceptor {

    @Override
    public ClientHttpResponse intercept(
            HttpRequest request, byte[] body, ClientHttpRequestExecution execution)
            throws IOException {

        HttpHeaders headers = request.getHeaders();
        headers.add("X-User-Agent", "My App v2.1");
        return execution.execute(request, body);
    }
}

Now we need to configure our RestTemplate to use it. Here I’m using Spring’s Java-based configuration, but you can implement the same thing with the XML-based configuration too:

package com.myapp;

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;
import com.myapp.connector.XUserAgentInterceptor;

@Configuration
public class MyAppConfig {

    @Bean
    public RestTemplate restTemplate() {
        RestTemplate restTemplate = new RestTemplate(clientHttpRequestFactory());
        restTemplate.setInterceptors(Collections.singletonList(new XUserAgentInterceptor()));
        return restTemplate;
    }
}

With this configuration, any requests you make through the RestTemplate will automatically carry the desired HTTP request header.

To learn how to set request timeouts automatically, see my post How to Set HTTP Request Timeouts With Spring RestTemplate.

http://springinpractice.com/2013/10/27/how-to-send-an-http-header-with-every-request-with-spring-resttemplate/

 

When creating a web service, it’s often useful to know which apps are hitting it. I don’t mean which users, but instead which apps. The reason is that you may want to coordinate with some other team on something. For example, maybe the team is being too aggressive about request retries, or maybe you want to alert the team to a change in the API. Whatever the reason, it’s good to know which apps are calling your service.

HTTP has a User-Agent header that can help here. One possible approach is to make that a required header. Unfortunately, this approach isn’t ideal. The problem is that HTTP client libraries usually set that header automatically. So if the client application forgets to set the header explicitly, you end up with user agents like Apache-HttpClient/release (java 1.5), which isn’t much help at all.

An approach I like better is to define a custom header and make it required. I use X-User-Agent, since it really is a user agent we’re talking about here.

Here’s how to implement this with a servlet filter. No Spring involved here at all; it’s just servlet stuff.

package com.myapp.web.filter;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class XUserAgentFilter implements Filter {
    private static final String X_USER_AGENT = "X-User-Agent";

    private String errorJson;

    public XUserAgentFilter() {
        String message =
            "HTTP header '" + X_USER_AGENT + "' is required. Please set it to your application name so we know " +
            "who to contact if there's an issue.";
        this.errorJson = "{ " + wrap("message") + " : " + wrap(message) + " }";
    }

    private String wrap(String s) { return "\"" + s + "\""; }

    @Override
    public void init(FilterConfig config) throws ServletException { }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {

        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;

        if (httpRequest.getHeader(X_USER_AGENT) == null) {//不走chain.doFilter即结束
            httpResponse.setStatus(422);
            httpResponse.getWriter().println(errorJson);
        } else {
            chain.doFilter(request, response);
        }
    }

    @Override
    public void destroy() { }
}

Of course, you need to configure this filter and a filter mapping in your web.xml file.

In the next post I’ll show you how to set up your Spring RestTemplate to send the X-User-Agent header with each request automatically.

http://springinpractice.com/2013/10/25/know-which-apps-are-hitting-your-web-service/

In How to Send an HTTP Header With Every Request With Spring RestTemplate, we looked at how to send a given HTTP header automatically with every request. Here we’ll do something similar, which is to automatically apply a request timeout to every request.

Here’s the Java-based configuration for this technique:

package com.myapp;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

@Configuration
public class MyAppConfig {

    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate(clientHttpRequestFactory());
    }

    private ClientHttpRequestFactory clientHttpRequestFactory() {
        HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
        factory.setReadTimeout(2000);
        factory.setConnectTimeout(2000);
        return factory;
    }
}

The XML-based configuration is this:

<bean class="org.springframework.web.client.RestTemplate">
    <constructor-arg>
        <bean class="org.springframework.http.client.HttpComponentsClientHttpRequestFactory"
            p:readTimeout="2000"
            p:connectTimeout="2000" />
    </constructor-arg>
</bean>

http://springinpractice.com/2013/10/27/how-to-set-http-request-timeouts-with-spring-resttemplate/

Basic Auth:

// Set the username and password for creating a Basic Auth request
HttpAuthentication authHeader = new HttpBasicAuthentication(username, password);
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.setAuthorization(authHeader);
HttpEntity<?> requestEntity = new HttpEntity<Object>(requestHeaders);

// Create a new RestTemplate instance
RestTemplate restTemplate = new RestTemplate();

// Add the String message converter
restTemplate.getMessageConverters().add(new StringHttpMessageConverter());

try {
    // Make the HTTP GET request to the Basic Auth protected URL
    ResponseEntity<Message> response = restTemplate.exchange(url, HttpMethod.GET, requestEntity, String.class);
    return response.getBody();
} catch (HttpClientErrorException e) {
    Log.e(TAG, e.getLocalizedMessage(), e);
    // Handle 401 Unauthorized response
}

http://docs.spring.io/autorepo/docs/spring-android/1.0.x/reference/html/rest-template.html

 

时间: 2024-08-31 20:40:28

How to Send an HTTP Header With Every Request With Spring RestTemplate的相关文章

PHP开发环境搭建详细教程

     首先你需要安装Apache Server,这里以当前最新版Apache Server2.4为例进行说明,可惜官网并没有提供最新版的msi安装包,连编译后的binary二进制压缩包都没提供,不过我已经编译并上传到我的百度网盘,下载地址如下:       Apache Server2.4最新版安装包   下载下来后直接解压到任意目录,如图:  然后你需要安装Apache Server系统服务,先cd 到apacher server2.4/bin下,然后执行如下命令: Java代码   ht

AJAX实例教程:异步调用的程序

文章简介:Ajax(Asynchronous JavaScript and XML),使用户在使用Web程序时,不用在来来回回的Post了,可以近乎实时的从客户端收到服务器返回的信息,而无需刷新,极大的非富了用户的操作体验. Ajax(Asynchronous JavaScript and XML),使用户在使用Web程序时,不用在来来回回的Post了,可以近乎实时的从客户端收到服务器返回的信息,而无需刷新,极大的非富了用户的操作体验. XMLHttpRequest对象是Ajax的核心对象 不同

Web开发帮助:学习http headers的方方面

无论是做前端还是做后端,都会不时与HTTP Headers打交道,了解它无疑对Web开发有莫大帮助.这篇文章就让我一起来学习下http headers的方方面. 什么是HTTP Headers HTTP是"Hypertext Transfer Protocol"的所写,整个万维网都在使用这种协议,几乎你在浏览器里看到的大部分内容都是通过http协议来传输的,比如这篇文章. HTTP Headers是HTTP请求和相应的核心,它承载了关于客户端浏览器,请求页面,服务器等相关的信息. 示例

PHP下载远程图片并保存到本地方法总结_php实例

1.获取远程文件大小及信息的函数 function getFileSize($url){ $url = parse_url($url); if($fp = @fsockopen($url['host'],empty($url['port'])?80:$url['port'],$error)){ fputs($fp,"GET ".(empty($url['path'])?'/':$url['path'])." HTTP/1.1\r\n"); fputs($fp,&qu

【原创】rabbitmq-c源码分析之amqp_socket.c

     走读 amqp_socket.c 源码,发现若干值得注意的细节: [amqp_open_socket ] 在 amqp_open_socket 函数中通过 getaddrinfo 函数进行域名解析可能会产生阻塞.其中参数指定了 ? 1 2 3 4 5 6 struct addrinfo hint; ... hint.ai_family = PF_UNSPEC; /* PF_INET or PF_INET6 */ hint.ai_socktype = SOCK_STREAM; hint.

Web 站点提速的最佳实践(Best Practices for Speeding Up Your Web Site)

Web 站点提速的最佳实践(Best Practices for Speeding Up Your Web Site) 太阳火神的美丽人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致"创作公用协议 转载请保留此句:太阳火神的美丽人生 -  本博客专注于 敏捷开发及移动和物联设备研究:iOS.Android.Html5.Arduino.pcDuino,否则,出自本博客的文章拒绝转载或再转载,谢谢合作. Best Practice

Spring MVC @RequestMapping Annotation Example with Controller, Methods, Headers, Params, @RequestPar

Spring MVC @RequestMapping Annotation Example with Controller, Methods, Headers, Params, @RequestParam, @PathVariable Pankaj July 4, 2014 Spring @RequestMapping is one of the most widely used Spring MVC annotation.org.springframework.web.bind.annotat

【ASP.NET Web API教程】6.3 内容协商

原文:[ASP.NET Web API教程]6.3 内容协商 本文是Web API系列教程的第6.3小节 6.3 Content Negotiation 6.3 内容协商 摘自:http://www.asp.net/web-api/overview/formats-and-model-binding/content-negotiation By Mike Wasson|May 20, 2012 作者:Mike Wasson | 日期:2012-3-20 This article describe

Activating Browser Modes with Doctype

原文地址:https://hsivonen.fi/doctype/   In order to deal both with content written according to Web standards and with content written according to legacy practices that were prevalent in the late 1990s, today's Web browsers implement various engine mode