Skip to content

Commit 279a26b

Browse files
feat(LENS-1642): support for SAP specific user-agent header (#128)
* Minimum required to set user agent * Support for multiple connector versions * Applied formatting with spotless * Changed user agent attribute from an enum to an array string * Improved regex
1 parent 7725e54 commit 279a26b

File tree

4 files changed

+155
-9
lines changed

4 files changed

+155
-9
lines changed

src/main/java/com/coveo/pushapiclient/PlatformClient.java

+34-8
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ public class PlatformClient {
2121
private final String organizationId;
2222
private final ApiCore api;
2323
private final PlatformUrl platformUrl;
24+
private String[] userAgents;
2425

2526
/**
2627
* Construct a PlatformClient
@@ -570,13 +571,12 @@ private String[] getAuthorizationHeader() {
570571
}
571572

572573
private String[] getContentTypeApplicationJSONHeader() {
573-
MavenXpp3Reader reader = new MavenXpp3Reader();
574-
String version = "";
575-
try {
576-
Model model = reader.read(new FileReader("pom.xml"));
577-
version = model.getVersion();
578-
} catch (Exception e) {
579-
version = "Not-Available";
574+
StringBuilder userAgentValue = new StringBuilder();
575+
String sdkVersion = getSdkVersion();
576+
userAgentValue.append(String.format("CoveoSDKJava/%s", sdkVersion));
577+
578+
if (userAgents != null && userAgents.length > 0) {
579+
userAgentValue.append(" ").append(String.join(" ", userAgents));
580580
}
581581

582582
return new String[] {
@@ -585,10 +585,20 @@ private String[] getContentTypeApplicationJSONHeader() {
585585
"Accept",
586586
"application/json",
587587
"User-Agent",
588-
String.format("CoveoSDKJava/%s", version)
588+
userAgentValue.toString()
589589
};
590590
}
591591

592+
private String getSdkVersion() {
593+
MavenXpp3Reader reader = new MavenXpp3Reader();
594+
try {
595+
Model model = reader.read(new FileReader("pom.xml"));
596+
return model.getVersion();
597+
} catch (Exception e) {
598+
return "Not-Available";
599+
}
600+
}
601+
592602
private String[] getAes256Header() {
593603
return new String[] {"x-amz-server-side-encryption", "AES256"};
594604
}
@@ -600,4 +610,20 @@ private String[] getContentTypeApplicationOctetStreamHeader() {
600610
private String toJSON(HashMap<String, Object> hashMap) {
601611
return new Gson().toJson(hashMap, new TypeToken<HashMap<String, Object>>() {}.getType());
602612
}
613+
614+
public String[] getUserAgents() {
615+
return userAgents;
616+
}
617+
618+
public void setUserAgents(String[] userAgents) {
619+
if (!validUserAgents(userAgents)) {
620+
throw new IllegalArgumentException("Invalid user agents");
621+
}
622+
this.userAgents = userAgents;
623+
}
624+
625+
protected boolean validUserAgents(String[] userAgents) {
626+
String pattern = "^.+/v(\\d+(\\.\\d+){0,2})$";
627+
return Arrays.stream(userAgents).allMatch(agent -> agent.matches(pattern));
628+
}
603629
}

src/main/java/com/coveo/pushapiclient/StreamService.java

+34-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,22 @@ public class StreamService {
1414
private String streamId;
1515
private DocumentUploadQueue queue;
1616

17+
/**
18+
* Creates a service to stream your documents to the provided source by interacting with the
19+
* Stream API.
20+
*
21+
* <p>To perform <a href="https://docs.coveo.com/en/l62e0540">full document updates or
22+
* deletions</a>, use the {@UpdateStreamService}, since pushing documents with the
23+
* {@StreamService} is equivalent to triggering a full source rebuild. The {@StreamService} can
24+
* also be used for an initial catalog upload.
25+
*
26+
* @param source The source to which you want to send your documents.
27+
* @param userAgents The user agent to use for the requests.
28+
*/
29+
public StreamService(StreamEnabledSource source, String[] userAgents) {
30+
this(source, new BackoffOptionsBuilder().build(), userAgents);
31+
}
32+
1733
/**
1834
* Creates a service to stream your documents to the provided source by interacting with the
1935
* Stream API.
@@ -42,6 +58,23 @@ public StreamService(StreamEnabledSource source) {
4258
* @param options The configuration options for exponential backoff.
4359
*/
4460
public StreamService(StreamEnabledSource source, BackoffOptions options) {
61+
this(source, options, null);
62+
}
63+
64+
/**
65+
* Creates a service to stream your documents to the provided source by interacting with the
66+
* Stream API.
67+
*
68+
* <p>To perform <a href="https://docs.coveo.com/en/l62e0540">full document updates or
69+
* deletions</a>, use the {@UpdateStreamService}, since pushing documents with the
70+
* {@StreamService} is equivalent to triggering a full source rebuild. The {@StreamService} can
71+
* also be used for an initial catalog upload.
72+
*
73+
* @param source The source to which you want to send your documents.
74+
* @param options The configuration options for exponential backoff.
75+
* @param userAgents The user agent to use for the requests.
76+
*/
77+
public StreamService(StreamEnabledSource source, BackoffOptions options, String[] userAgents) {
4578
String apiKey = source.getApiKey();
4679
String organizationId = source.getOrganizationId();
4780
PlatformUrl platformUrl = source.getPlatformUrl();
@@ -51,7 +84,7 @@ public StreamService(StreamEnabledSource source, BackoffOptions options) {
5184
this.source = source;
5285
this.queue = new DocumentUploadQueue(uploader);
5386
this.platformClient = new PlatformClient(apiKey, organizationId, platformUrl, options);
54-
87+
platformClient.setUserAgents(userAgents);
5588
this.service = new StreamServiceInternal(this.source, this.queue, this.platformClient, logger);
5689
}
5790

src/main/java/com/coveo/pushapiclient/UpdateStreamService.java

+33
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,21 @@ public class UpdateStreamService {
1414

1515
private FileContainer fileContainer;
1616

17+
/**
18+
* Creates a service to stream your documents to the provided source by interacting with the
19+
* Stream API. This provides the ability to incrementally add, update, or delete documents via a
20+
* stream.
21+
*
22+
* <p>To perform <a href="https://docs.coveo.com/en/lb4a0344">a full source rebuild</a>, use the
23+
* {@StreamService}
24+
*
25+
* @param source The source to which you want to send your documents.
26+
* @param userAgents The user agent to use for the requests.
27+
*/
28+
public UpdateStreamService(StreamEnabledSource source, String[] userAgents) {
29+
this(source, new BackoffOptionsBuilder().build(), userAgents);
30+
}
31+
1732
/**
1833
* Creates a service to stream your documents to the provided source by interacting with the
1934
* Stream API. This provides the ability to incrementally add, update, or delete documents via a
@@ -40,10 +55,28 @@ public UpdateStreamService(StreamEnabledSource source) {
4055
* @param options The configuration options for exponential backoff.
4156
*/
4257
public UpdateStreamService(StreamEnabledSource source, BackoffOptions options) {
58+
this(source, options, null);
59+
}
60+
61+
/**
62+
* Creates a service to stream your documents to the provided source by interacting with the
63+
* Stream API. This provides the ability to incrementally add, update, or delete documents via a
64+
* stream.
65+
*
66+
* <p>To perform <a href="https://docs.coveo.com/en/lb4a0344">a full source rebuild</a>, use the
67+
* {@StreamService}
68+
*
69+
* @param source The source to which you want to send your documents.
70+
* @param options The configuration options for exponential backoff.
71+
* @param userAgents The user agent to use for the requests.
72+
*/
73+
public UpdateStreamService(
74+
StreamEnabledSource source, BackoffOptions options, String[] userAgents) {
4375
Logger logger = LogManager.getLogger(UpdateStreamService.class);
4476
this.platformClient =
4577
new PlatformClient(
4678
source.getApiKey(), source.getOrganizationId(), source.getPlatformUrl(), options);
79+
this.platformClient.setUserAgents(userAgents);
4780
this.updateStreamServiceInternal =
4881
new UpdateStreamServiceInternal(
4982
source,

src/test/java/com/coveo/pushapiclient/PlatformClientTest.java

+54
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,17 @@
77
import static org.mockito.Mockito.verify;
88

99
import com.google.gson.Gson;
10+
import java.io.FileReader;
1011
import java.io.IOException;
1112
import java.net.http.HttpClient;
1213
import java.net.http.HttpRequest;
1314
import java.net.http.HttpResponse;
1415
import java.util.ArrayList;
1516
import java.util.HashMap;
1617
import java.util.Map;
18+
import org.apache.maven.model.Model;
19+
import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
20+
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
1721
import org.junit.Before;
1822
import org.junit.Test;
1923
import org.mockito.ArgumentCaptor;
@@ -39,6 +43,10 @@ public void assertApplicationJsonHeader() {
3943
assertTrue(this.argument.getValue().headers().map().get("Accept").contains("application/json"));
4044
}
4145

46+
public void assertUserAgentHeader(String userAgentValue) {
47+
assertTrue(this.argument.getValue().headers().map().get("User-Agent").contains(userAgentValue));
48+
}
49+
4250
public SecurityIdentityModel securityIdentityModel() {
4351
return new SecurityIdentityModel(identityModels(), identityModel(), identityModels());
4452
}
@@ -472,4 +480,50 @@ public void testDeleteDocument() throws IOException, InterruptedException {
472480
assertApplicationJsonHeader();
473481
assertAuthorizationHeader();
474482
}
483+
484+
@Test
485+
public void testCorrectUserAgentHeader()
486+
throws IOException, InterruptedException, XmlPullParserException {
487+
String[] userAgents = {"MyAgent/v1", "MyAgent/v2.1", "MyAgent/v3.1.1"};
488+
String version = getVersionFromPom();
489+
String defaultAgent = String.format("CoveoSDKJava/%s", version);
490+
String[] userAgentsWithDefault = new String[userAgents.length + 1];
491+
userAgentsWithDefault[0] = defaultAgent;
492+
System.arraycopy(userAgents, 0, userAgentsWithDefault, 1, userAgents.length);
493+
494+
client.setUserAgents(userAgents);
495+
client.createSource("the_name", SourceType.PUSH, SourceVisibility.SECURED);
496+
verify(httpClient)
497+
.send(argument.capture(), any(HttpResponse.BodyHandlers.ofString().getClass()));
498+
499+
assertUserAgentHeader(String.join(" ", userAgentsWithDefault));
500+
}
501+
502+
@Test
503+
public void testDefaultUserAgentHeader()
504+
throws IOException, InterruptedException, XmlPullParserException {
505+
client.createSource("the_name", SourceType.PUSH, SourceVisibility.SECURED);
506+
verify(httpClient)
507+
.send(argument.capture(), any(HttpResponse.BodyHandlers.ofString().getClass()));
508+
String version = getVersionFromPom();
509+
assertUserAgentHeader(String.format("CoveoSDKJava/%s", version));
510+
}
511+
512+
@Test(expected = IllegalArgumentException.class)
513+
public void testInvalidHeaderValue() {
514+
String[] userAgents = {"MyAgent/v1", "MyAgent/v2.1", "MyAgent/v3.1.1", "invalidHeaderValue"};
515+
client.setUserAgents(userAgents);
516+
}
517+
518+
@Test(expected = IllegalArgumentException.class)
519+
public void testInvalidSemanticVersionHeaderValue() {
520+
String[] userAgents = {"MyAgent/v1.1.1.1"};
521+
client.setUserAgents(userAgents);
522+
}
523+
524+
private String getVersionFromPom() throws IOException, XmlPullParserException {
525+
MavenXpp3Reader reader = new MavenXpp3Reader();
526+
Model model = reader.read(new FileReader("pom.xml"));
527+
return model.getVersion();
528+
}
475529
}

0 commit comments

Comments
 (0)