This is an automated email from the ASF dual-hosted git repository.
radu pushed a commit to branch feature/SLING-9655
in repository
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-graphql-core.git
The following commit(s) were added to refs/heads/feature/SLING-9655 by this
push:
new 1cb7350 SLING-9655 - Caching support for the GraphQL core
1cb7350 is described below
commit 1cb7350b2e0e7f843dd2256f241958057cd48157
Author: Radu Cotescu <[email protected]>
AuthorDate: Fri Aug 21 20:29:13 2020 +0200
SLING-9655 - Caching support for the GraphQL core
* added basic support for the Cache-Control header
for persisted queries
---
.../sling/graphql/core/servlet/GraphQLServlet.java | 30 ++++++++++++++++++++--
.../graphql/core/it/GraphQLCoreTestSupport.java | 17 +++++++++---
.../sling/graphql/core/it/GraphQLServletIT.java | 25 +++++++++++++++---
3 files changed, 63 insertions(+), 9 deletions(-)
diff --git
a/src/main/java/org/apache/sling/graphql/core/servlet/GraphQLServlet.java
b/src/main/java/org/apache/sling/graphql/core/servlet/GraphQLServlet.java
index 25f7928..a54b0e4 100644
--- a/src/main/java/org/apache/sling/graphql/core/servlet/GraphQLServlet.java
+++ b/src/main/java/org/apache/sling/graphql/core/servlet/GraphQLServlet.java
@@ -41,6 +41,7 @@ import org.apache.sling.graphql.core.json.JsonSerializer;
import org.apache.sling.graphql.core.scalars.SlingScalarsProvider;
import org.apache.sling.graphql.core.schema.RankedSchemaProviders;
import org.jetbrains.annotations.NotNull;
+import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.ConfigurationPolicy;
import org.osgi.service.component.annotations.Reference;
@@ -48,6 +49,7 @@ import
org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;
import org.osgi.service.component.annotations.ReferencePolicyOption;
import org.osgi.service.metatype.annotations.AttributeDefinition;
+import org.osgi.service.metatype.annotations.AttributeType;
import org.osgi.service.metatype.annotations.Designate;
import org.osgi.service.metatype.annotations.ObjectClassDefinition;
@@ -104,6 +106,15 @@ public class GraphQLServlet extends SlingAllMethodsServlet
{
name = "Extensions",
description="Standard Sling servlet property")
String[] sling_servlet_extensions() default "gql";
+
+ @AttributeDefinition(
+ name = "Persisted Queries Cache-Control max-age",
+ description = "The maximum amount of time a persisted query
resource is considered fresh (in seconds). A negative value " +
+ "will be interpreted as 0.",
+ min = "0",
+ type = AttributeType.INTEGER
+ )
+ int cache$_$control_max$_$age() default 60;
}
@Reference
@@ -122,8 +133,17 @@ public class GraphQLServlet extends SlingAllMethodsServlet
{
)
private GraphQLCacheProvider cacheProvider;
+ private final Config config;
+ private final int cacheControlMaxAge;
+
private final JsonSerializer jsonSerializer = new JsonSerializer();
+ @Activate
+ public GraphQLServlet(Config config) {
+ this.config = config;
+ cacheControlMaxAge = config.cache$_$control_max$_$age() >= 0 ?
config.cache$_$control_max$_$age() : 0;
+ }
+
@Override
public void doGet(SlingHttpServletRequest request,
SlingHttpServletResponse response) throws IOException {
String suffix = request.getRequestPathInfo().getSuffix();
@@ -139,6 +159,12 @@ public class GraphQLServlet extends SlingAllMethodsServlet
{
String query = cacheProvider.getQuery(queryHash,
request.getResource().getResourceType(),
request.getRequestPathInfo().getSelectorString());
if (query != null) {
+ boolean isAuthenticated =
request.getHeaders("Authorization").hasMoreElements();
+ StringBuilder cacheControlValue = new
StringBuilder("max-age=").append(cacheControlMaxAge);
+ if (isAuthenticated) {
+ cacheControlValue.append(",private");
+ }
+ response.addHeader("Cache-Control",
cacheControlValue.toString());
execute(query, request, response);
} else {
response.sendError(HttpServletResponse.SC_NOT_FOUND,
"Cannot find persisted query " + queryHash);
@@ -160,7 +186,7 @@ public class GraphQLServlet extends SlingAllMethodsServlet {
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "This servlet
does not support persisted queries.");
return;
}
- String query = IOUtils.toString(request.getInputStream(),
StandardCharsets.UTF_8);
+ String query = IOUtils.toString(request.getReader());
String hash = cacheProvider.cacheQuery(query,
request.getResource().getResourceType(),
request.getRequestPathInfo().getSelectorString());
response.addHeader("Location", getLocationHeaderValue(request,
hash));
@@ -213,7 +239,7 @@ public class GraphQLServlet extends SlingAllMethodsServlet {
StringBuilder location = new StringBuilder();
location.append(request.getScheme()).append("://");
location.append(request.getServerName());
- int localPort = request.getLocalPort();
+ int localPort = request.getServerPort();
if (localPort != 80 && localPort != 443) {
location.append(":").append(localPort);
}
diff --git
a/src/test/java/org/apache/sling/graphql/core/it/GraphQLCoreTestSupport.java
b/src/test/java/org/apache/sling/graphql/core/it/GraphQLCoreTestSupport.java
index 49a6f87..604f218 100644
--- a/src/test/java/org/apache/sling/graphql/core/it/GraphQLCoreTestSupport.java
+++ b/src/test/java/org/apache/sling/graphql/core/it/GraphQLCoreTestSupport.java
@@ -49,9 +49,7 @@ import static
org.apache.sling.testing.paxexam.SlingOptions.slingScriptingJsp;
import static org.ops4j.pax.exam.CoreOptions.composite;
import static org.ops4j.pax.exam.CoreOptions.junitBundles;
import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
-import static org.ops4j.pax.exam.CoreOptions.vmOptions;
import static org.ops4j.pax.exam.CoreOptions.when;
-import static org.ops4j.pax.exam.CoreOptions.vmOption;
import static org.ops4j.pax.exam.CoreOptions.streamBundle;
import static org.ops4j.pax.exam.cm.ConfigurationAdminOptions.newConfiguration;
@@ -70,7 +68,7 @@ public abstract class GraphQLCoreTestSupport extends
TestSupport {
private final static int STARTUP_WAIT_SECONDS = 30;
@Inject
- private ResourceResolverFactory resourceResolverFactory;
+ protected ResourceResolverFactory resourceResolverFactory;
@Inject
protected SlingRequestProcessor requestProcessor;
@@ -211,6 +209,19 @@ public abstract class GraphQLCoreTestSupport extends
TestSupport {
return executeRequest("POST", path, null, "application/json", new
StringReader(toJSON(body)), 200).getOutputAsString();
}
+ protected MockSlingHttpServletResponse persistQuery(String path, String
query, Map<String, Object> variables) throws Exception {
+ Map<String, Object> body = new HashMap<>();
+ if (query != null) {
+ String queryEncoded = query.replace("\n", "\\n");
+ body.put("query", queryEncoded);
+ }
+ if (variables != null) {
+ body.put("variables", variables);
+ }
+
+ return executeRequest("POST", path + "/persisted", null,
"application/json", new StringReader(toJSON(body)), 201);
+ }
+
protected String toJSON(Object source) {
return JsonWriter.objectToJson(source, JsonSerializer.WRITER_OPTIONS);
}
diff --git
a/src/test/java/org/apache/sling/graphql/core/it/GraphQLServletIT.java
b/src/test/java/org/apache/sling/graphql/core/it/GraphQLServletIT.java
index 31cfced..9f2d45e 100644
--- a/src/test/java/org/apache/sling/graphql/core/it/GraphQLServletIT.java
+++ b/src/test/java/org/apache/sling/graphql/core/it/GraphQLServletIT.java
@@ -18,14 +18,15 @@
*/
package org.apache.sling.graphql.core.it;
-import javax.inject.Inject;
+import java.io.StringReader;
-import static com.jayway.jsonpath.matchers.JsonPathMatchers.hasJsonPath;
-import static com.jayway.jsonpath.matchers.JsonPathMatchers.hasNoJsonPath;
+import javax.inject.Inject;
import org.apache.sling.graphql.api.SchemaProvider;
import org.apache.sling.graphql.core.mocks.ReplacingSchemaProvider;
import org.apache.sling.resource.presence.ResourcePresence;
+import org.apache.sling.servlethelpers.MockSlingHttpServletResponse;
+import org.apache.sling.servlethelpers.internalrequests.SlingInternalRequest;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.Configuration;
@@ -36,8 +37,11 @@ import org.ops4j.pax.exam.spi.reactors.PerClass;
import org.ops4j.pax.exam.util.Filter;
import org.osgi.framework.BundleContext;
-import static org.junit.Assert.assertThat;
+import static com.jayway.jsonpath.matchers.JsonPathMatchers.hasJsonPath;
+import static com.jayway.jsonpath.matchers.JsonPathMatchers.hasNoJsonPath;
import static org.hamcrest.Matchers.equalTo;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
import static
org.ops4j.pax.exam.cm.ConfigurationAdminOptions.factoryConfiguration;
@RunWith(PaxExam.class)
@@ -96,6 +100,19 @@ public class GraphQLServletIT extends
GraphQLCoreTestSupport {
}
@Test
+ public void testPersistedQueries() throws Exception {
+ String queryHash =
"a16982712f6ecdeba5d950d42e3c13df0fc26d008c497f6bf012701b57e02a51";
+ MockSlingHttpServletResponse response =
persistQuery("/graphql/two.gql", "{ currentResource { resourceType name } }",
null);
+ assertEquals("http://localhost/graphql/two.gql/persisted/" +
queryHash, response.getHeader("Location"));
+
+ response = executeRequest("GET", "/graphql/two.gql/persisted/" +
queryHash, null, "application/json", new StringReader(""),200);
+ assertEquals("max-age=60", response.getHeader("Cache-Control"));
+
+ // need another test for a request with an Authorization header
+ }
+
+
+ @Test
public void testOtherExtAndTestingSelector() throws Exception {
executeRequest("GET", "/graphql/two.otherExt", null, null, null, 404);
final String json = getContent("/graphql/two.testing.otherExt",
"query", "{ withTestingSelector { farenheit } }");