Skip to content

Commit 291f2eb

Browse files
committed
move default headers to rest template config
1 parent 497ff27 commit 291f2eb

File tree

6 files changed

+93
-58
lines changed

6 files changed

+93
-58
lines changed

src/main/java/org/commcare/formplayer/services/RestoreFactory.java

Lines changed: 8 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
package org.commcare.formplayer.services;
22

3-
import static org.commcare.formplayer.util.Constants.TOGGLE_INCLUDE_STATE_HASH;
4-
53
import com.google.common.collect.ImmutableMap;
64
import com.timgroup.statsd.StatsDClient;
7-
5+
import datadog.trace.api.Trace;
6+
import io.sentry.SentryLevel;
87
import org.apache.commons.io.IOUtils;
98
import org.apache.commons.logging.Log;
109
import org.apache.commons.logging.LogFactory;
@@ -25,14 +24,12 @@
2524
import org.commcare.formplayer.sqlitedb.UserDB;
2625
import org.commcare.formplayer.util.Constants;
2726
import org.commcare.formplayer.util.FormplayerSentry;
28-
import org.commcare.formplayer.util.RequestUtils;
2927
import org.commcare.formplayer.util.SimpleTimer;
3028
import org.commcare.formplayer.util.UserUtils;
3129
import org.commcare.formplayer.web.client.WebClient;
3230
import org.commcare.modern.database.TableBuilder;
3331
import org.javarosa.core.api.ClassNameHasher;
3432
import org.javarosa.core.model.User;
35-
import org.javarosa.core.util.PropertyUtils;
3633
import org.javarosa.core.util.externalizable.PrototypeFactory;
3734
import org.javarosa.xml.util.InvalidStructureException;
3835
import org.javarosa.xml.util.UnfullfilledRequirementsException;
@@ -55,27 +52,23 @@
5552
import org.xml.sax.SAXException;
5653
import org.xmlpull.v1.XmlPullParserException;
5754

55+
import javax.annotation.PreDestroy;
56+
import javax.annotation.Resource;
57+
import javax.xml.parsers.DocumentBuilder;
58+
import javax.xml.parsers.DocumentBuilderFactory;
59+
import javax.xml.parsers.ParserConfigurationException;
5860
import java.io.ByteArrayInputStream;
5961
import java.io.IOException;
6062
import java.io.InputStream;
6163
import java.io.UnsupportedEncodingException;
6264
import java.net.URI;
6365
import java.sql.SQLException;
64-
import java.time.Duration;
65-
import java.util.Collections;
6666
import java.util.HashMap;
6767
import java.util.LinkedHashMap;
6868
import java.util.Map;
6969
import java.util.concurrent.TimeUnit;
7070

71-
import javax.annotation.PreDestroy;
72-
import javax.annotation.Resource;
73-
import javax.xml.parsers.DocumentBuilder;
74-
import javax.xml.parsers.DocumentBuilderFactory;
75-
import javax.xml.parsers.ParserConfigurationException;
76-
77-
import datadog.trace.api.Trace;
78-
import io.sentry.SentryLevel;
71+
import static org.commcare.formplayer.util.Constants.TOGGLE_INCLUDE_STATE_HASH;
7972

8073

8174
/**
@@ -107,8 +100,6 @@ public class RestoreFactory {
107100

108101
private static final String DEVICE_ID_SLUG = "WebAppsLogin";
109102

110-
private static final String ORIGIN_TOKEN_SLUG = "OriginToken";
111-
112103
@Autowired
113104
protected StatsDClient datadogStatsDClient;
114105

@@ -124,18 +115,9 @@ public class RestoreFactory {
124115
@Autowired
125116
private WebClient webClient;
126117

127-
@Autowired
128-
private RedisTemplate redisTemplateLong;
129-
130118
@Resource(name = "redisTemplateLong")
131119
private ValueOperations<String, Long> valueOperations;
132120

133-
@Autowired
134-
private RedisTemplate redisTemplateString;
135-
136-
@Resource(name = "redisTemplateString")
137-
private ValueOperations<String, String> originTokens;
138-
139121
@Autowired
140122
private RedisTemplate redisSetTemplate;
141123

@@ -593,17 +575,9 @@ private HttpHeaders getStandardHeaders() {
593575
if (syncToken != null) {
594576
headers.set("X-CommCareHQ-LastSyncToken", getSyncToken());
595577
}
596-
headers.setAll(getOriginTokenHeader());
597578
return headers;
598579
}
599580

600-
private Map<String, String> getOriginTokenHeader() {
601-
String originToken = PropertyUtils.genUUID();
602-
String redisKey = String.format("%s%s", ORIGIN_TOKEN_SLUG, originToken);
603-
originTokens.set(redisKey, "valid", Duration.ofSeconds(60));
604-
return Collections.singletonMap("X-CommCareHQ-Origin-Token", originToken);
605-
}
606-
607581
public URI getRestoreUrl(boolean skipFixtures) {
608582
// TODO: remove timing once the state hash rollout is complete
609583
return categoryTimingHelper.timed(Constants.TimingCategories.BUILD_RESTORE_URL, () -> {
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package org.commcare.formplayer.web.client;
2+
3+
import org.commcare.formplayer.util.RequestUtils;
4+
import org.javarosa.core.util.PropertyUtils;
5+
import org.springframework.beans.factory.annotation.Value;
6+
import org.springframework.boot.web.client.RestTemplateRequestCustomizer;
7+
import org.springframework.data.redis.core.ValueOperations;
8+
import org.springframework.http.client.ClientHttpRequest;
9+
import org.springframework.stereotype.Component;
10+
11+
import javax.annotation.Resource;
12+
import java.time.Duration;
13+
14+
15+
/**
16+
* Adds default headers to requests to CommCareHQ
17+
*/
18+
@Component
19+
public class CommCareDefaultHeaders implements RestTemplateRequestCustomizer {
20+
21+
private static final String ORIGIN_TOKEN_SLUG = "OriginToken";
22+
private final CommCareRequestFilter requestFilter;
23+
24+
@Resource(name = "redisTemplateString")
25+
private ValueOperations<String, String> originTokens;
26+
27+
public CommCareDefaultHeaders(@Value("${commcarehq.host}") String commcareHost) {
28+
requestFilter = new CommCareRequestFilter(commcareHost);
29+
}
30+
31+
@Override
32+
public void customize(ClientHttpRequest request) {
33+
if (!requestFilter.isMatch(request)) {
34+
return;
35+
}
36+
37+
String ipAddress = RequestUtils.getIpAddress();
38+
if (ipAddress != null) {
39+
request.getHeaders().add("X-CommCareHQ-Origin-IP", ipAddress);
40+
}
41+
request.getHeaders().add("X-CommCareHQ-Origin-Token", getOriginTokenHeader());
42+
}
43+
44+
private String getOriginTokenHeader() {
45+
String originToken = PropertyUtils.genUUID();
46+
String redisKey = String.format("%s%s", ORIGIN_TOKEN_SLUG, originToken);
47+
originTokens.set(redisKey, "valid", Duration.ofSeconds(60));
48+
return originToken;
49+
}
50+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package org.commcare.formplayer.web.client;
2+
3+
import org.commcare.formplayer.util.RequestUtils;
4+
import org.springframework.http.HttpRequest;
5+
6+
/**
7+
* Filter to determine if a request is a request to CommCare. Additionally, filter based on
8+
* whether the current Spring request was authenticated with HMAC or not.
9+
*/
10+
public class CommCareHmacRequestFilter extends CommCareRequestFilter {
11+
12+
private final boolean matchHmac;
13+
14+
public CommCareHmacRequestFilter(String commcareHost, boolean matchHmac) {
15+
super(commcareHost);
16+
this.matchHmac = matchHmac;
17+
}
18+
19+
public boolean isMatch(HttpRequest request) {
20+
return super.isMatch(request) && matchHmac == RequestUtils.requestAuthedWithHmac();
21+
}
22+
}

src/main/java/org/commcare/formplayer/web/client/CommCareRequestFilter.java

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,17 @@
66
import java.util.function.Predicate;
77

88
/**
9-
* Filter to determine if a request is a request to CommCare. Additionally, it can filter based on
10-
* whether the current Spring request was authenticated with HMAC.
9+
* Filter to determine if a request is a request to CommCare.
1110
*/
1211
public class CommCareRequestFilter {
1312

1413
private final String commcareHost;
15-
private final boolean matchHmac;
1614

17-
public CommCareRequestFilter(String commcareHost, boolean matchHmac) {
15+
public CommCareRequestFilter(String commcareHost) {
1816
this.commcareHost = commcareHost;
19-
this.matchHmac = matchHmac;
2017
}
2118

2219
public boolean isMatch(HttpRequest request) {
23-
boolean currentRequestUsedHMAC = RequestUtils.requestAuthedWithHmac();
24-
boolean isCommCareRequest = request.getURI().toString().startsWith(commcareHost);
25-
return isCommCareRequest && (matchHmac == currentRequestUsedHMAC);
20+
return request.getURI().toString().startsWith(commcareHost);
2621
}
2722
}

src/main/java/org/commcare/formplayer/web/client/RestTemplateConfig.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.commcare.formplayer.web.client;
22

33
import org.commcare.formplayer.util.Constants;
4+
import org.springframework.beans.factory.annotation.Autowired;
45
import org.springframework.beans.factory.annotation.Value;
56
import org.springframework.boot.web.client.RestTemplateBuilder;
67
import org.springframework.context.annotation.Bean;
@@ -19,6 +20,9 @@ public class RestTemplateConfig {
1920

2021
public static String MODE_REPLACE_HOST = "replace-host";
2122

23+
@Autowired
24+
private CommCareDefaultHeaders commCareDefaultHeaders;
25+
2226
@Value("${formplayer.externalRequestMode}")
2327
private String externalRequestMode;
2428

@@ -45,16 +49,17 @@ public RestTemplate restTemplate(RestTemplateBuilder builder) throws URISyntaxEx
4549
builder = builder
4650
.setConnectTimeout(Duration.ofMillis(Constants.CONNECT_TIMEOUT))
4751
.setReadTimeout(Duration.ofMillis(Constants.READ_TIMEOUT))
48-
.requestFactory(OkHttp3ClientHttpRequestFactory.class);
52+
.requestFactory(OkHttp3ClientHttpRequestFactory.class)
53+
.additionalRequestCustomizers(commCareDefaultHeaders);
4954

5055
if (externalRequestMode.equals(MODE_REPLACE_HOST)) {
5156
log.warn(String.format("RestTemplate configured in '%s' mode", externalRequestMode));
5257
builder = builder.additionalInterceptors(
5358
new RewriteHostRequestInterceptor(commcareHost));
5459
}
5560

56-
CommCareRequestFilter hmacAuthFilter = new CommCareRequestFilter(commcareHost, true);
57-
CommCareRequestFilter sessionAuthFilter = new CommCareRequestFilter(commcareHost, false);
61+
CommCareRequestFilter hmacAuthFilter = new CommCareHmacRequestFilter(commcareHost, true);
62+
CommCareRequestFilter sessionAuthFilter = new CommCareHmacRequestFilter(commcareHost, false);
5863
return builder.additionalInterceptors(
5964
new HmacAuthInterceptor(hmacAuthFilter, formplayerAuthKey),
6065
new SessionAuthInterceptor(sessionAuthFilter)

src/main/java/org/commcare/formplayer/web/client/WebClient.java

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,16 @@
11
package org.commcare.formplayer.web.client;
22

33
import com.google.common.collect.Multimap;
4-
4+
import lombok.extern.apachecommons.CommonsLog;
55
import org.commcare.formplayer.services.RestoreFactory;
6-
import org.commcare.formplayer.util.RequestUtils;
76
import org.springframework.beans.factory.annotation.Autowired;
8-
import org.springframework.http.HttpHeaders;
9-
import org.springframework.http.HttpStatus;
10-
import org.springframework.http.MediaType;
11-
import org.springframework.http.RequestEntity;
12-
import org.springframework.http.ResponseEntity;
7+
import org.springframework.http.*;
138
import org.springframework.stereotype.Component;
149
import org.springframework.util.LinkedMultiValueMap;
1510
import org.springframework.web.client.RestTemplate;
1611

1712
import java.net.URI;
1813

19-
import lombok.extern.apachecommons.CommonsLog;
20-
2114
@Component
2215
@CommonsLog
2316
public class WebClient {
@@ -63,10 +56,6 @@ public <T> String post(String url, T body, boolean isMultipart) {
6356
if (isMultipart) {
6457
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
6558
}
66-
String ipAddress = RequestUtils.getIpAddress();
67-
if (ipAddress != null) {
68-
headers.add("X-CommCareHQ-Origin-IP", ipAddress);
69-
}
7059
return postRaw(uri, headers, body, String.class).getBody();
7160
}
7261

0 commit comments

Comments
 (0)