Skip to content

Commit 43051ee

Browse files
authored
Merge pull request #4474 from marmoure/rest-client-encoding
fix Rest client file encoding
2 parents 1c60a4e + 7a42f96 commit 43051ee

File tree

3 files changed

+184
-14
lines changed

3 files changed

+184
-14
lines changed

exist-core/src/main/java/org/exist/http/RESTServer.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,7 @@ public void doGet(final DBBroker broker, final Txn transaction, final HttpServle
393393
// Process the request
394394
LockedDocument lockedDocument = null;
395395
DocumentImpl resource = null;
396-
final XmldbURI pathUri = XmldbURI.createInternal(path);
396+
final XmldbURI pathUri = XmldbURI.create(path);
397397
try {
398398
// check if path leads to an XQuery resource
399399
final String xquery_mime_type = MimeType.XQUERY_TYPE.getName();
@@ -545,7 +545,7 @@ public void doHead(final DBBroker broker, final Txn transaction, final HttpServl
545545
throws BadRequestException, PermissionDeniedException,
546546
NotFoundException, IOException {
547547

548-
final XmldbURI pathUri = XmldbURI.createInternal(path);
548+
final XmldbURI pathUri = XmldbURI.create(path);
549549
if (checkForXQueryTarget(broker, transaction, pathUri, request, response)) {
550550
return;
551551
}
@@ -623,7 +623,7 @@ public void doPost(final DBBroker broker, final Txn transaction, final HttpServl
623623
}
624624

625625
final Properties outputProperties = new Properties(defaultOutputKeysProperties);
626-
final XmldbURI pathUri = XmldbURI.createInternal(path);
626+
final XmldbURI pathUri = XmldbURI.create(path);
627627
LockedDocument lockedDocument = null;
628628
DocumentImpl resource = null;
629629

@@ -1134,7 +1134,7 @@ public void doPatch(final DBBroker broker, final Txn transaction, final XmldbURI
11341134

11351135
public void doDelete(final DBBroker broker, final Txn transaction, final String path, final HttpServletRequest request, final HttpServletResponse response)
11361136
throws PermissionDeniedException, NotFoundException, IOException, BadRequestException {
1137-
final XmldbURI pathURI = XmldbURI.createInternal(path);
1137+
final XmldbURI pathURI = XmldbURI.create(path);
11381138
if (checkForXQueryTarget(broker, transaction, pathURI, request, response)) {
11391139
return;
11401140
}
@@ -1322,7 +1322,7 @@ protected void search(final DBBroker broker, final Txn transaction, final String
13221322
}
13231323
}
13241324

1325-
final XmldbURI pathUri = XmldbURI.createInternal(path);
1325+
final XmldbURI pathUri = XmldbURI.create(path);
13261326
final Source source = new StringSource(query);
13271327
final XQueryPool pool = broker.getBrokerPool().getXQueryPool();
13281328
CompiledXQuery compiled = null;

exist-core/src/main/java/org/exist/http/servlets/EXistServlet.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ protected void doPut(final HttpServletRequest request, final HttpServletResponse
135135
try (final DBBroker broker = getPool().get(Optional.of(user));
136136
final Txn transaction = getPool().getTransactionManager().beginTransaction()) {
137137

138-
final XmldbURI dbpath = XmldbURI.createInternal(path);
138+
final XmldbURI dbpath = XmldbURI.create(path);
139139
try (final Collection collection = broker.getCollection(dbpath)) {
140140
if (collection != null) {
141141
transaction.abort();

exist-core/src/test/java/org/exist/http/RESTServiceTest.java

Lines changed: 178 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,25 +21,34 @@
2121
*/
2222
package org.exist.http;
2323

24-
import java.io.BufferedReader;
25-
import java.io.IOException;
26-
import java.io.InputStream;
27-
import java.io.InputStreamReader;
28-
import java.io.OutputStreamWriter;
29-
import java.io.Writer;
30-
import java.io.StringReader;
24+
import java.io.*;
3125
import java.net.HttpURLConnection;
3226
import java.net.URL;
3327
import java.net.URLEncoder;
28+
import java.util.Optional;
3429
import javax.xml.parsers.ParserConfigurationException;
3530

3631
import com.googlecode.junittoolbox.ParallelRunner;
3732
import org.apache.commons.codec.binary.Base64;
3833
import org.eclipse.jetty.http.HttpStatus;
34+
import org.exist.EXistException;
3935
import org.exist.Namespaces;
36+
import org.exist.collections.Collection;
37+
import org.exist.collections.triggers.TriggerException;
4038
import org.exist.dom.memtree.SAXAdapter;
39+
import org.exist.dom.persistent.LockedDocument;
40+
import org.exist.security.PermissionDeniedException;
41+
import org.exist.storage.BrokerPool;
42+
import org.exist.storage.DBBroker;
43+
import org.exist.storage.lock.Lock;
44+
import org.exist.storage.txn.Txn;
45+
import org.exist.test.ExistEmbeddedServer;
4146
import org.exist.test.ExistWebServer;
47+
import org.exist.test.TestConstants;
4248
import org.exist.util.ExistSAXParserFactory;
49+
import org.exist.util.LockException;
50+
import org.exist.util.MimeType;
51+
import org.exist.util.StringInputSource;
4352
import org.exist.xmldb.XmldbURI;
4453
import org.junit.runner.RunWith;
4554
import org.xml.sax.InputSource;
@@ -237,11 +246,30 @@ private static String getResourceUriPlus() {
237246
return getServerUri() + XmldbURI.ROOT_COLLECTION + "/test//../test/A-Za-z0-9_~!$&'()*+,;=@%20%23%25%27%2F%3F%5B%5Däöü.xml";
238247
}
239248

249+
@ClassRule
250+
public static final ExistEmbeddedServer existEmbeddedServer = new ExistEmbeddedServer(true, true);
240251

241252
@BeforeClass
242-
public static void createCredentials() {
253+
public static void setup() throws PermissionDeniedException, IOException, TriggerException {
243254
credentials = Base64.encodeBase64String("admin:".getBytes(UTF_8));
244255
badCredentials = Base64.encodeBase64String("johndoe:this pw should fail".getBytes(UTF_8));
256+
257+
final XmldbURI TEST_XML_DOC_URI = XmldbURI.create("AéB.xml");
258+
final XmldbURI TEST_COLLECTION_URI = XmldbURI.create("/db/AéB");
259+
final String TEST_XML_DOC = "<foo/>";
260+
261+
final BrokerPool pool = existEmbeddedServer.getBrokerPool();
262+
try (final DBBroker broker = pool.get(Optional.of(pool.getSecurityManager().getSystemSubject()));
263+
final Txn transaction = pool.getTransactionManager().beginTransaction()) {
264+
try (final Collection col = broker.getOrCreateCollection(transaction, TEST_COLLECTION_URI)) {
265+
broker.storeDocument(transaction, TEST_XML_DOC_URI, new StringInputSource(TEST_XML_DOC), MimeType.XML_TYPE, col);
266+
broker.saveCollection(transaction, col);
267+
}
268+
269+
transaction.commit();
270+
} catch (EXistException | SAXException | LockException e) {
271+
throw new RuntimeException(e);
272+
}
245273
}
246274

247275
@Test
@@ -1036,6 +1064,148 @@ public void execSetUidQueryWithBearerAuth() throws IOException {
10361064
}
10371065
}
10381066

1067+
//test rest server ability to handle encoded characters
1068+
// all the tests with EncodedPath in function declaration aim to test rest server ability to handle special characters
1069+
@Test
1070+
public void doGetEncodedPath() throws IOException {
1071+
String DOC_URI = getServerUri() + XmldbURI.ROOT_COLLECTION + "/AéB/AéB.xml";
1072+
final HttpURLConnection connect = getConnection(DOC_URI);
1073+
try {
1074+
connect.setRequestMethod("GET");
1075+
connect.connect();
1076+
1077+
final int r = connect.getResponseCode();
1078+
assertEquals("Server returned response code " + r, HttpStatus.OK_200, r);
1079+
String contentType = connect.getContentType();
1080+
final int semicolon = contentType.indexOf(';');
1081+
if (semicolon > 0) {
1082+
contentType = contentType.substring(0, semicolon).trim();
1083+
}
1084+
assertEquals("Server returned content type " + contentType, "application/xml", contentType);
1085+
1086+
String response = readResponse(connect.getInputStream());
1087+
1088+
//readResponse is appending \r\n to each line that's why its added the expected content
1089+
assertEquals("Server returned document content " + response,"<foobar/>\r\n",response);
1090+
} finally {
1091+
connect.disconnect();
1092+
}
1093+
}
1094+
1095+
@Test
1096+
public void doHeadEncodedPath() throws IOException {
1097+
String DOC_URI = getServerUri() + XmldbURI.ROOT_COLLECTION + "/AéB/AéB.xml";
1098+
final HttpURLConnection connect = getConnection(DOC_URI);
1099+
try {
1100+
connect.setRequestMethod("GET");
1101+
connect.connect();
1102+
1103+
final int r = connect.getResponseCode();
1104+
assertEquals("Server returned response code " + r, HttpStatus.OK_200, r);
1105+
} finally {
1106+
connect.disconnect();
1107+
}
1108+
}
1109+
1110+
@Test
1111+
public void doPutEncodedPath() throws IOException {
1112+
String DOC_URI = getServerUri() + XmldbURI.ROOT_COLLECTION + "/AéB/AéB.xml";
1113+
final HttpURLConnection connect = getConnection(DOC_URI);
1114+
final HttpURLConnection getConnect = getConnection(DOC_URI);
1115+
String data = "<foobar/>";
1116+
try {
1117+
connect.setRequestProperty("Authorization", "Basic " + credentials);
1118+
connect.setRequestMethod("PUT");
1119+
connect.setDoOutput(true);
1120+
connect.setRequestProperty("ContentType", "application/xml");
1121+
try (final Writer writer = new OutputStreamWriter(connect.getOutputStream(), UTF_8)) {
1122+
writer.write(data);
1123+
}
1124+
1125+
connect.connect();
1126+
final int r = connect.getResponseCode();
1127+
assertEquals("doPut: Server returned response code " + r, HttpStatus.CREATED_201, r);
1128+
1129+
// assert file content updated
1130+
getConnect.setRequestMethod("GET");
1131+
getConnect.connect();
1132+
1133+
final int res_code = getConnect.getResponseCode();
1134+
assertEquals("Server returned response code " + res_code, HttpStatus.OK_200, res_code);
1135+
1136+
String response = readResponse(getConnect.getInputStream());
1137+
1138+
//readResponse is appending \r\n to each line that's why its added the expected content
1139+
assertEquals("Server returned document content " + response,"<foobar/>\r\n",response);
1140+
1141+
} finally {
1142+
connect.disconnect();
1143+
getConnect.disconnect();
1144+
}
1145+
}
1146+
1147+
@Test
1148+
public void doPostEncodedPath() throws IOException {
1149+
String DOC_URI = getServerUri() + XmldbURI.ROOT_COLLECTION + "/AéB/AéB.xml";
1150+
final HttpURLConnection connect = getConnection(DOC_URI);
1151+
1152+
String data = "<query xmlns=\"http://exist.sourceforge.net/NS/exist\">\n" +
1153+
" <text>\n" +
1154+
" //foo\n" +
1155+
" </text>\n" +
1156+
"</query>";
1157+
try {
1158+
connect.setRequestProperty("Authorization", "Basic " + credentials);
1159+
connect.setRequestMethod("POST");
1160+
connect.setDoOutput(true);
1161+
connect.setRequestProperty("Content-Type", "application/xml");
1162+
try (final Writer writer = new OutputStreamWriter(connect.getOutputStream(), UTF_8)) {
1163+
writer.write(data);
1164+
}
1165+
1166+
connect.connect();
1167+
final int r = connect.getResponseCode();
1168+
assertEquals("doPut: Server returned response code " + r, HttpStatus.OK_200, r);
1169+
1170+
String response = readResponse(connect.getInputStream());
1171+
1172+
//readResponse is appending \r\n to each line that's why its added the expected content
1173+
assertTrue("Server returned " + response,response.contains("exist:hits=\"1\""));
1174+
1175+
} finally {
1176+
connect.disconnect();
1177+
}
1178+
}
1179+
1180+
@Test
1181+
public void doDeleteEncodedPath() throws IOException {
1182+
String DOC_URI = getServerUri() + XmldbURI.ROOT_COLLECTION + "/AéB/AéB.xml";
1183+
final HttpURLConnection connect = getConnection(DOC_URI);
1184+
final HttpURLConnection getConnect = getConnection(DOC_URI);
1185+
1186+
try {
1187+
connect.setRequestProperty("Authorization", "Basic " + credentials);
1188+
connect.setRequestMethod("DELETE");
1189+
connect.setDoOutput(true);
1190+
1191+
connect.connect();
1192+
final int r = connect.getResponseCode();
1193+
assertEquals("doPut: Server returned response code " + r, HttpStatus.OK_200, r);
1194+
1195+
// assert file content updated
1196+
getConnect.setRequestMethod("GET");
1197+
getConnect.connect();
1198+
1199+
1200+
final int res_code = getConnect.getResponseCode();
1201+
assertEquals("Server returned response code " + res_code, HttpStatus.NOT_FOUND_404, res_code);
1202+
1203+
}finally {
1204+
connect.disconnect();
1205+
getConnect.disconnect();
1206+
}
1207+
}
1208+
10391209
private void chmod(final String resourcePath, final String mode) throws IOException {
10401210
final String uri = getCollectionUri() +"?_query=" + URLEncoder.encode(
10411211
"sm:chmod(xs:anyURI('" + resourcePath + "'), '" + mode + "')",

0 commit comments

Comments
 (0)