Add POST body support to update api (#252)

This commit is contained in:
Ben 2022-04-07 09:34:34 -05:00 committed by GitHub
parent b8944fb3bf
commit 733a88ddcb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -8,6 +8,7 @@ import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
import static javax.servlet.http.HttpServletResponse.SC_OK; import static javax.servlet.http.HttpServletResponse.SC_OK;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet; import javax.servlet.annotation.WebServlet;
@ -18,6 +19,8 @@ import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import static org.apache.jena.riot.web.HttpNames.paramUsingGraphURI;
import static org.apache.jena.riot.web.HttpNames.paramUsingNamedGraphURI;
import org.apache.jena.query.Dataset; import org.apache.jena.query.Dataset;
import org.apache.jena.query.ReadWrite; import org.apache.jena.query.ReadWrite;
import org.apache.jena.update.GraphStore; import org.apache.jena.update.GraphStore;
@ -25,6 +28,9 @@ import org.apache.jena.update.GraphStoreFactory;
import org.apache.jena.update.UpdateAction; import org.apache.jena.update.UpdateAction;
import org.apache.jena.update.UpdateFactory; import org.apache.jena.update.UpdateFactory;
import org.apache.jena.update.UpdateRequest; import org.apache.jena.update.UpdateRequest;
import org.apache.jena.graph.Node;
import org.apache.jena.graph.NodeFactory;
import org.apache.jena.sparql.modify.UsingList;
import edu.cornell.mannlib.vitro.webapp.application.ApplicationUtils; import edu.cornell.mannlib.vitro.webapp.application.ApplicationUtils;
import edu.cornell.mannlib.vitro.webapp.auth.permissions.SimplePermission; import edu.cornell.mannlib.vitro.webapp.auth.permissions.SimplePermission;
@ -76,27 +82,48 @@ public class SparqlUpdateApiController extends VitroApiServlet {
private UpdateRequest parseUpdateString(HttpServletRequest req) private UpdateRequest parseUpdateString(HttpServletRequest req)
throws ParseException { throws ParseException {
String update = req.getParameter("update"); InputStream update;
if (StringUtils.isBlank(update)) { String reqtype = req.getContentType();
UsingList usingList = processProtocol(req);
// Support update via both POST body and an 'update' parameter
if (reqtype.equalsIgnoreCase("application/sparql-update")) {
try {
update = req.getInputStream();
} catch (IOException e) {
log.debug("Error parsing POST body.");
throw new ParseException("Error parsing POST body.");
}
}
else {
String updateString = req.getParameter("update");
if (StringUtils.isBlank(updateString)) {
log.debug("No update parameter."); log.debug("No update parameter.");
throw new ParseException("No 'update' parameter."); throw new ParseException("No 'update' parameter.");
} }
if (!StringUtils.containsIgnoreCase(updateString, "GRAPH") && !StringUtils.containsIgnoreCase(updateString, "WITH")) {
if (!StringUtils.containsIgnoreCase(update, "GRAPH") && !StringUtils.containsIgnoreCase(update, "WITH")) {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("No GRAPH or WITH uri in '" + update + "'"); log.debug("No GRAPH or WITH uri in '" + updateString + "'");
} }
throw new ParseException("SPARQL update must specify a GRAPH ( or WITH) URI."); throw new ParseException("SPARQL update must specify a GRAPH ( or WITH) URI.");
} }
try {
update = org.apache.commons.io.IOUtils.toInputStream(updateString, "UTF-8");
} catch (IOException e) {
log.debug("Error parsing POST body.");
throw new ParseException("Error parsing POST body.");
}
}
try { try {
return UpdateFactory.create(update); return UpdateFactory.read(usingList, update);
} catch (Exception e) { } catch (Exception e) {
log.debug("Problem parsing", e); log.debug("Problem parsing", e);
throw new ParseException("Failed to parse SPARQL update", e); throw new ParseException("Failed to parse SPARQL update", e);
} }
} }
private void executeUpdate(HttpServletRequest req, UpdateRequest parsed) { private void executeUpdate(HttpServletRequest req, UpdateRequest parsed) {
VitroRequest vreq = new VitroRequest(req); VitroRequest vreq = new VitroRequest(req);
SearchIndexer indexer = ApplicationUtils.instance().getSearchIndexer(); SearchIndexer indexer = ApplicationUtils.instance().getSearchIndexer();
@ -121,6 +148,35 @@ public class SparqlUpdateApiController extends VitroApiServlet {
} }
} }
/*
* The method below and the 'createNode' helper were
* adapted from the Fuseki source code
*/
private UsingList processProtocol(HttpServletRequest request) {
UsingList toReturn = new UsingList();
String[] usingArgs = request.getParameterValues(paramUsingGraphURI);
String[] usingNamedArgs = request.getParameterValues(paramUsingNamedGraphURI);
if ( usingArgs == null && usingNamedArgs == null )
return toReturn;
if ( usingArgs == null )
usingArgs = new String[0];
if ( usingNamedArgs == null )
usingNamedArgs = new String[0];
// Impossible.
// if ( usingArgs.length == 0 && usingNamedArgs.length == 0 )
// return;
for ( String nodeUri : usingArgs ) {
toReturn.addUsing(createNode(nodeUri));
}
for ( String nodeUri : usingNamedArgs ) {
toReturn.addUsingNamed(createNode(nodeUri));
}
return toReturn;
}
private void do200response(HttpServletResponse resp) throws IOException { private void do200response(HttpServletResponse resp) throws IOException {
sendShortResponse(SC_OK, "SPARQL update accepted.", resp); sendShortResponse(SC_OK, "SPARQL update accepted.", resp);
} }
@ -158,4 +214,14 @@ public class SparqlUpdateApiController extends VitroApiServlet {
} }
} }
private static Node createNode(String x) {
try {
return NodeFactory.createURI(x);
} catch (Exception ex) {
log.debug("SPARQL Update: bad IRI: "+x);
return null;
}
}
} }