Skip to content

Commit 81246fa

Browse files
committed
add test client names in AdminHttpHandler
These names can be used to simulate multi-client accesses through the xatkit-react component.
1 parent f80b972 commit 81246fa

File tree

3 files changed

+56
-28
lines changed

3 files changed

+56
-28
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ The changelog format is based on [Keep a Changelog](https://keepachangelog.com/e
1515
- Support for all the Http methods supported by Apache http-core in XatkitServer (fix [#222]( https://github.com/xatkit-bot-platform/xatkit-runtime/issues/222 )). This includes requests with parameters (`?param=value`), that are correctly mapped to the handler corresponding to their base URI. **This change breaks the public API**: it is now required to specify the `HttpMethod` when registering a rest handler.
1616
- We have replaced the previous monitoring API with a brand new REST API that will offer us the required flexibility to expose additional information in the future. You can take a look at the available endpoints and the associated responses in this [wiki article](https://github.com/xatkit-bot-platform/xatkit-releases/wiki/REST-API). Note that this API is far from perfect, and we already have a couple of opened issues to improve it (see [here](https://github.com/xatkit-bot-platform/xatkit-runtime/issues/258) and [here](https://github.com/xatkit-bot-platform/xatkit-runtime/issues/257)).
1717
- `RuntimeActions` creating a dedicated `XatkitSession` (e.g. messaging actions getting a session based on the targeted channel) now update the execution rule's session to reflect the session shift. This allows, in the context of an event reaction bot, to set session variables in reaction to an *event* that will be merged in the session corresponding to the messaging action triggered within the rule.
18+
- `AdminHttpHandler` now uses a list of test client names to simulate multi-client bots using the web-based component. The name is printed in the rendered HTML page, and used to initialize the *xatkit-react* client.
1819

1920
### Changed
2021

core/src/main/java/com/xatkit/core/server/AdminHttpHandler.java

Lines changed: 51 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
11
package com.xatkit.core.server;
22

33
import com.xatkit.core.XatkitException;
4-
import com.xatkit.core.platform.io.WebhookEventProvider;
54
import fr.inria.atlanmod.commons.log.Log;
65
import org.apache.commons.configuration2.Configuration;
76
import org.apache.http.HttpRequest;
87
import org.apache.http.HttpResponse;
98
import org.apache.http.HttpStatus;
109
import org.apache.http.entity.BasicHttpEntity;
1110
import org.apache.http.entity.ContentType;
12-
import org.apache.http.protocol.HTTP;
1311
import org.apache.http.protocol.HttpContext;
1412
import org.apache.http.protocol.HttpRequestHandler;
1513

@@ -18,24 +16,48 @@
1816
import java.io.IOException;
1917
import java.io.InputStream;
2018
import java.io.InputStreamReader;
21-
import java.io.UnsupportedEncodingException;
19+
import java.net.URISyntaxException;
20+
import java.nio.charset.StandardCharsets;
2221
import java.text.MessageFormat;
22+
import java.util.Arrays;
23+
import java.util.List;
2324
import java.util.Locale;
2425
import java.util.Objects;
2526

2627
import static fr.inria.atlanmod.commons.Preconditions.checkNotNull;
2728
import static java.util.Objects.isNull;
2829

2930
/**
30-
* Handles the input requests and notifies the {@link WebhookEventProvider}s.
31+
* A handler bound to {@code /admin} that allows to quickly test web-based bots.
3132
*/
3233
class AdminHttpHandler implements HttpRequestHandler {
3334

3435
/**
35-
* The pattern used to match and replace the server location template in the HTML file.
36+
* The pattern used to print the server location in the rendered {@code admin.html} file.
3637
*/
37-
// Need to double single quotes, see https://docs.oracle.com/javase/7/docs/api/java/text/MessageFormat.html
38-
private static final String SERVER_LOCATION_PATTERN = "window.xatkit_server = ''{0}''";
38+
private static final String SERVER_LOCATION_PATTERN = "#xatkit\\.server";
39+
40+
/**
41+
* The pattern used to print the username in the rendered {@code admin.html} file.
42+
* <p>
43+
* This pattern is replaced with a random name from {@link #TEST_CLIENT_NAMES} when the page is displayed to
44+
* simulate multiple users.
45+
*/
46+
private static final String USERNAME_PATTERN = "#xatkit\\.username";
47+
48+
/**
49+
* A {@link List} of test client names used to render the {@code /admin} page and simulate multiple users.
50+
*
51+
* @see #TEMPLATE_FILLED_COUNT
52+
*/
53+
private static List<String> TEST_CLIENT_NAMES = Arrays.asList("Bob", "Alice", "Gwendal", "Jordi");
54+
55+
/**
56+
* A counter used to render the {@code /admin} page with random client names.
57+
*
58+
* @see #TEST_CLIENT_NAMES
59+
*/
60+
private static int TEMPLATE_FILLED_COUNT = 0;
3961

4062
/**
4163
* The placeholder used for the server location in the HTML file.
@@ -87,19 +109,24 @@ public AdminHttpHandler(Configuration configuration) {
87109
public void handle(final HttpRequest request, final HttpResponse response, final HttpContext context) {
88110

89111
String method = request.getRequestLine().getMethod().toUpperCase(Locale.ROOT);
90-
String target = request.getRequestLine().getUri();
91-
92-
Log.info("Received a {0} query on {1}", method, target);
112+
String path = null;
113+
try {
114+
path = HttpUtils.getPath(request);
115+
} catch(URISyntaxException e) {
116+
throw new XatkitException(MessageFormat.format("Cannot parse the provided URI {0}, see attached exception",
117+
request.getRequestLine().getUri()), e);
118+
}
119+
Log.info("Received a {0} query on {1}", method, path);
93120

94121
/*
95122
* Ignore the parameters, they are not used for now.
96123
*/
97124

98-
if (Objects.equals(method,"GET")) {
125+
if (Objects.equals(method, "GET")) {
99126
/*
100127
* Use Objects.equals(): the method/target may be null
101128
*/
102-
if (Objects.equals(target, "/admin")) {
129+
if (Objects.equals(path, "/admin")) {
103130
InputStream is = this.getClass().getClassLoader().getResourceAsStream("admin/admin.html");
104131
if (isNull(is)) {
105132
Log.error("Cannot return the admin/admin.html page not found");
@@ -110,14 +137,14 @@ public void handle(final HttpRequest request, final HttpResponse response, final
110137
InputStream entityContent = replaceHtmlTemplates(is);
111138
entity.setContent(entityContent);
112139
entity.setContentType(ContentType.TEXT_HTML.getMimeType());
113-
entity.setContentEncoding(HTTP.UTF_8);
140+
entity.setContentEncoding(StandardCharsets.UTF_8.name());
114141
response.setEntity(entity);
115142
response.setStatusCode(HttpStatus.SC_OK);
116143
return;
117144
}
118145

119-
if (target.startsWith("/admin/js/") || target.startsWith("/admin/css/")) {
120-
String targetPath = target.substring(1);
146+
if (path.startsWith("/admin/js/") || path.startsWith("/admin/css/")) {
147+
String targetPath = path.substring(1);
121148
InputStream is = this.getClass().getClassLoader().getResourceAsStream(targetPath);
122149
if (isNull(is)) {
123150
Log.error("Cannot return the resource at {0}", targetPath);
@@ -131,24 +158,27 @@ public void handle(final HttpRequest request, final HttpResponse response, final
131158
} else if (targetPath.endsWith(".js")) {
132159
entity.setContentType("application/javascript");
133160
}
134-
entity.setContentEncoding(HTTP.UTF_8);
161+
entity.setContentEncoding(StandardCharsets.UTF_8.name());
135162
response.setEntity(entity);
136163
response.setStatusCode(HttpStatus.SC_OK);
137164
return;
138165
}
139166
}
140167
}
141168

169+
142170
/**
143171
* Replaces the templates of the provided {@code from} {@link InputStream}.
144172
* <p>
145173
* This method creates a new {@link InputStream} containing {@code from}'s contents with its template replaced.
146174
*
147175
* @param from the {@link InputStream} to replace the templates from
148176
* @return an {@link InputStream} containing {@code from}'s contents with its templates replaced
149-
* @see XatkitServerUtils#SERVER_PUBLIC_URL_KEY
177+
* @see #SERVER_LOCATION_PATTERN
178+
* @see #USERNAME_PATTERN
150179
*/
151180
private InputStream replaceHtmlTemplates(InputStream from) {
181+
TEMPLATE_FILLED_COUNT++;
152182
BufferedReader reader = new BufferedReader(new InputStreamReader(from));
153183
StringBuilder builder = new StringBuilder();
154184
try {
@@ -160,14 +190,9 @@ private InputStream replaceHtmlTemplates(InputStream from) {
160190
"attached exception", this.getClass().getSimpleName()), e);
161191
}
162192
String content = builder.toString();
163-
content = content.replace(MessageFormat.format(SERVER_LOCATION_PATTERN, SERVER_LOCATION_PLACEHOLDER),
164-
MessageFormat.format(SERVER_LOCATION_PATTERN, reactServerURL));
165-
try {
166-
return new ByteArrayInputStream(content.getBytes("UTF-8"));
167-
} catch (UnsupportedEncodingException e) {
168-
throw new XatkitException(MessageFormat.format("Cannot create an {0} from the provided {1}: {2}, see " +
169-
"attached exception", InputStream.class.getSimpleName(), String.class.getSimpleName(),
170-
content), e);
171-
}
193+
content = content.replaceAll(SERVER_LOCATION_PATTERN, reactServerURL);
194+
String clientName = TEST_CLIENT_NAMES.get(TEMPLATE_FILLED_COUNT % TEST_CLIENT_NAMES.size());
195+
content = content.replaceAll(USERNAME_PATTERN, clientName);
196+
return new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8));
172197
}
173198
}

core/src/main/resources/admin/admin.html

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@
55
<link href="/admin/css/xatkit-react2.css" rel="stylesheet">
66
</head>
77
<body>
8+
<h1>Xatkit test environment</h1>
9+
<p>Your test username: #xatkit.username</p>
810
<div id="xatkit-chat"></div>
911
<script>
10-
window.xatkit_username = 'admin';
11-
window.xatkit_server = 'http://localhost:5001'
12+
window.xatkit_username = '#xatkit.username';
13+
window.xatkit_server = '#xatkit.server'
1214
</script>
1315
<script src="/admin/js/xatkit-react1.js"></script>
1416
<script src="/admin/js/xatkit-react2.js"></script>

0 commit comments

Comments
 (0)