Matching file extensions

159 views
Skip to first unread message

Konstantin Haase

unread,
Mar 25, 2013, 1:41:48 PM3/25/13
to sina...@googlegroups.com
Quick survey,

1. How would you expect `get '/:id(.format)?'` to match "/foo.bar"? Valid responses: {id:'foo', format:'bar'} or {id:'foo.bar', fromat:nil}.
2. How would you expect `get '/:id.:format` to parse "/hello.world.html"?
2. How would you expect `get '/:id.:format` to parse "/download.tar.gz"?
3. How would you expect `get '/:id.:format` to parse "/a.brief.blog.post.html"?

Feel free to add justifications and comments.

Thank you for your time.

Konstantin

Jason Rogers

unread,
Mar 25, 2013, 2:00:52 PM3/25/13
to sina...@googlegroups.com
#1 I was going to say {id: 'foo', format: 'bar'}. However, after thinking about #'s 2-4 a bit more I think I would want to be able to expect {id: 'foo.bar', format: nil} unless I "somehow" registered 'bar' as a valid format.

#2 {id: 'hello.world', format: 'html'}

#3 {id: 'download', format: 'tar.gz'}

#4 {id: 'a.brief.blog.post', format: 'html'}

I'm a little unsure about what I would want on #3 -- I could also see it as {id: 'download.tar', format: 'gz'}. I think the one bit of information that could sway anyone of these responses is what the server is expected to do with the given information. For instance, with #3 is the server expected to generate a tarball and then gzip it before sending it on, or does the tarball alreday exist and it just needs to do the gzip'ed, or (in either case) is the gzip'ing expected to be done by the web server? If #3 were a POST instead of a GET, would that alter the expectation?

Having some way of flexibly registering allowable formats (for the app as a whole, or for each Sinatra subclass, or for each route) would help to alleviate the ambiguity (with some sensible defaults in place, of course -- eg. :json, :html, :js, :css).


--
Jason Rogers



Konstantin

--
You received this message because you are subscribed to the Google Groups "sinatrarb" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sinatrarb+...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.



Alper Akgün

unread,
Mar 25, 2013, 2:20:45 PM3/25/13
to sina...@googlegroups.com
1. {id: 'foo.bar', format: nil}, #setting "format" may break compatibility with lots of existing sinatra apps.
2. {id: 'hello.world', format: 'html'}   #last extension after dot, is enough to identify files on most OSes, and processing purposes.
3. {id: 'download.tar', format: 'gz'}   # its a gz to the outside world, a .gz processor knows about tar, if she needs.
4. {id: 'a.brief.blog.post', format: 'html'}  # ditto
4b. `get '/:id..:format` to parse "/a.brief.blog.post.html"?  # we may use 2 dots (..)  to give us    {id: 'a', format: 'brief.blog.post.html'}, it that's not a plain mistake

Iain Barnett

unread,
Mar 25, 2013, 2:21:45 PM3/25/13
to sina...@googlegroups.com

On 25 Mar 2013, at 17:41, Konstantin Haase wrote:

> Quick survey,
>
> 1. How would you expect `get '/:id(.format)?'` to match "/foo.bar"? Valid responses: {id:'foo', format:'bar'} or {id:'foo.bar', fromat:nil}.

{id: 'foo.bar', format: nil}

Never ever {id: 'foo', format: 'bar'}

> 2. How would you expect `get '/:id.:format` to parse "/hello.world.html"?

I'd expect it to follow regex rules, which takes the greediest possible match:

{id: "hello.world", format: "html"}

e.g

s =
r = /\/(?<id>.+)\.(?<format>.+)/
r.match s
# => #<MatchData "/hello.world.html" id:"hello.world" format:"html">

and

File.extname s
# => ".html"

File.basename s, File.extname(s)
# => "hello.world"


> 2. How would you expect `get '/:id.:format` to parse "/download.tar.gz"?

Um, 2? :P :)

Same again:

s = "/download.tar.gz"
r = /\/(?<id>.+)\.(?<format>.+)/
r.match s
# => #<MatchData "/download.tar.gz" id:"download.tar" format:"gz">

It's a gzipped tarball, so technically it's .gz. The tarball is the resource, not the contents of the tarball. `tar` recognises gzip compression as a convenience so you can *pass around the tarball*. That's how I'd think of it.

> 3. How would you expect `get '/:id.:format` to parse "/a.brief.blog.post.html"?

Without the regex, as I'm sounding like a computer now…

{ id: "a.brief.blog.post" format: "html" }

but that is how the regex would match it :)

Regards,
Iain


>
> Feel free to add justifications and comments.
>
> Thank you for your time.
>
> Konstantin
>

Konstantin Haase

unread,
Mar 25, 2013, 2:24:14 PM3/25/13
to sina...@googlegroups.com
Iain,

In that case, what's the advantage of using the pattern vs. using a regexp?

How would I get an optional extension? Parse it after the fact?

Konstantin

Konstantin Haase

unread,
Mar 25, 2013, 2:24:58 PM3/25/13
to sina...@googlegroups.com
The two dot syntax is a bit strange at first look. I was thinking maybe a config option?

Konstantin

Konstantin Haase

unread,
Mar 25, 2013, 2:29:10 PM3/25/13
to sina...@googlegroups.com
So Sinatra should assume . + named capture is a file extension? Or only if the capture is named format?

Konstantin

Konstantin Haase

unread,
Mar 25, 2013, 2:30:25 PM3/25/13
to sina...@googlegroups.com
Same to you as to Jason: Will that only affect captures named format?

What about '/:id.:frmt'? What about '/:name.:tld'? What about '/:year.:month.:day'?

Konstantin

On Mar 25, 2013, at 6:52 PM, Patricio Mac Adden <patricio...@gmail.com> wrote:

Konstantin, I'll respond in between lines:


El lunes, 25 de marzo de 2013 14:41:48 UTC-3, Konstantin Haase escribió:
Quick survey,

1. How would you expect `get '/:id(.format)?'` to match "/foo.bar"? Valid responses: {id:'foo', format:'bar'} or {id:'foo.bar', fromat:nil}.

{id:'foo', format:'bar'}
 
2. How would you expect `get '/:id.:format` to parse "/hello.world.html"?

{ id: 'hello.world', format: 'html' }
 
2. How would you expect `get '/:id.:format` to parse "/download.tar.gz"?

{id: 'download', format: 'tar.gz'}
 
3. How would you expect `get '/:id.:format` to parse "/a.brief.blog.post.html"?

{id: 'a.brief.blog.post', format: 'html'}
 
As you can see, the format parameter does not follow any pattern, so maybe we could add a "format whitelist" (.html, .tar.gz, etc) for matching them before the rest of the parameters. What do you think?


Feel free to add justifications and comments.

Thank you for your time.

Konstantin
 

Konstantin Haase

unread,
Mar 25, 2013, 2:32:13 PM3/25/13
to sina...@googlegroups.com
Interesting. So '/:host.:tld' when parsing 'www.google.com' would parse 'www' as host?

Konstantin

On Mar 25, 2013, at 6:51 PM, Daniel Huckstep <darkh...@darkhelmetlive.com> wrote:

My thought is that the first dot separates the :id from :format, so everything after the first dot is the extension.

{ id: 'foo', format: 'bar' }
{ id: 'hello', format: 'world.html' }
{ id: 'download', format: 'tar.gz' }
{ id: 'a', format: 'brief.blog.post.html' }

- Daniel

Alper Akgün

unread,
Mar 25, 2013, 2:39:06 PM3/25/13
to sina...@googlegroups.com
two dot is indeed strange; just a reminder for recursive asterisk used in some commands as  "./**/*"
my basic idea was to create a (b) option for 2 types of format extension parsing; i dont believe file sytems and uris and regexes have a coherent way they agreed upon, how you could do that..
finally, a global config option, would end up being confusing across projects.. 

we still need a better idea...


Patricio Mac Adden

unread,
Mar 25, 2013, 2:40:43 PM3/25/13
to sina...@googlegroups.com
Yes, you are right… but, if we only capture the format as the "last word after the last dot", then formats like 'tar.gz' are not well captured. Maybe, if a whitelist format is not found, we can fallback to "last word after the last dot".

Iain Barnett

unread,
Mar 25, 2013, 2:53:37 PM3/25/13
to sina...@googlegroups.com
On 25 Mar 2013, at 18:24, Konstantin Haase wrote:

> Iain,
>
> In that case, what's the advantage of using the pattern vs. using a regexp?
>
> How would I get an optional extension? Parse it after the fact?
>
> Konstantin

I use patterns for simple things because they're clearer, it's a very nice syntax. If I need something more precise or it's more complex, like the optional extension for something complicated) I'd use regex. I think the overall logic for my response is "principle of least surprise" in that (I feel) my answers reflect either the regex or the File class parsing, so pattern should follow that too.

Regards,
Iain

Jason Rogers

unread,
Mar 25, 2013, 3:25:38 PM3/25/13
to sina...@googlegroups.com
I was only thinking of :format in this case. But, I concede that it could be problematic to special-case :format, and it could conflict with the principal of least surprise.


--
Jason Rogers

Jason Rogers

unread,
Mar 25, 2013, 3:26:08 PM3/25/13
to sina...@googlegroups.com
Yup. I amend my former responses to agree with Iain here.


--
Jason Rogers

Magnus Holm

unread,
Mar 25, 2013, 4:45:20 PM3/25/13
to sina...@googlegroups.com

On Monday, March 25, 2013 6:41:48 PM UTC+1, Konstantin Haase wrote:
Quick survey,

1. How would you expect `get '/:id(.format)?'` to match "/foo.bar"? Valid responses: {id:'foo', format:'bar'} or {id:'foo.bar', fromat:nil}.

{id:'foo',format:'bar'}
 
2. How would you expect `get '/:id.:format` to parse "/hello.world.html"?

{id:'hello.world',format:'html'}
 
2. How would you expect `get '/:id.:format` to parse "/download.tar.gz"?
 
{id:'download.tar',format:'gz'}
 
3. How would you expect `get '/:id.:format` to parse "/a.brief.blog.post.html"?
 
{id:'a.brief.blog.post',format:'html'} 


Feel free to add justifications and comments.

:foobar is just a shortcut for regexp ([^\/]+). (:foobar)? is a shortcut for ([^\/]+)?

I would also assume there's a way to put restrictions on :format, so by e.g. setting :format => %w[html json tar.gz] it would compile it to the regexp (html|json|tar\.gz).

Sinatra could also ship with a default :format-setting.

Jon

unread,
Mar 25, 2013, 5:38:07 PM3/25/13
to sina...@googlegroups.com
{id:'foo', format:'bar'}
{id:'hello.world', format:'html'}

{id:'download.tar', format:'gz'}
{id:'a.brief.blog.post', format:'html'}

Is `:format` usable in conditions like

get '/:id.:format', :format => /jpe?g|gif|png/

and the `set(:format) { |value| ... }` variant?

Iain Barnett

unread,
Mar 26, 2013, 4:19:52 AM3/26/13
to sina...@googlegroups.com
Konstantin,

Thinking about this a bit, what I'd most prefer is that the internals to the route matching were opened up, and then special words could be added via a module/gem/plugin. Then if you want .format to match a format in a particular way, you have that choice and it's clearly marked somewhere (the requires / the configure block / the registrations etc).

I'd prefer that to baking in new stuff, but that's just a suggestion. There will obviously be plus and minus points to everything.

Regards,
Iain




On 25 Mar 2013, at 18:24, Konstantin Haase wrote:

Konstantin Haase

unread,
Mar 26, 2013, 1:15:26 PM3/26/13
to sina...@googlegroups.com
Yes, I'm working on that. I was more wondering about the default behaviour. I do not want to ship some special logic for captures called format by default, but I think :foo(.:bar)? should match the part after the last dot as bar. At least that's what I'd expect.

Konstantin

Nicolás Sanguinetti

unread,
Mar 26, 2013, 1:36:03 PM3/26/13
to sina...@googlegroups.com
:+1: 

Always be greedy :P

Iain Barnett

unread,
Mar 27, 2013, 5:50:07 AM3/27/13
to sina...@googlegroups.com

On 26 Mar 2013, at 17:15, Konstantin Haase wrote:

> Yes, I'm working on that. I was more wondering about the default behaviour. I do not want to ship some special logic for captures called format by default, but I think :foo(.:bar)? should match the part after the last dot as bar. At least that's what I'd expect.
>
> Konstantin

I think you've found a philosophical line around which a holy war can begin, commensurate with the "Rails commits the binstubs" scandal. It may even make the front page of Hacker News :)

As long as it's documented clearly one way or the other then I won't be the one to post it to Hacker News.

Regards,
Iain

Konstantin Haase

unread,
Mar 27, 2013, 6:06:01 AM3/27/13
to sina...@googlegroups.com
Note that right now Sinatra parses the pattern '/:foo.?:bar' so that :bar matches the last part after a dot. Sinatra 1.3 didn't.

Konstantin
Reply all
Reply to author
Forward
0 new messages