Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Potential bug/Unspecified behaviour #34

Open
sigmavirus24 opened this issue Jun 24, 2017 · 4 comments
Open

Potential bug/Unspecified behaviour #34

sigmavirus24 opened this issue Jun 24, 2017 · 4 comments

Comments

@sigmavirus24
Copy link
Collaborator

Let's look at a template like this:

http://example.com/dictionary/{term:1}

We have two different behaviours depending upon the value used to expand term.

>>> import uritemplate
>>> u = uritemplate.URITemplate('http://example.com/dictionary/{term:1}')
>>> u.expand(term='foo')
'http://example.com/dictionary/f'
>>> u.expand(term=['foo', 'bar', 'bogus'])
'http://example.com/dictionary/foo,bar,bogus'

A simplified version of this is simply

{term:1}

In other words:

>>> import uritemplate
>>> u = uritemplate.URITemplate('{term:1}')
>>> u.expand(term='foo')
'f'
>>> u.expand(term=['foo', 'bar', 'bogus'])
'foo,bar,bogus'

All versions of uritemplate (and uritemplate.py) exhibit this behaviour and the RFC does not provide clear guidance.

I have not investigated how other implementations in other languages handle this, though. There do not appear to be any examples in the RFC that combine lists with length limitations.

@sigmavirus24
Copy link
Collaborator Author

sigmavirus24 commented Jun 24, 2017

So jtacoma/uritemplates behaves significantly differently:

package main

import (
	"fmt"
	"github.com/jtacoma/uritemplates"
)

func main() {
	uritemplateStr := "{term}"
	template, _ := uritemplates.Parse(uritemplateStr)
	values := make(map[string]interface{})
	values["term"] = [3]string{"foo", "bar", "bogus"}
	expanded, _ := template.Expand(values)
	fmt.Println(expanded)
}

When run produces:

%5Bfoo%20bar%20bogus%5D

Which un-encoded is

[foo bar bogus]

Which seems to be pretty egregiously wrong. (It produces the same output with {term*}.)

That said, if we modify this to use {term:1} we get only %5B as the output.

@sigmavirus24
Copy link
Collaborator Author

Ruby's Addressable has different behaviour:

puts Addressable::Template.new('{term:1}').expand({
  'term' => ['foo', 'bar', 'bogus'],
}).to_s

prints

f,b,b

I'm not sure I disagree with that either.

@sigmavirus24
Copy link
Collaborator Author

sigmavirus24 commented Jun 25, 2017

Meanwhile URIjs raises an error for this. That may be the most reasonable path forward.

var URITemplate = require('urijs/src/URITemplate');
console.log(URITemplate('{term:1}').expand({term: ['foo', 'bar', 'bogus']}))

@metatoaster
Copy link
Contributor

metatoaster commented Jul 15, 2019

Actually, this is addressed in the specification itself in 2.4.1:

Prefix modifiers are not applicable to variables that have composite values.

With "composite values" being defined in the subsequent section (2.4.2) to be "either a list of values or an associative array of (name, value) pairs".

Hence, the correct behavior would be to do what URIjs does.

Edit: of course, unless the confusion is specifically about what "not applicable" means, i.e. whether to ignore it (current behavior as implemented in this library) or simply be explicitly unsupported (like URIjs).

Reading some more, the normative section on expansion implementation hints (Appendix A), the prefix modifier is only applicable if the variable value is a string; in all the "else if" options, the prefix modifier is simply not mentioned (i.e. not applicable). This non-normative "suggestion" may mean that the current implementation is sufficient.

However, section 3 does not exclude the fact that what URIjs does is out of spec, depend on how that is read - fourth paragraph reads "such as an operator or value modifier that the template processor does not recognize or does not yet support" - given that there isn't an exhaustive definition for "error" defined, the template processor can just do what was described there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants