mirror of https://github.com/apache/lucene.git
SOLR-6163: Correctly decode special characters in managed stopwords and synonym endpoints.
git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1616361 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
ddbd55d24d
commit
c119cf89a4
|
@ -238,6 +238,9 @@ Bug Fixes
|
||||||
* SOLR-6264: Distributed commit and optimize are executed serially across all
|
* SOLR-6264: Distributed commit and optimize are executed serially across all
|
||||||
replicas. (Mark Miller, Timothy Potter)
|
replicas. (Mark Miller, Timothy Potter)
|
||||||
|
|
||||||
|
* SOLR-6163: Correctly decode special characters in managed stopwords and synonym endpoints.
|
||||||
|
(Vitaliy Zhovtyuk, Timo Schmidt via Timothy Potter)
|
||||||
|
|
||||||
Optimizations
|
Optimizations
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
|
|
|
@ -66,6 +66,8 @@ public class RestManager {
|
||||||
// used for validating resourceIds provided during registration
|
// used for validating resourceIds provided during registration
|
||||||
private static final Pattern resourceIdRegex = Pattern.compile("(/config|/schema)(/.*)");
|
private static final Pattern resourceIdRegex = Pattern.compile("(/config|/schema)(/.*)");
|
||||||
|
|
||||||
|
private static final boolean DECODE = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used internally to keep track of registrations during core initialization
|
* Used internally to keep track of registrations during core initialization
|
||||||
*/
|
*/
|
||||||
|
@ -251,21 +253,23 @@ public class RestManager {
|
||||||
* to. ManagedResource implementations are heavy-weight objects that live for the duration of
|
* to. ManagedResource implementations are heavy-weight objects that live for the duration of
|
||||||
* a SolrCore, so this class acts as the proxy between Restlet and a ManagedResource when
|
* a SolrCore, so this class acts as the proxy between Restlet and a ManagedResource when
|
||||||
* doing request processing.
|
* doing request processing.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
public static class ManagedEndpoint extends BaseSolrResource
|
public static class ManagedEndpoint extends BaseSolrResource
|
||||||
implements GETable, PUTable, POSTable, DELETEable
|
implements GETable, PUTable, POSTable, DELETEable
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Determines the ManagedResource resourceId from the Restlet request.
|
* Determines the ManagedResource resourceId from the Restlet request.
|
||||||
*/
|
*/
|
||||||
public static String resolveResourceId(Request restletReq) {
|
public static String resolveResourceId(Request restletReq) {
|
||||||
String resourceId = restletReq.getResourceRef().
|
String resourceId = restletReq.getResourceRef().
|
||||||
getRelativeRef(restletReq.getRootRef().getParentRef()).getPath();
|
getRelativeRef(restletReq.getRootRef().getParentRef()).getPath(DECODE);
|
||||||
|
|
||||||
// all resources are registered with the leading slash
|
// all resources are registered with the leading slash
|
||||||
if (!resourceId.startsWith("/"))
|
if (!resourceId.startsWith("/"))
|
||||||
resourceId = "/"+resourceId;
|
resourceId = "/"+resourceId;
|
||||||
|
|
||||||
|
|
||||||
return resourceId;
|
return resourceId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -427,7 +427,7 @@
|
||||||
<!-- A specialized field for geospatial search. If indexed, this fieldType must not be multivalued. -->
|
<!-- A specialized field for geospatial search. If indexed, this fieldType must not be multivalued. -->
|
||||||
<fieldType name="location" class="solr.LatLonType" subFieldSuffix="_coordinate"/>
|
<fieldType name="location" class="solr.LatLonType" subFieldSuffix="_coordinate"/>
|
||||||
|
|
||||||
<!-- Field type where stopwords are managed by the REST API -->
|
<!-- Field type where english stopwords are managed by the REST API -->
|
||||||
<fieldtype name="managed_en" class="solr.TextField">
|
<fieldtype name="managed_en" class="solr.TextField">
|
||||||
<analyzer>
|
<analyzer>
|
||||||
<tokenizer class="solr.StandardTokenizerFactory"/>
|
<tokenizer class="solr.StandardTokenizerFactory"/>
|
||||||
|
@ -436,6 +436,15 @@
|
||||||
</analyzer>
|
</analyzer>
|
||||||
</fieldtype>
|
</fieldtype>
|
||||||
|
|
||||||
|
<!-- Field type where german stopwords are managed by the REST API -->
|
||||||
|
<fieldtype name="managed_de" class="solr.TextField">
|
||||||
|
<analyzer>
|
||||||
|
<tokenizer class="solr.StandardTokenizerFactory"/>
|
||||||
|
<filter class="solr.ManagedStopFilterFactory" managed="german" />
|
||||||
|
<filter class="solr.ManagedSynonymFilterFactory" managed="german" />
|
||||||
|
</analyzer>
|
||||||
|
</fieldtype>
|
||||||
|
|
||||||
</types>
|
</types>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,8 @@ import org.apache.solr.rest.ManagedResourceStorage.StorageIO;
|
||||||
import org.apache.solr.rest.schema.analysis.ManagedWordSetResource;
|
import org.apache.solr.rest.schema.analysis.ManagedWordSetResource;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.noggit.JSONUtil;
|
import org.noggit.JSONUtil;
|
||||||
|
import org.restlet.Request;
|
||||||
|
import org.restlet.data.Reference;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests {@link RestManager} functionality, including resource registration,
|
* Tests {@link RestManager} functionality, including resource registration,
|
||||||
|
@ -248,4 +250,30 @@ public class TestRestManager extends SolrRestletTestBase {
|
||||||
RestManager restManager2 = new RestManager();
|
RestManager restManager2 = new RestManager();
|
||||||
restManager2.init(loader, initArgs, storageIO);
|
restManager2.init(loader, initArgs, storageIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testResolveResourceId () throws Exception {
|
||||||
|
Request testRequest = new Request();
|
||||||
|
Reference rootRef = new Reference("http://solr.apache.org/");
|
||||||
|
testRequest.setRootRef(rootRef);
|
||||||
|
|
||||||
|
Reference resourceRef = new Reference("http://solr.apache.org/schema/analysis/synonyms/de");
|
||||||
|
testRequest.setResourceRef(resourceRef);
|
||||||
|
|
||||||
|
String resourceId = RestManager.ManagedEndpoint.resolveResourceId(testRequest);
|
||||||
|
assertEquals(resourceId, "/schema/analysis/synonyms/de");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testResolveResourceIdDecodeUrlEntities () throws Exception {
|
||||||
|
Request testRequest = new Request();
|
||||||
|
Reference rootRef = new Reference("http://solr.apache.org/");
|
||||||
|
testRequest.setRootRef(rootRef);
|
||||||
|
|
||||||
|
Reference resourceRef = new Reference("http://solr.apache.org/schema/analysis/synonyms/de/%C3%84ndern");
|
||||||
|
testRequest.setResourceRef(resourceRef);
|
||||||
|
|
||||||
|
String resourceId = RestManager.ManagedEndpoint.resolveResourceId(testRequest);
|
||||||
|
assertEquals(resourceId, "/schema/analysis/synonyms/de/Ändern");
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -185,4 +185,29 @@ public class TestManagedStopFilterFactory extends RestTestBase {
|
||||||
// should fail with 404 as foo doesn't exist
|
// should fail with 404 as foo doesn't exist
|
||||||
assertJDelete(endpoint + "/foo", "/error/code==404");
|
assertJDelete(endpoint + "/foo", "/error/code==404");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Can we add and remove stopwords with umlauts
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testCanHandleDecodingAndEncodingForStopwords() throws Exception {
|
||||||
|
String endpoint = "/schema/analysis/stopwords/german";
|
||||||
|
|
||||||
|
//initially it should not exist
|
||||||
|
assertJQ(endpoint + "/schön", "/error/code==404");
|
||||||
|
|
||||||
|
//now we put a stopword with an umlaut
|
||||||
|
assertJPut(endpoint,
|
||||||
|
JSONUtil.toJSON(Arrays.asList("schön")),
|
||||||
|
"/responseHeader/status==0");
|
||||||
|
|
||||||
|
//let's check if it exists
|
||||||
|
assertJQ(endpoint + "/schön", "/schön=='schön'");
|
||||||
|
|
||||||
|
//now let's remove it
|
||||||
|
assertJDelete(endpoint + "/schön", "/responseHeader/status==0");
|
||||||
|
|
||||||
|
//and of it is unavailable again
|
||||||
|
assertJQ(endpoint + "/schön", "/error/code==404");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -196,4 +196,41 @@ public class TestManagedSynonymFilterFactory extends RestTestBase {
|
||||||
assertJQ(endpoint+"/MB",
|
assertJQ(endpoint+"/MB",
|
||||||
"/MB==['Megabyte','MiB','megabyte']");
|
"/MB==['Megabyte','MiB','megabyte']");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Can we add and remove stopwords with umlauts
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testCanHandleDecodingAndEncodingForSynonyms() throws Exception {
|
||||||
|
String endpoint = "/schema/analysis/synonyms/german";
|
||||||
|
|
||||||
|
assertJQ(endpoint,
|
||||||
|
"/synonymMappings/initArgs/ignoreCase==false",
|
||||||
|
"/synonymMappings/managedMap=={}");
|
||||||
|
|
||||||
|
// does not exist
|
||||||
|
assertJQ(endpoint+"/fröhlich",
|
||||||
|
"/error/code==404");
|
||||||
|
|
||||||
|
Map<String,List<String>> syns = new HashMap<>();
|
||||||
|
|
||||||
|
// now put a synonym
|
||||||
|
syns.put("fröhlich", Arrays.asList("glücklick"));
|
||||||
|
assertJPut(endpoint,
|
||||||
|
JSONUtil.toJSON(syns),
|
||||||
|
"/responseHeader/status==0");
|
||||||
|
|
||||||
|
// and check if it exists
|
||||||
|
assertJQ(endpoint,
|
||||||
|
"/synonymMappings/managedMap/fröhlich==['glücklick']");
|
||||||
|
|
||||||
|
// verify delete works
|
||||||
|
assertJDelete(endpoint+"/fröhlich",
|
||||||
|
"/responseHeader/status==0");
|
||||||
|
|
||||||
|
|
||||||
|
// was it really deleted?
|
||||||
|
assertJDelete(endpoint+"/fröhlich",
|
||||||
|
"/error/code==404");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue