A Hello World Example

    In the following example, we want to define an action in ArangoDB, so that theserver returns the HTML document

    if asked GET /hello/world.

    The server needs to know what function to call or what document to deliver if itreceives a request. This is called routing. All the routing information ofArangoDB is stored in a collection _routing. Each entry in this collectionsdescribes how to deal with a particular request path.

    For the above example, add the following document to the _routing collection:

    1. arangosh> db._routing.save({
    2. ........> url: {
    3. ........> match: "/hello/world"
    4. ........> },
    5. ........> content: {
    6. ........> contentType: "text/html",
    7. ........> body: "<html><body>Hello World</body></html>"
    8. ........> }
    9. ........> });

    Show execution results

    1. {
    2. "_id" : "_routing/7894",
    3. "_key" : "7894",
    4. "_rev" : "_ZHpYWHS--_"
    5. }

    Hide execution results

    In order to activate the new routing, you must either restart the server or callthe internal reload function.

    1. arangosh> require("internal").reloadRouting()

    Show execution results

    1.  

    Hide execution results

    Now use the browser and access http:// localhost:8529/hello/world

    You should see the Hello World in our browser:

    1.  

    Show execution results

    1. shell> curl --header 'accept: application/json' --dump - http://localhost:8529/hello/world
    2.  
    3. HTTP/1.1 200 OK
    4. content-type: text/html
    5. x-content-type-options: nosniff
    6.  
    7. "Hello World"

    Hide execution results

    There are a lot of options for the url attribute. If you define differentrouting for the same path, then the following simple rule is applied in order todetermine which match wins: If there are two matches, then the more specificwins. I. e, if there is a wildcard match and an exact match, the exact match ispreferred. If there is a short and a long match, the longer match wins.

    If the definition is

    1. url: {
    2. match: "/hello/world"
    3. }
    4. }

    The following definition is a short-cut for an exact match.

    Note: While the two definitions will result in the same URLmatching, there is a subtle difference between them:

    The former definition (defining url as an object with a match attribute)will result in the URL being accessible via all supported HTTP methods (e.g.GET, POST, PUT, DELETE, …), whereas the latter definition (providing a stringurl attribute) will result in the URL being accessible via HTTP GET and HTTP HEAD only, with all other HTTP methods being disabled. Calling a URLwith an unsupported or disabled HTTP method will result in an HTTP 501 (not implemented) error.

    Prefix Match

    If the definition is

    1. {
    2. url: {
    3. match: "/hello/world/*"
    4. }
    5. }

    then the match can be a prefix match. The requests for /hello/world,/hello/world/my, and /hello/world/how/are/you will all match. However/hello/world2 does not match. Prefix matches within a URL part,i. e. /hello/world*, are not allowed. The wildcard must occur at the end,i. e.

    1. /hello/*/world

    is also disallowed.

    If you define two routes

    1. { url: { match: "/hello/world/*" } }
    2. { url: { match: "/hello/world/emil" } }

    then the second route will be used for /hello/world/emil because it is morespecific.

    A parameterized match is similar to a prefix match, but the parameters are alsoallowed inside the URL path.

    If the definition is

    1. {
    2. url: {
    3. match: "/hello/:name/world"
    4. }
    5. }

    then the URL must have three parts, the first part being hello and the thirdpart world. For example, /hello/emil/world will match, while/hello/emil/meyer/world will not.

    Constraint Match

    A constraint match is similar to a parameterized match, but the parameters cancarry constraints.

    If the definition is

    1. {
    2. match: "/hello/:name/world",
    3. constraint: {
    4. name: "/[a-z]+/"
    5. }
    6. }
    7. }

    then the URL must have three parts, the first part being hello and the thirdpart world. The second part must be all lowercase.

    It is possible to use more then one constraint for the same URL part.

    1. {
    2. url: {
    3. match: "/hello/:name|:id/world",
    4. constraint: {
    5. name: "/[a-z]+/", id: "/[0-9]+/"
    6. }
    7. }
    8. }

    If the definition is

    1. {
    2. url: {
    3. match: "/hello/:name?",
    4. constraint: {
    5. }
    6. }
    7. }

    then the URL /hello and /hello/emil will match.

    If the definitions are

    then the URL /hello/world will be matched by the first route, because it isthe most specific. The URL /hello/you will be matched by the second route,because it is more specific than the prefix match.

    Method Restriction

    You can restrict the match to specific HTTP methods.

    If the definition is

    1. {
    2. url: {
    3. match: "/hello/world",
    4. methods: [ "post", "put" ]
    5. }
    6. }

    then only HTTP POST and PUT requests will match.Calling with a different HTTP method will result in an HTTP 501 error.

    Please note that if url is defined as a simple string, then only theHTTP methods GET and HEAD will be allowed, an all other methods will bedisabled:

    1. {
    2. url: "/hello/world"
    3. }

    Remember that the more specific match wins.

    • A match without parameter or wildcard is more specific than a match withparameters or wildcard.
    • A match with parameter is more specific than a match with a wildcard.
    • If there is more than one parameter, specificity is applied from left toright.Consider the following definitions
    1. arangosh> db._routing.save({
    2. ........> url: { match: "/hello/world" },
    3. ........> content: { contentType: "text/plain", body: "Match No 1"} });
    4. arangosh> db._routing.save({
    5. ........> url: { match: "/hello/:name", constraint: { name: "/[a-z]+/" } },
    6. ........> content: { contentType: "text/plain", body: "Match No 2"} });
    7. arangosh> db._routing.save({
    8. ........> url: { match: "/:something/world" },
    9. ........> content: { contentType: "text/plain", body: "Match No 3"} });
    10. arangosh> db._routing.save({
    11. ........> url: { match: "/hi/*" },
    12. ........> content: { contentType: "text/plain", body: "Match No 4"} });
    13. arangosh> require("internal").reloadRouting()

    Show execution results

    1. {
    2. "_id" : "_routing/7908",
    3. "_key" : "7908",
    4. "_rev" : "_ZHpYWKm--_"
    5. {
    6. "_id" : "_routing/7912",
    7. "_key" : "7912",
    8. "_rev" : "_ZHpYWKm--B"
    9. }
    10. {
    11. "_id" : "_routing/7915",
    12. "_key" : "7915",
    13. "_rev" : "_ZHpYWKq--_"
    14. }
    15. {
    16. "_id" : "_routing/7918",
    17. "_key" : "7918",
    18. "_rev" : "_ZHpYWKq--B"
    19. }

    Hide execution results

    Then

    1.  

    Show execution results

    1. shell> curl --header 'accept: application/json' --dump - http://localhost:8529/hello/world
    2.  
    3. HTTP/1.1 200 OK
    4. content-type: text/plain
    5. x-content-type-options: nosniff
    6.  
    7. "Match No 1"
    8. shell> curl --header 'accept: application/json' --dump - http://localhost:8529/hello/emil
    9.  
    10. HTTP/1.1 200 OK
    11. content-type: text/plain
    12. x-content-type-options: nosniff
    13.  
    14. "Match No 2"
    15. shell> curl --header 'accept: application/json' --dump - http://localhost:8529/your/world
    16.  
    17. HTTP/1.1 200 OK
    18. content-type: text/plain
    19. x-content-type-options: nosniff
    20.  
    21. "Match No 3"
    22. shell> curl --header 'accept: application/json' --dump - http://localhost:8529/hi/you
    23.  
    24. HTTP/1.1 200 OK
    25. content-type: text/plain
    26. x-content-type-options: nosniff
    27.  
    28. "Match No 4"

    Hide execution results

    You can write the following document into the _routing collectionto test the above examples.

    1. {
    2. routes: [
    3. { url: { match: "/hello/world" }, content: "route 1" },
    4. { url: { match: "/hello/:name|:id", constraint: { name: "/[a-z]+/", id: "/[0-9]+/" } }, content: "route 2" },
    5. { url: { match: "/:something/world" }, content: "route 3" },
    6. { url: { match: "/hello/*" }, content: "route 4" },