Arbitrary JS code execution
In out client system we need to implement a mechanism for automatic incremental database migration. For that we need to execute a number of (potentially complex) migration scripts on the ArangoDB server. Something like one would do in Arangosh, but it needs to be done from a Java application.
My first attempt was to utilize the db.transaction() method. Unfortunately due to Arango's inability to create/delete collections and indices from inside a transaction it's not suitable for our needs.
Now I'm looking at the POST /_admin/execute hoping that it does exactly what I need. But I cannot find a way to invoke this API via the Arango Java driver.
Is there any way to call POST /_admin/execute from a Java driver?
Thanks!
You can build arbitrary requests and execute them using ArangoDB#execute(Request):
https://github.com/arangodb/arangodb-java-driver/blob/d00ddb1afe787199e604424020475953defd46b3/src/main/java/com/arangodb/ArangoDB.java#L798-L805
Thanks Michele. I tried that but couldn't create a request body object. I might be doing something wrong, could you please correct me? The aforementioned POST accepts a javascript block as a string. The Request.body filed however has a type VPackSlice which (if I get it right) is sort of a binary representation of JSON. How would I serialize e.g "console.log('test');" string to a VPackSlice?
In general, you can serialize the body in this way:
ArangoSerialization serializer = arangoDB.util();
// or using user custom serializer
// ArangoSerialization serializer = arangoDB.util(ArangoSerializationFactory.Serializer.CUSTOM);
Request request = new Request("_system", RequestType.POST, "/_admin/execute");
String code = "console.log('test');";
VPackSlice body = serializer.serialize(code);
request.setBody(body);
Response response = arangoDB.execute(request);
// ...
If the driver is configured with Protocol.HTTP_JSON then the VPackSlice will be automatically converted to JSON.
Nevertheless I have just realized that POST /_admin/execute decodes the body as text/plain, while the VPack serializer encodes it as a JSON string (a quoted string). So the entire payload is interpreted as a javascript string rather than code to be evaluated.
Therefore at the moment I don't see any way to call POST /_admin/execute from the Java driver and more in general to perform any request with content type other than application/json.
Thanks for the prompt response. That's what I ended up with as well. It would be great to have that ability in the driver. Meantime I'll use a separate HTTP connection for that request.
Server bug tracked here: https://arangodb.atlassian.net/jira/software/c/projects/BTS/issues/BTS-209
Fixed on the server side: https://github.com/arangodb/arangodb/pull/17426 It should be released in ArangoDB 3.11.
Closing as fixed, tested in https://github.com/arangodb/arangodb-java-driver/commit/ca34bd9aa35a3ea8b8a1075c349168489537b427