Handy-URI-Templates icon indicating copy to clipboard operation
Handy-URI-Templates copied to clipboard

Reverse variable matching

Open aslakhellesoy opened this issue 12 years ago • 37 comments

I couldn't find any information about this in the docs or by skimming the source code. For example - given a template /foo/{name}/bar/{id} and a URI /foo/hello/bar/world - be able to extract the name and id variables with values hello and world respectively.

Would this be within the scope of this library? The wo-furi library supports this, but since that library seems abandoned and implements an older version of the spec I'm looking for something else.

FWIW, I'd like to use this in webbit-rest

aslakhellesoy avatar Jun 29 '12 09:06 aslakhellesoy

Follow-up - the ruby addressable project has an implementation that does this: https://github.com/sporkmonger/addressable/blob/master/lib/addressable/template.rb

It essentially turns the pattern into a regexp and then matches against the uri and then loops over the capture groups to extract variable values.

aslakhellesoy avatar Jun 29 '12 09:06 aslakhellesoy

If I'm understanding this correctly, you want to see if a URI matches a given expression and if it does, you want to be able extract the variable values from the URI? Obvious use case to match request URIs to patterns on the server. If that correct?

damnhandy avatar Jun 29 '12 11:06 damnhandy

Yes, that's exactly it. As mentioned in section 1.4 in the spec:

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.

aslakhellesoy avatar Jun 29 '12 11:06 aslakhellesoy

Got it. I'll target this for the 1.2 release. I have been refactoring the code a bit to separate the expression model from the template in order to make issue #1 a bit easier. This feature request fits nicely into the same refactoring. It'll take a few more days but doable.

damnhandy avatar Jun 29 '12 11:06 damnhandy

+1 to this request. Would be extremely useful for a web framework I'm writing.

mwanji avatar Aug 16 '12 10:08 mwanji

I've been working on this here and there over the past few months and it's nearly complete. As a result of this new functionality, it will change the API considerably. For starters, the UriTemplate will now be immutable and there will be a UriTemplate.Builder class that will be used to programmatically construct a URI template. Lastly, this change will introduce a UriMatcher that will match a URI against a URI template pattern.

damnhandy avatar Aug 20 '12 13:08 damnhandy

+1 to this request.

Has been any advance in this issue?

Is there any schedule for release?

We're needing this so bad that we'll roll our own if not available.

lalloni avatar Sep 04 '12 17:09 lalloni

Realistically, it's 2 to 3 weeks out. Juggling summer and my day job, just getting back into the swing of things

damnhandy avatar Sep 04 '12 17:09 damnhandy

+1. I'm in the same boat as plalloni. Will either have to deal with wo-furi or roll our own and then hopefully replace with Handy when this feature is available.

While I'm at it the other thing we will need to layer on top is to be able to pick the "best" match for a given URI from a set of candidate URITemplates

kminder avatar Oct 22 '12 15:10 kminder

On the subject of reverse mapping, this is a bit more challenging that one might think. This is especially true when you start looking at reverse mapping for level 3 and level 4 expression types. level 1 and level 2 expressions are fairly straight forward and that's close to what wo-furi supports now. I've been proceeding with the idea of trying to be bale to reverse map level 4 expressions. If folks find levels 1 and 2 acceptable for the time being, that's a tad easier.

On the topic of rolling your own implementation, let's remember that this is GitHub and this is an open source project. I'm pretty liberal on contributions. I've already taken in a few bug fixes and feature contributions are more than welcome.

damnhandy avatar Oct 22 '12 20:10 damnhandy

Got back to this after some time. After all we just went with ugly hand made uri parsing & building.

@damnhandy I think level 1 & 2 would be great and enough for most cases.

@damnhandy WRT "roll our own": at that time, I was talking about rolling our own just because we target the scala language, not java, so if any effort would've been undertaken it would've been more gain for us if we offered a scala API

lalloni avatar May 16 '13 14:05 lalloni

Same here @plalloni , been a while. I've restructured the code to better support this as the initial design presented some problems. There's going to be some API changes, but this will pave the way to reverse matching as well as much better feedback on parsing errors. Version 2.0 should be available in a few days and then we'll get reverse matching in 2.1.

damnhandy avatar Jul 11 '13 12:07 damnhandy

Just a heads up, I'm planning on using Java 7 since the regex supports named groups, which in turn will make this process a lot easier. If anyone has any objections, please let me know. I'm also assuming that since Java 6 was EOL'd back in February, most folks have moved on from Java 6.

damnhandy avatar Sep 24 '13 10:09 damnhandy

+1 for the request; as a temporary measure, adding the URITemplateResolver and test from 2.1 branch in the 2.0 trunk using Java7 tests ok. Any status on level 3/4 resolution ?

henrib avatar Nov 21 '13 11:11 henrib

What is the state on this? I could not find any Class to perform matching or variable extraction :)

felipesere avatar Apr 15 '14 07:04 felipesere

@felipesere take a look at this class: https://github.com/damnhandy/Handy-URI-Templates/blob/2.1-branch/src/main/java/com/damnhandy/uri/template/UriTemplateResolver.java

faisalferoz avatar Aug 02 '14 17:08 faisalferoz

That looks pretty interesting. I'd like to go over the code and make a pull request. Should I do it against Master or the 2.1-branch?

felipesere avatar Aug 02 '14 22:08 felipesere

IMO should be against 2.1- branch. @damnhandy shud be able to tell better since he is the owner of the project.

faisalferoz avatar Aug 03 '14 09:08 faisalferoz

Yes @faisalferoz, use the 2.1 branch.

damnhandy avatar Aug 03 '14 14:08 damnhandy

I think this is a very useful feature. Is this feature available in the current 2.0.4 release? If not when will be added to a GA release?

Thanks, Kasun.

kasun04 avatar Oct 26 '15 04:10 kasun04

came looking for this functionality...how close is it? is there any stepping stones? what is this regex pattern stuff?

drdamour avatar Feb 23 '16 04:02 drdamour

Although an old issue, I think this is still a very useful and desirable feature. I'd be willing to put some time in to development if @damnhandy can point me in the right direction.

nrktkt avatar May 18 '16 15:05 nrktkt

@kag0 I could definitely use a hand on defining the API for this feature and some test cases.

When I started the 2.x release, I refactored everything so that there is a structured model that represents the URI Template. A URI template consists of a collection of URITemplateComponent instances, which has two specializations:

  • Expression: this represents the a URI template expression such as {?foo}, etc.
  • Literal which represents the bits that are not URI template expressions

An Expression is composed of an Operator and a collection of VarSpec instances. The model goes something like this:

  • UriTemplate:
    • UriTemplateComponent:
      • Literal
      • Expression:
        • Operator
        • VarSpec

What I had intended to do here is generate a regex match string for each VarSpec, which the Expression could then use build a regex for the expression, all the way up to the UriTemplate level.

Getting the regexes correct had been frustrating, mainly because I suck at it :) I'm not entirely sure the approach I'm taking is ideal, but it seemed to make sense at the time. The last tricky bit is getting the reverse matching accuracy down. In places, it's going to be tough to distinguish which URI matches given template given how the regex is constructed.

damnhandy avatar Jul 03 '16 16:07 damnhandy

@damnhandy that seems like a reasonable way to go about it. I'll start playing around with it. Is master the best branch to look at as far as reverse matching changes?

nrktkt avatar Jul 03 '16 21:07 nrktkt

Use the 2.2-reverse-matching branch. Let's keep it out of master for now. The work I had done to date on this feature had led to other bugs, so I'd rather keep this in a separate branch for the time being.

damnhandy avatar Jul 03 '16 22:07 damnhandy

@damnhandy I've taken a quick 'n dirty stab at it here and jotted some notes. Check it out if you think you might have some comment, otherwise I'll keep working at it.

nrktkt avatar Jul 04 '16 05:07 nrktkt

This looks good. Can you issue a PR to the 2.2-reverse-matching branch? Next step is to figure out how to integrate this into the project. The furi project that @aslakhellesoy mentioned has a dedicated URIResolver class to perform the reverse lookup. We could do something similar, but I'm not sure about the multiple matching rules approach. An suggestions are appreciated.

damnhandy avatar Aug 03 '16 11:08 damnhandy

@damnhandy checked out furi. Could be something there, but might be tricky given how the structures of the two libraries are different. In the meantime I went ahead and finished the feature more or less.

nrktkt avatar Aug 15 '16 02:08 nrktkt

Awesome! /me is eagerly anticipating 2.2 now :-)

brianm avatar Sep 01 '16 16:09 brianm

Hey @damnhandy, just checkin in. Is there anything that could be done to help speed up a 2.2 release?

nrktkt avatar Dec 17 '16 20:12 nrktkt