首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用springframework/spring的RestTemplate实现Firebase远程Config REST中的"etag“?

如何使用springframework/spring的RestTemplate实现Firebase远程Config REST中的"etag“?
EN

Stack Overflow用户
提问于 2019-11-11 13:27:34
回答 1查看 690关注 0票数 0

为了学习的目的,我在一个Android应用程序的spring引导服务器中实现了firebase远程配置rest。我的春季引导版本是2.1.7.RELEASE,我正在尝试获取etag值,这样我就可以从服务器端更新键&值,而无需使用firebase控制台。根据这个链接,我能够通过httpconnection获得etag。但是,每当我使用RestTemplate时,我都无法得到etag,我得到的只是

这是build.gradle文件

代码语言:javascript
复制
buildscript {
    ext {
        springBootVersion = '2.1.7.RELEASE'
    }
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    }
}

apply plugin: 'java'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'

group = 'com.practice.shaikhalvee'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'

repositories {
    mavenCentral()
}

dependencies {
    compile group: 'org.springframework.boot', name: 'spring-boot-starter-web'
    compile group: 'com.google.apis', name: 'google-api-services-firebaseremoteconfig', version: 'v1-rev14-1.23.0'
    compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.8.5'
    compile group: 'com.google.code.gson', name: 'gson', version: '2.8.6'
    testCompile group: 'junit', name: 'junit', version: '4.12'
}

这就是我创建的用于实验firebase-remote-config的控制器。

代码语言:javascript
复制
@RestController
@RequestMapping(value = "/api/remote-config")
public class FirebaseRestApiEndpoint {

    private final FirebaseRemoteConfigService firebaseRemoteConfigService;

    public FirebaseRestApiEndpoint(FirebaseRemoteConfigService firebaseRemoteConfigService) {
        this.firebaseRemoteConfigService = firebaseRemoteConfigService;
    }

    @GetMapping(value = "/get-template/{call-type}")
    public void getTemplate(@PathVariable("call-type") String callType) {
        switch (callType) {
            case "http":
                firebaseRemoteConfigService.getMetadataTemplateWithHttpCall();
                break;
            case "rest":
                firebaseRemoteConfigService.getMetadataTemplateWithRestCall();
                break;
            default:
                throw new RuntimeException("call-type is unknown. Should be rest or http");
        }
    }
}

这是我使用的accessToken()进程

代码语言:javascript
复制
// Constant File holds the url and other static final string values.
public static String getAccessToken() throws IOException {
    GoogleCredential googleCredential = GoogleCredential
            .fromStream(new FileInputStream(Constants.CERTIFICATE_FILE))
            .createScoped(Arrays.asList(Constants.SCOPES));
    googleCredential.refreshToken();
    return googleCredential.getAccessToken();
}

对于服务层,我只包括这里为简化而调用的方法。

这是使用HttpUrlConnection的方法。

代码语言:javascript
复制
public void getMetadataTemplateWithHttpCall() {
    try {
        URL url = new URL(Constants.BASE_URL + Constants.REMOTE_CONFIG_ENDPOINT);
        HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
        httpURLConnection.setRequestProperty("Authorization", "Bearer " + CommonConfig.getAccessToken());
        httpURLConnection.setRequestProperty("Content-Type", "application/json; UTF-8");
        httpURLConnection.setRequestMethod("GET");
        httpURLConnection.setRequestProperty("Accept-Encoding", "gzip");

        int code = httpURLConnection.getResponseCode();
        if (code == 200) {
            InputStream inputStream = new GZIPInputStream(httpURLConnection.getInputStream());
            JsonElement jsonElement = JsonParser.parseReader(new InputStreamReader(inputStream));

            Gson gson = new GsonBuilder()
                    .setPrettyPrinting()
                    .disableHtmlEscaping()
                    .enableComplexMapKeySerialization()
                    .serializeSpecialFloatingPointValues()
                    .create();
            String jsonStr = gson.toJson(jsonElement);
            RemoteConfig remoteConfig = gson.fromJson(jsonStr, RemoteConfig.class);
            String etag = httpURLConnection.getHeaderField("ETag");
            System.out.println(etag);
        }
    } catch (IOException e) {
        System.err.println(e.getMessage());
    }
}

这里,正确的etag是按照Firebase的文档打印的-Remote-Config REST Api。

但是,如果我尝试实现与RestTemplate相同的http连接,则无法获得etag。

现在,这是利用RestTemplate的方法。对于rest调用,我提供了非常类似的请求属性。但我还是拿不到etag

代码语言:javascript
复制
public void getMetadataTemplateWithRestCall() {
    ObjectMapper objectMapper = new ObjectMapper();
    HttpHeaders httpHeaders = new HttpHeaders();
    String url = "";
    try {
        httpHeaders.add(HttpHeaders.CONTENT_ENCODING, "gzip");
        httpHeaders.setBearerAuth(CommonConfig.getAccessToken());
        httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8);

        url = Constants.BASE_URL + Constants.REMOTE_CONFIG_ENDPOINT;

        HttpEntity<?> requestEntity = new HttpEntity(httpHeaders);
        ResponseEntity<RemoteConfig> baseResponse = restTemplate.exchange(url, HttpMethod.GET, requestEntity, RemoteConfig.class);

        String etag = baseResponse.getHeaders().getETag();
        System.out.println(etag);
    } catch (IOException e) {
        e.getMessage();
    }
}

正如您已经猜到的,这个etag值是。我正在尝试Firebase远程Config REST调用,但是如果我不能正确地处理REST调用,也许我在这里遗漏了什么。

为了您的方便,我提供它们的标题,因为etag驻留在标头中。有趣的是,在http call中,我得到了13个标题。在rest电话中,我得到了11,你猜到了,etag失踪了

这是http连接调用的头。

代码语言:javascript
复制
Transfer-Encoding=[chunked], 
null=[HTTP/1.1 200 OK],
Alt-Svc=[quic=":443"; ma=2592000; v="46,43",h3-Q050=":443"; ma=2592000,h3-Q049=":443"; ma=2592000,h3-Q048=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000], 
Server=[ESF], 
X-Content-Type-Options=[nosniff], 
Date=[Mon, 11 Nov 2019 04:59:04 GMT], 
X-Frame-Options=[SAMEORIGIN], 
Cache-Control=[private], 
ETag=[etag-111111311162-47],
Content-Encoding=[gzip],
Vary=[Referer, X-Origin, Origin], 
X-XSS-Protection=[0], 
Content-Type=[application/json; charset=UTF-8]

这是Rest调用的头。

代码语言:javascript
复制
Content-Type:"application/json; charset=UTF-8", 
Vary:"X-Origin", "Referer", "Origin,Accept-Encoding", 
Date:"Mon, 11 Nov 2019 05:15:10 GMT", 
Server:"ESF", 
Cache-Control:"private", 
X-XSS-Protection:"0", 
X-Frame-Options:"SAMEORIGIN", 
X-Content-Type-Options:"nosniff", 
Alt-Svc:"quic=":443"; ma=2592000; v="46,43",h3-Q050=":443"; ma=2592000,h3-Q049=":443"; ma=2592000,h3-Q048=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000", 
Accept-Ranges:"none", 
Transfer-Encoding:"chunked"

有人能帮帮我吗。我的目标是使用rest调用获得etag值,更确切地说是使用precisely框架的RestTemplate,因为它是REST。

谢谢。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-11-14 11:58:57

经过长时间的研究和调试,我找到了一个解决办法。

文档中,我们被告知添加标题Accept-Encoding: gzip。这就是我在httpHeaders.add(HttpHeaders.CONTENT_ENCODING, "gzip");方法中使用getMetadataTemplateWithHttpCall()的原因。它不起作用。我甚至添加了这样的标题,httpHeaders.add("Accept-Encoding", "gzip");。它引发异常,RestTemplate不接受gzip作为接受-编码。如果您在调用之前使用自定义的RestTemplate拦截器拦截rest调用,并使用gzip与拦截器一起压缩请求,则可以做到这一点。这意味着,对于RestTemplate,我们需要在http调用之前压缩请求,然后发送请求。只有到那时,在ResponseEntity中我才会得到"etag“。

我为指定的@Bean创建了一个RestTemplate,如下所示。如果您想使用Config框架的RestTemplate,那么必须添加这种类型的拦截器才能利用Firebase远程Config REST。

这是@Bean

代码语言:javascript
复制
@Configuration
public class RestTemplateConfig {
    @Bean(value = "gzippedRestTemplate")
    public RestTemplate restTemplate() {
        HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(
                HttpClientBuilder.create().build());
        clientHttpRequestFactory.setConnectTimeout(2000);
        clientHttpRequestFactory.setReadTimeout(10000);
        RestTemplate restTemplate = new RestTemplate(clientHttpRequestFactory);
        List<ClientHttpRequestInterceptor> interceptors = restTemplate.getInterceptors();
        if (interceptors == null) {
            interceptors = new ArrayList<>();
            restTemplate.setInterceptors(interceptors);
        }
        interceptors.add(new GzipAcceptHeaderRequestInterceptor());
        return restTemplate;
    }
    public static class GzipAcceptHeaderRequestInterceptor implements ClientHttpRequestInterceptor {
        @Override
        public ClientHttpResponse intercept(HttpRequest request, @Nullable byte[] body, ClientHttpRequestExecution execution) throws IOException {
            request.getHeaders().set(HttpHeaders.ACCEPT_ENCODING, "gzip");
            return execution.execute(request, body);
        }
    }
}

现在,您可以使用publish框架的GET RestTemplate从该调用中获得"etag“值,并发布您的工作。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58802311

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档