-
Notifications
You must be signed in to change notification settings - Fork 66
Working with the REST API
Roxy 1.3 and later allow you to combine MarkLogic's new REST API with your Roxy MVC code, serving up both from the same app server. For such applications, you won't need a proxy for your JavaScript code to be able to hit the REST API on some other port.
As of Roxy 1.4 (currently on the dev branch), you can use the --app-type parameter to specify what kind of application you want. Use this with the "ml new" command when setting up a new project, or follow the tips on this page to update an existing project for the different app types.
ml new my-app --app-type=mvc
This is the default kind of application. Use this to build a Roxy MVC application that does not use the MarkLogic REST API. URL rewriting is controlled by the Roxy rewriter.
ml new my-app --app-type=rest
This type of application uses the MarkLogic REST API but not MVC. With this type of application, you can use the deployer with Application Builder. The new application will not have anything under the src directory, but will have a rest-api directory. Add your source and put your REST API options under $project/rest-api. The deployer will put the options where they need to be. URL rewriting is controlled by the MarkLogic REST rewriter.
ml new my-app --app-type=hybrid
The best of both worlds! With this application type, you can use the REST API and Roxy MVC together. URL rewriting is controlled by the Roxy rewriter.
Activate the REST API settings by specifying the application type, using the app-type property. You'll find it set in deploy/default.properties (as always, don't change it there; copy it to deploy/build.properties to override it). Set the value to "mvc" (the default), "rest", or "hybrid".
- mvc -- the normal type of Roxy MVC XQuery application you've come to know and love
- rest -- an application that relies on the REST API, without using Roxy's MVC structure
- hybrid -- an application that uses both Roxy MVC and REST
Currently there are few differences between "rest" and "hybrid". If you want the REST API you probably want hybrid.
MarkLogic's REST API relies on a set of options to tell it how to search; MarkLogic has a REST API Developer's Guide for details on how to use the options. The REST API code expects to find its options in the modules database at /{group-name}/{appserver-name}/rest-api/.... To make sure your options are put in the right place, put them in your {project-home}/rest-api/. You will need to create these, although you can get examples by generating an Application Builder project and looking in the /{group-name}/{appserver-name}/rest-api/ directory in the modules database that it generates. Put all contents (recursively) of that directory into your {project-home}/rest-api directory and the deployer will make sure it goes to the right place.
Example contents:
$ cd {project-home}
$ find rest-api
rest-api
rest-api/options
rest-api/options/all.xml
rest-api/options/default.xml
rest-api/properties.xml
After running "ml {env} deploy modules", you can test that the REST API was set up correctly by pointing a browser to http://{server}:{port}/v1/search?options=all (assuming the presence of {project-home}/rest-api/options/all.xml. If you get a search:response element back, all's well. If you got an error, then the all.xml options file did not get where it needs to be.
If you to put the options somewhere else, copy the rest-options.dir property from deploy/default.properties to deploy/build.properties and set it to the location of your rest-api directory.
Do not put rest-api under your source directory. It will get deployed with your source code along with everything else, but won't be in the right place, and you'll end up with two sets of files. That could be confusing.
Do not try to get the rest-api into the right place by putting it under src/{group-name}/{appserver-name}/rest-api. If you do, it should work fine -- until the first time you deploy it to a a different group, or to an app server with a different name. The deployer picks these up from your deploy/*.properties files and makes sure everything goes where it needs to be.
The MarkLogic REST API can be configured to meet many needs, but sometimes, you need to write an extension. As of Roxy 1.4, the deployer will deploy extensions in a specified directory. Deploying extensions typically requires running a curl command that includes the names of the supported HTTP verbs and the function parameters as HTTP parameters. Consider this module:
`xquery version "1.0-ml";
module namespace ez = "http://marklogic.com/rest-api/resource/easy";
declare namespace roxy = "http://marklogic.com/roxy";
(: : Just writes the one parameter to the log file. :) declare %roxy:params("thing1=xs:string", "thing2=xs:string") function ez:get( $context as map:map, $params as map:map ) as document-node()* { xdmp:log("ez:get: " || map:get($params, "thing1") || "; " || map:get($params, "thing2")) }; `
Note the use of XQuery annotations, a new feature in MarkLogic 6 (backward compatibility isn't an issue, because this is only relevant to the REST API, which also depends on ML6). More on that in a moment.
Assuming you have this file in ./rest-ext/easy.xqy, the MarkLogic-documented process to deploy this extension to a REST API app server on localhost:8020 is:
curl --anyauth --user admin:admin -X PUT -H "Content-type: application/xquery" \
-d@"./rest-ext/easy.xqy" \
"http://localhost:8020/v1/config/resources/easy?method=get&get:thing1=xs:string&get:thing2=xs:string"
In Roxy 1.4+, you can specify a rest-ext.dir property (default value: "rest-ext.dir=${basedir}/rest-ext"). Put your extension modules there, and the "ml {env} deploy modules" command will construct and execute the HTTP PUT command needed.
In order to build the correct parameters, you module needs to make clear what the parameters are. Take a look at the XQuery annotations in the code:
%roxy:params("thing1=xs:string", "thing2=xs:string")
Roxy will look for annotations of this form as part of the function declarations. The deployer doesn't actually pay attention to the namespace of the annotation; it's looking specifically for "%roxy:params". Inside the annotation, list each parameter and its type.
When calling your new endpoint, don't forget the rs: prefix on the parameters, as required by MarkLogic:
http://localhost:8020/v1/resources/easy?rs:thing1=foo&rs:thing2=bar
Put any library modules that your extensions need under your src directory (src/app/models/ for hybrid apps). The deployer will upload the contents of src normally.
If you look at the code generated by Application Builder, you will see that REST API extensions and transformations get put into the "http://marklogic.com/extension/plugin" collection. The Roxy deployer will do that for source code under src/marklogic.rest.*, which is where this code will need to be for the REST API to find it. To see examples of this, take a look at a modules database generated by Application Builder.