URI templates: Is there an rfc-6570 implementation in javascript?
Asked Answered
I

4

13

I am using node and express. To register a controller I call:

app.get('/user/:id', function (req, res) {...});  

But I would like to do it the rfc-6570 way:

app.get('/user/{id}', function (req, res) {...});

I googled just an implementation in python on google code, but found nothing (except the dead link on google code to http://www.snellspace.com/wp/?p=831) for JavaScript.

URI templating in general is not so easy as it looks on the first sight. Have a look on the examples in the RFC.

PS: I will need the URI templates on the client, too.

Islean answered 5/5, 2012 at 17:12 Comment(8)
That RFC is only two months old; I wouldn't be surprised if there aren't any compliant implementations for awhile...Olnek
Out of curiosity, why do you want to use that RFC instead of the form that Express provides?Olnek
First, the rfc is only 2 months old. But the drafts are about 3 years old.Islean
Second, I want to use the RFC way, because I have a mixed environment on the server: express and java/spring. Spring is using the rfc style (closely). I want to use the same templates with spring and express -- and in the user agent, of course. The rfc way is much more expressive than the express/(ruby?) wayIslean
and finally Third, if there is no implementation, I will create one ;-)Islean
AFAICT, RFC 6570 is for parsing templates as a Consumer, not for specifying a syntax accepted by a Provider. It goes from URI Template + Variables to URL, not the other way around.Kalif
please see #19919623Auroora
@Islean 4.5yrs in, can we still count on your library? :)Olden
I
8

I've been cleaning up the implementations list at http://code.google.com/p/uri-templates/wiki/Implementations - there is a JS one at https://github.com/marc-portier/uri-templates but I'm not sure of whether it implements the RFC, nor of what its quality is.

Note that we've started publishing tests here: https://github.com/uri-templates/uritemplate-test

So if you want to check it, you could start there.

Imparipinnate answered 17/5, 2012 at 6:44 Comment(3)
Thank you! I will integrate the tests when implementing. The work of marc portier is fine, but it can only parse a template and expand it to an URI. But the difficult part is to extract the variables of a given URI with a uriTemplate. As You wrote in the last paragraph of 1.5 in the rfc: "Some URI Templates can be used in reverse for the purpose of variable matching: comparing the template to a fully formed URI in order to extract the variable parts from that URI and assign them to the named variables."Islean
@Islean Have you implement it somewhere? I'd like to do similar thing and will have to create one too, anywhere I can join?Deathful
@Islean Sorry, somehow missed that you are probably fxa from github ;)Deathful
C
4

As of June 2014, these JavaScript implementations seem most complete (Level 4 of the spec) and tested. All three also support both the browser and node.js.

Companionway answered 30/6, 2014 at 10:33 Comment(0)
A
0

Regarding the express router part I would recommend to use your uri templates within a hyperschema (read more) ...

Then you could also benefit from regex for your router which express.js supports. Regarding resolving the parameters you need an RFC 6570 implementation like https://github.com/geraintluff/uri-templates ...

Here is some .js code to illustrate the rewriting of a hyperschema USING RFC 6570 to convert it to an express js router:

  var hyperschema = {
  "$schema": "http://json-schema.org/draft-04/hyper-schema",
  "links": [
    {
      "href": "{/id}{/ooo*}{#q}",
      "method": "GET",
      "rel": "self",
      "schema": {
        "type": "object",
        "properties": {
          "params": {
            "type": "object",
            "properties": {
              "id": {"$ref": "#/definitions/id"}
            },
            "additionalProperties": false
          }
        },
        "additionalProperties": true
      }
    }
  ],
  "definitions": {
    "id": {
      "type": "string",
      "pattern": "[a-z]{0,3}"
    }
  }
}
  var deref = require('json-schema-deref');
  var tv4 = require('tv4');
  var url = require('url');
  var rql = require('rql/parser');

// DOJO lang AND _
function getDottedProperty(object, parts, create) {
    var key;
    var i = 0;

    while (object && (key = parts[i++])) {
        if (typeof object !== 'object') {
            return undefined;
        }
        object = key in object ? object[key] : (create ? object[key] = {} : undefined);
    }

    return object;
}
function getProperty(object, propertyName, create) {
    return getDottedProperty(object, propertyName.split('.'), create);
}
function _rEscape(str) {
  return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}

function getPattern(k, ldo, customCat) {
  // ...* = explode = array
  // ...: = maxLength
  var key = ((k.slice(-1) === '*') ? k.slice(0,-1) : k).split(':')[0];
  var cat = (customCat) ? customCat : 'params'; // becomes default of customCat in TS
  var pattern = '';
  if (typeof ldo === 'object' && ldo.hasOwnProperty('schema')) {
    var res = getProperty(ldo.schema, ['properties',cat,'properties',key,'pattern'].join('.'));
    if (res) {
      console.log(['properties',cat,'properties',key,'pattern'].join('.'),res);
      return ['(',res,')'].join('');
    }
  }
  return pattern;
}
function ldoToRouter(ldo) {
  var expression = ldo.href.replace(/(\{\+)/g, '{') // encoding
    .replace(/(\{\?.*\})/g, '') // query
    .replace(/\{[#]([^}]*)\}/g, function(_, arg) {
      // crosshatch
      //console.log(arg);
      return ['(?:[/]*)?#:',arg,getPattern(arg,ldo,'anchor')].join('');
    })
    .replace(/\{([./])?([^}]*)\}/g, function(_, op, arg) {
      // path seperator
      //console.log(op, '::', arg, '::', ldo.schema);
      return [op,':',arg,getPattern(arg,ldo)].join('');
    });
    return {method: ldo.method.toLowerCase(), args:[expression]};
}

deref(hyperschema, function(err, fullSchema) {
  console.log('deref hyperschema:',JSON.stringify(fullSchema));
  var router = fullSchema.links.map(ldoToRouter);

  console.log('router:',JSON.stringify(router));
});
Auroora answered 30/10, 2015 at 18:55 Comment(0)
O
0

Might not be exactly what you are looking for, but the closest you can get in terms of a native implementation, is URLPattern. It's currently experimental and browser support is limited.

Ohalloran answered 8/1 at 17:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.