Skip to content

dscape/rewrite

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

87 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

rewrite

rewrite is an implementation of MarkLogic's URL Rewriter for HTTP Application Servers. rewrite aims to provide an expressive language that allows you to specify REST applications. This is intended to make your routing logic simple and easy to maintain:

<routes>
  <root> dashboard#show </root> 
  <resource name="inbox"> <!-- no users named inbox --> 
    <member action="sent"/> 
  </resource> 
  <resource name=":user"> 
    <constraints>  
      <user type="string" match="^[a-z]([a-z]|[0-9]|_|-)*$"/> 
    </constraints> 
    <member action="followers"/> <!-- no repo named followers --> 
    <resource name=":repo"> 
      <constraints>  
        <repo match="^[a-z]([a-z]|[0-9]|_|-|\.)*$"/> 
      </constraints> 
      <member action="commit/:commit"> 
        <constraints>  
          <commit type="string" match="[a-zA-Z0-9]+"/> 
        </constraints> 
      </member> 
      <member action="tree/:tag" /> 
      <member action="forks" /> 
      <member action="pulls" /> 
      <member action="graphs/impact" /> 
      <member action="graphs/language" /> 
    </resource> 
  </resource>
</routes>

Routes are matched in the order you specified and they can be nested. They are dispatched dispatched to a resource XQuery file providing the action as a request field.

rewrite also enables you to hide specific routes from users given specific constraints.

rewrite is designed to work with MarkLogic Server only. However it can easily be ported to another product that understands XQuery and has similar capabilities. rewrite is heavily inspired in the Rails 3.0 routing.

Usage

In your HTTP Application Server configuration make rewrite.xqy the default rewriter script.

This section doesn't cover how to set up an HTTP Application Server in MarkLogic. If you are a beginner I suggest you start by browsing the MarkLogic Developer Community site or sign up for training.

Place the lib folder of rewrite in your application root. Still in the root create a new file named rewrite.xqy with the following contents:

xquery version "1.0-ml" ;

import module namespace r = "routes.xqy" at "/lib/routes.xqy" ;

declare variable $routesCfg := 
  <routes>
    <root> users#list </root>
    <get path="users/:id">
      <to> users#show </to>
    </get>
  </routes> ;

r:selectedRoute( $routesCfg )

With the rewrite in place:

  • Request / will be dispatched to /resource/users.xqy?action=list
  • Request /users/dscape will be dispatched to /resource/users.xqy?action=show&id=dscape

You can customize the file path and/or store configurations in a file. If you are curious on how the translation from path to file is done refer to "Supported Features".

Here's an example of how your users.xqy might look like:

xquery version "1.0-ml";

import module namespace u = "user.xqy" at "/lib/user.xqy";
import module namespace h = "helper.xqy" at "/lib/helper.xqy";

declare function local:list() { u:list() };
declare function local:get()  { u:get( h:id() ) } ;

try          { xdmp:apply( h:function() ) } 
catch ( $e ) { h:error( $e ) }

A centralized error handler can also be used removing the need for a try catch statement. Refer to the wiki section on using an error handler for instructions.

This assumes a hypothetical users.xqy XQuery library that models users. It also contains a helper.xqy module. The helper.xqy module is contained in lib as an example but is not part of rewrite, so you can/should modify it to fit your needs; or even create your fully fledged MVC framework.

Supported Elements

Name Type Meaning More Info
Root Route Responds to GET requests to the root of the application Wiki
Get Route Responds to GET requests for a given path Wiki
Put Route Responds to PUT requests for a given path Wiki
Delete Route Responds to DELETE requests for a given path Wiki
Post Route Responds to POST requests for a given path Wiki
Head Route Responds to HEAD requests for a given path Wiki
Resources Multiple Routes Creates a RESTful Resource addressable by :id Wiki
Resource Multiple Routes Creates a singleton RESTful Resource Wiki

Supported Functionality

Name Type Meaning More Info
Static Files Static Serving static files Wiki
Constraints Constraint Makes rules invisible given constraints Wiki
Scopes Scope Propagates environment, e.g. constraints. Wiki
Route Globbing Globbing Allows wildcard routes Wiki

Sample Application

You can find a sample applications in the Samples wiki page. Just follow the instructions in the read me file to deploy. If you used rewrite and want to contribute a sample application just add it to the wiki page.

Contribute

Think the documentation sucks? Think the performance is crap? Think rewrite is cool but is missing feature X? This is your change to shine: contribute to the project.

  1. Message dscape on github talking about what you want to accomplish.
  2. Fork rewrite in github
  3. Create a new branch - git checkout -b my-branch
  4. Develop/fix the functionality
  5. Test your changes
  6. Commit your changes
  7. Push to your branch - git push origin my-branch
  8. Create an pull request

Running the tests

To run the tests simply point an MarkLogic HTTP AppServer to the root of rewrite

You can run the tests by accessing: (assuming 127.0.0.1 is the host and 8090 is the port)

http://127.0.0.1:8090/test/

Make sure all the tests pass before sending in a pull request!

Report a bug

If you want to contribute with a test case please file a issue and attach the following information:

  • Request method, request path, and other parts of the request that are relevant (e.g. request headers)
  • routes.xml
  • paths.xml (if relevant)

Meta

(oO)--',- in caos

About

MarkLogic rewrite logic made simple

Resources

License

Stars

Watchers

Forks

Packages

No packages published