sinatra 1.4.1 → 1.4.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of sinatra might be problematic. Click here for more details.

data/CHANGES CHANGED
@@ -1,3 +1,12 @@
1
+ = 1.4.2 / 2013-03-21
2
+
3
+ * Fix parsing error for case where both the pattern and the captured part
4
+ contain a dot. (Florian Hanke, Konstantin Haase)
5
+
6
+ * Missing Accept header is treated like */*. (Greg Denton)
7
+
8
+ * Improve documentation. (Patricio Mac Adden, Joe Bottigliero)
9
+
1
10
  = 1.4.1 / 2013-03-15
2
11
 
3
12
  * Make delegated methods available in config.ru (Konstantin Haase)
@@ -15,7 +15,7 @@ get '/' do
15
15
  end
16
16
  ```
17
17
 
18
- Instalá la gem y ejecutá la aplicación con:
18
+ Instalá el gem y corré la aplicación con:
19
19
 
20
20
  ``` shell
21
21
  gem install sinatra
@@ -58,11 +58,11 @@ options '/' do
58
58
  end
59
59
  ```
60
60
 
61
- Las rutas son comparadas en el orden en el que son definidas. La primer ruta
61
+ Las rutas son comparadas en el orden en el que son definidas. La primera ruta
62
62
  que coincide con la petición es invocada.
63
63
 
64
64
  Los patrones de las rutas pueden incluir parámetros nombrados, accesibles a
65
- través de el hash `params`:
65
+ través del hash `params`:
66
66
 
67
67
  ``` ruby
68
68
  get '/hola/:nombre' do
@@ -76,6 +76,9 @@ También podés acceder a los parámetros nombrados usando parámetros de bloque
76
76
 
77
77
  ``` ruby
78
78
  get '/hola/:nombre' do |n|
79
+ # coincide con "GET /hola/foo" y "GET /hola/bar"
80
+ # params[:nombre] es 'foo' o 'bar'
81
+ # n almacena params[:nombre]
79
82
  "Hola #{n}!"
80
83
  end
81
84
  ```
@@ -128,7 +131,7 @@ get '/posts.?:formato?' do
128
131
  end
129
132
  ```
130
133
 
131
- A propósito, a menos que desactivés la protección para el ataque *path
134
+ A propósito, a menos que desactives la protección para el ataque *path
132
135
  traversal* (ver más abajo), el path de la petición puede ser modificado
133
136
  antes de que se compare con los de tus rutas.
134
137
 
@@ -201,10 +204,10 @@ end
201
204
 
202
205
  ### Valores de Retorno
203
206
 
204
- El valor de retorno de un bloque de ruta determina al menos el cuerpo de la
207
+ El valor de retorno de un bloque de ruta que determina al menos el cuerpo de la
205
208
  respuesta que se le pasa al cliente HTTP o al siguiente middleware en la pila
206
209
  de Rack. Lo más común es que sea un string, como en los ejemplos anteriores.
207
- Sin embargo, otros valor también son aceptados.
210
+ Sin embargo, otros valores también son aceptados.
208
211
 
209
212
  Podés devolver cualquier objeto que sea una respuesta Rack válida, un objeto
210
213
  que represente el cuerpo de una respuesta Rack o un código de estado HTTP:
@@ -377,7 +380,7 @@ Opciones disponibles:
377
380
 
378
381
  <dt>layout</dt>
379
382
  <dd>
380
- Si es <tt>true</tt> o <tt>false</tt> indica que se debe usar, o nó, un layout,
383
+ Si es <tt>true</tt> o <tt>false</tt> indica que se debe usar, o no, un layout,
381
384
  respectivamente. También puede ser un símbolo que especifique qué plantilla
382
385
  usar. Ejemplo: <tt>erb :index, :layout => !request.xhr?</tt>
383
386
  </dd>
@@ -412,9 +415,9 @@ Opciones disponibles:
412
415
  <dd>
413
416
  Es importante acordarse que siempre tenés que referenciar a las plantillas con
414
417
  símbolos, incluso cuando se encuentran en un subdirectorio (en este caso
415
- tenés que usar: <tt>'subdir/plantilla'</tt>). Tenés que usar un símbolo porque los
416
- métodos de renderización van a renderizar directamente cualquier string que se
417
- les pase como argumento.
418
+ tenés que usar: `:'subdir/plantilla'` o `'subdir/plantilla'.to_sym`). Tenés que
419
+ usar un símbolo porque los métodos de renderización van a renderizar
420
+ directamente cualquier string que se les pase como argumento.
418
421
  </dd>
419
422
  </dl>
420
423
 
@@ -872,7 +875,6 @@ distinto al de la plantilla pasando la opción `:layout_engine`.
872
875
  </tr>
873
876
  </table>
874
877
 
875
-
876
878
  El contenido de La plantilla se evalúa como código Ruby, y la variable `json` es convertida a JSON mediante `#to_json`.
877
879
 
878
880
  ``` ruby
@@ -1057,7 +1059,7 @@ after do
1057
1059
  end
1058
1060
  ```
1059
1061
 
1060
- Nota: A menos que usés el método `body` en lugar de simplemente devolver un
1062
+ Nota: A menos que uses el método `body` en lugar de simplemente devolver un
1061
1063
  string desde una ruta, el cuerpo de la respuesta no va a estar disponible en
1062
1064
  un filtro after, debido a que todavía no se ha generado.
1063
1065
 
@@ -1125,7 +1127,7 @@ incluir los módulos en la clase de la aplicación.
1125
1127
  ### Usando Sesiones
1126
1128
 
1127
1129
  Una sesión es usada para mantener el estado a través de distintas peticiones.
1128
- Cuando están activadas, tenés un hash de sesión para cada sesión de usuario:
1130
+ Cuando están activadas, proporciona un hash de sesión para cada sesión de usuario:
1129
1131
 
1130
1132
  ``` ruby
1131
1133
  enable :sessions
@@ -1140,8 +1142,8 @@ end
1140
1142
  ```
1141
1143
 
1142
1144
  Tené en cuenta que `enable :sessions` guarda todos los datos en una
1143
- cookie, lo que no es siempre deseable (guardar muchos datos va a incrementar
1144
- tu tráfico, por citar un ejemplo). Podés usar cualquier middleware Rack para
1145
+ cookie, lo cual no es siempre deseable (guardar muchos datos va a incrementar
1146
+ el tráfico, por citar un ejemplo). Podés usar cualquier middleware Rack para
1145
1147
  manejar sesiones, de la misma manera que usarías cualquier otro middleware,
1146
1148
  pero con la salvedad de que *no* tenés que llamar a `enable :sessions`:
1147
1149
 
@@ -1230,7 +1232,7 @@ end
1230
1232
  ```
1231
1233
 
1232
1234
  Se sale inmediatamente del bloque de la ruta y se le pasa el control a la
1233
- siguiente ruta que coincida. Si no coincide ninguna ruta, se devuelve un 404.
1235
+ siguiente ruta que coincida. Si no coincide ninguna ruta, se devuelve 404.
1234
1236
 
1235
1237
  ### Ejecutando Otra Ruta
1236
1238
 
@@ -1413,7 +1415,7 @@ Para generar URLs deberías usar el método `url`. Por ejemplo, en Haml:
1413
1415
 
1414
1416
  Tiene en cuenta proxies inversos y encaminadores de Rack, si están presentes.
1415
1417
 
1416
- Este método también puede invocarse mediante su alias `to` (mirá un ejemplo
1418
+ Este método también puede invocarse mediante su alias `to` (mirá un ejemplo
1417
1419
  a continuación).
1418
1420
 
1419
1421
  ### Redirección del Navegador
@@ -1524,7 +1526,7 @@ etag @articulo.sha1, :weak
1524
1526
 
1525
1527
  Estos helpers no van a cachear nada por vos, sino que van a facilitar la
1526
1528
  información necesaria para poder hacerlo. Si estás buscando soluciones rápidas
1527
- de cacheo con proxys inversos, mirá
1529
+ de cacheo con proxys reversos, mirá
1528
1530
  [rack-cache](https://github.com/rtomayko/rack-cache):
1529
1531
 
1530
1532
  ``` ruby
@@ -1548,7 +1550,7 @@ De acuerdo con la RFC 2616 tu aplicación debería comportarse diferente si a la
1548
1550
  cabeceras If-Match o If-None-Match se le asigna el valor `*` cuando el
1549
1551
  recurso solicitado ya existe. Sinatra asume para peticiones seguras (como get)
1550
1552
  e idempotentes (como put) que el recurso existe, mientras que para el resto
1551
- (como post), que no. Podes cambiar este comportamiento con la opción
1553
+ (como post) asume que no. Podes cambiar este comportamiento con la opción
1552
1554
  `:new_resource`:
1553
1555
 
1554
1556
  ``` ruby
@@ -1643,7 +1645,7 @@ get '/foo' do
1643
1645
  request.path # "/ejemplo/foo"
1644
1646
  request.ip # dirección IP del cliente
1645
1647
  request.secure? # false (sería true sobre ssl)
1646
- request.forwarded? # true (si se está corriendo atrás de un proxy inverso)
1648
+ request.forwarded? # true (si se está corriendo atrás de un proxy reverso)
1647
1649
  requuest.env # hash de entorno directamente entregado por Rack
1648
1650
  end
1649
1651
  ```
@@ -1766,7 +1768,7 @@ helpers do
1766
1768
  end
1767
1769
  ```
1768
1770
 
1769
- ¡Es muy fácil convertir estos ejemplos en una extensión y compartirla!.
1771
+ ¡Es muy fácil convertir estos ejemplos en una extensión y compartirla!
1770
1772
 
1771
1773
  Notá que `find_template` no verifica si un archivo existe realmente, sino
1772
1774
  que llama al bloque que recibe para cada path posible. Esto no representa un
@@ -1864,7 +1866,7 @@ set :protection, :except => [:path_traversal, :session_hijacking]
1864
1866
  1.1), que solamente permite redirecciones absolutas.
1865
1867
 
1866
1868
  Activalo si tu apliación está corriendo atrás de un proxy
1867
- inverso que no se ha configurado adecuadamente. Notá que
1869
+ reverso que no se ha configurado adecuadamente. Notá que
1868
1870
  el helper <tt>url</tt> va a seguir produciendo URLs absolutas, a
1869
1871
  menos que le pasés <tt>false</tt> como segundo parámetro.
1870
1872
 
@@ -1996,7 +1998,7 @@ set :protection, :except => [:path_traversal, :session_hijacking]
1996
1998
  <dt>run</dt>
1997
1999
  <dd>
1998
2000
  Cuando está habilitada, Sinatra se va a encargar de
1999
- iniciar el servidor web, no la habilités cuando estés
2001
+ iniciar el servidor web, no la habilites cuando estés
2000
2002
  usando rackup o algún otro medio.
2001
2003
  </dd>
2002
2004
 
@@ -2033,7 +2035,7 @@ set :protection, :except => [:path_traversal, :session_hijacking]
2033
2035
  Define si Sinatra debe encargarse de servir archivos
2034
2036
  estáticos.
2035
2037
 
2036
- Deshabilitala cuando usés un servidor capaz de
2038
+ Deshabilitala cuando uses un servidor capaz de
2037
2039
  hacerlo por sí solo, porque mejorará el
2038
2040
  rendimiento. Se encuentra habilitada por
2039
2041
  defecto en el estilo clásico y desactivado en el
@@ -2156,7 +2158,7 @@ cuando se ejecuta dentro del entorno de desarrollo "development".
2156
2158
 
2157
2159
  Sinatra corre sobre Rack[http://rack.rubyforge.org/], una interfaz minimalista
2158
2160
  que es un estándar para frameworks webs escritos en Ruby. Una de las
2159
- capacidades más interesantes de Rack para los desarrolladores de aplicaciones
2161
+ características más interesantes de Rack para los desarrolladores de aplicaciones
2160
2162
  es el soporte de "middleware" -- componentes que se ubican entre el servidor y
2161
2163
  tu aplicación, supervisando y/o manipulando la petición/respuesta HTTP para
2162
2164
  proporcionar varios tipos de funcionalidades comunes.
@@ -2176,9 +2178,9 @@ get '/hola' do
2176
2178
  end
2177
2179
  ```
2178
2180
 
2179
- Las semánticas de `use` son idénticas a las definidas para el DSL
2181
+ La semántica de `use` es idéntica a la definida para el DSL
2180
2182
  Rack::Builder[http://rack.rubyforge.org/doc/classes/Rack/Builder.html] (más
2181
- frecuentemente usado desde archivos rackup). Por ejemplo, el método `use`
2183
+ frecuentemente usado en archivos rackup). Por ejemplo, el método `use`
2182
2184
  acepta argumentos múltiples/variables así como bloques:
2183
2185
 
2184
2186
  ``` ruby
@@ -2237,7 +2239,7 @@ end
2237
2239
 
2238
2240
  Definir tu aplicación en el top-level funciona bien para micro-aplicaciones
2239
2241
  pero trae inconvenientes considerables a la hora de construir componentes
2240
- reutilizables como Rack middleware, Rails metal, simple librerías con un
2242
+ reutilizables como Rack middleware, Rails metal, librerías simples con un
2241
2243
  componente de servidor, o incluso extensiones de Sinatra. El DSL de top-level
2242
2244
  asume una configuración apropiada para micro-aplicaciones (por ejemplo, un
2243
2245
  único archivo de aplicación, los directorios `./public` y
@@ -2574,7 +2576,7 @@ Tenés la ligadura al ámbito de delegación dentro de:
2574
2576
  * La ligadura del top-level, si hiciste `require "sinatra"`
2575
2577
  * Un objeto extendido con el mixin `Sinatra::Delegator`
2576
2578
 
2577
- Pegale una mirada al código: acá está el
2579
+ Hechale un vistazo al código: acá está el
2578
2580
  [Sinatra::Delegator mixin](https://github.com/sinatra/sinatra/blob/ca06364/lib/sinatra/base.rb#L1609-1633)
2579
2581
  que [extiende el objeto main](https://github.com/sinatra/sinatra/blob/ca06364/lib/sinatra/main.rb#L28-30).
2580
2582
 
@@ -2605,7 +2607,7 @@ Las siguientes versiones de Ruby son soportadas oficialmente:
2605
2607
  <dt>Ruby 1.8.7</dt>
2606
2608
  <dd>
2607
2609
  1.8.7 es soportado completamente. Sin embargo, si no hay nada que te lo
2608
- prohíba, te recomendamos que usés 1.9.2 o cambies a JRuby o Rubinius. No se
2610
+ prohiba, te recomendamos que uses 1.9.2 o cambies a JRuby o Rubinius. No se
2609
2611
  dejará de dar soporte a 1.8.7 hasta Sinatra 2.0 y Ruby 2.0, aunque si se
2610
2612
  libera la versión 1.8.8 de Ruby las cosas podrían llegar a cambiar. Sin
2611
2613
  embargo, que eso ocurra es muy poco probable, e incluso el caso de que lo
@@ -2617,7 +2619,7 @@ Las siguientes versiones de Ruby son soportadas oficialmente:
2617
2619
 
2618
2620
  <dt>Ruby 1.9.2</dt>
2619
2621
  <dd>
2620
- 1.9.2 es soportado y recomendado. No usés 1.9.2p0, porque se producen fallos
2622
+ 1.9.2 es soportado y recomendado. No uses 1.9.2p0, porque se producen fallos
2621
2623
  de segmentación cuando se ejecuta Sinatra. El soporte se mantendrá al menos
2622
2624
  hasta que se libere la versión 1.9.4/2.0 de Ruby. El soporte para la última
2623
2625
  versión de la serie 1.9 se mantendrá mientras lo haga el core team de Ruby.
@@ -2655,16 +2657,16 @@ oficialmente. De cualquier manera, pueden ejecutar Sinatra:
2655
2657
  * Versiones anteriores de JRuby y Rubinius
2656
2658
  * Ruby Enterprise Edition
2657
2659
  * MacRuby, Maglev e IronRuby
2658
- * Ruby 1.9.0 y 1.9.1 (pero no te recomendamos que los usés)
2660
+ * Ruby 1.9.0 y 1.9.1 (pero no te recomendamos que los uses)
2659
2661
 
2660
2662
  No estar soportada oficialmente, significa que si las cosas solamente se rompen
2661
2663
  ahí y no en una plataforma soportada, asumimos que no es nuestro problema sino
2662
2664
  el suyo.
2663
2665
 
2664
2666
  Nuestro servidor CI también se ejecuta sobre ruby-head (que será la próxima
2665
- versión 2.0.0) y la rama 1.9.4. Como están en movimiento constante, no podemos
2667
+ versión 2.1.0) y la rama 1.9.4. Como están en movimiento constante, no podemos
2666
2668
  garantizar nada. De todas formas, podés contar con que tanto 1.9.4-p0 como
2667
- 2.0.0-p0 sea soportadas.
2669
+ 2.1.0-p0 sea soportadas.
2668
2670
 
2669
2671
  Sinatra debería funcionar en cualquier sistema operativo soportado por la
2670
2672
  implementación de Ruby elegida.
@@ -2677,7 +2679,7 @@ BlueRuby o cualquier versión de Ruby anterior a 1.8.7.
2677
2679
  Si querés usar el código de Sinatra más reciente, sentite libre de ejecutar
2678
2680
  tu aplicación sobre la rama master, en general es bastante estable.
2679
2681
 
2680
- También liberamos prereleases de vez en cuando, así, podés hacer
2682
+ También liberamos prereleases de vez en cuando, así, podés hacer:
2681
2683
 
2682
2684
  ``` shell
2683
2685
  gem install sinatra --pre
data/README.md CHANGED
@@ -12,10 +12,15 @@ get '/' do
12
12
  end
13
13
  ```
14
14
 
15
- Install the gem and run with:
15
+ Install the gem:
16
16
 
17
17
  ``` shell
18
18
  gem install sinatra
19
+ ```
20
+
21
+ And run with:
22
+
23
+ ``` shell
19
24
  ruby myapp.rb
20
25
  ```
21
26
 
@@ -166,6 +171,9 @@ You can also access named parameters via block parameters:
166
171
 
167
172
  ``` ruby
168
173
  get '/hello/:name' do |n|
174
+ # matches "GET /hello/foo" and "GET /hello/bar"
175
+ # params[:name] is 'foo' or 'bar'
176
+ # n stores params[:name]
169
177
  "Hello #{n}!"
170
178
  end
171
179
  ```
@@ -488,12 +496,13 @@ Available Options:
488
496
 
489
497
  Templates are assumed to be located directly under the `./views` directory. To
490
498
  use a different views directory:
491
- <tt>set :views, settings.root + '/templates'</tt>
499
+ `set :views, settings.root + '/templates'`
492
500
 
493
501
  One important thing to remember is that you always have to reference templates
494
502
  with symbols, even if they're in a subdirectory (in this case, use:
495
- <tt>'subdir/template'</tt>). You must use a symbol because otherwise rendering
496
- methods will render any strings passed to them directly.
503
+ `:'subdir/template'` or `'subdir/template'.to_sym`). You must use a symbol
504
+ because otherwise rendering methods will render any strings passed to them
505
+ directly.
497
506
 
498
507
  ### Literal Templates
499
508
 
@@ -723,7 +732,6 @@ template than for the layout by passing the `:layout_engine` option.
723
732
  </tr>
724
733
  </table>
725
734
 
726
-
727
735
  It is not possible to call methods from textile, nor to pass locals to it. You
728
736
  therefore will usually use it in combination with another rendering engine:
729
737
 
@@ -1033,7 +1041,7 @@ other templates.
1033
1041
  ### Templates with `yield` and nested layouts
1034
1042
 
1035
1043
  A layout is usually just a template that calls `yield`.
1036
- Such a template can by used either through the `:template` option as
1044
+ Such a template can be used either through the `:template` option as
1037
1045
  described above, or it can be rendered with a block as follows:
1038
1046
 
1039
1047
  ``` ruby
@@ -1993,7 +2001,7 @@ set :protection, :session => true
1993
2001
  properly. Note that the <tt>url</tt> helper will still produce absolute URLs, unless you
1994
2002
  pass in <tt>false</tt> as the second parameter.
1995
2003
  </dd>
1996
- <dd>Disabled per default.</dd>
2004
+ <dd>Disabled by default.</dd>
1997
2005
 
1998
2006
  <dt>add_charsets</dt>
1999
2007
  <dd>
@@ -2009,7 +2017,7 @@ set :protection, :session => true
2009
2017
  </dd>
2010
2018
 
2011
2019
  <dt>bind</dt>
2012
- <dd>IP address to bind to (default: <tt>0.0.0.0</tt>). Only used for built-in server.</dd>
2020
+ <dd>IP address to bind to (default: <tt>0.0.0.0</tt> <em>or</em> <tt>localhost</tt> if your `environment` is set to development.). Only used for built-in server.</dd>
2013
2021
 
2014
2022
  <dt>default_encoding</dt>
2015
2023
  <dd>encoding to assume if unknown (defaults to <tt>"utf-8"</tt>).</dd>
@@ -2730,14 +2738,14 @@ The following Ruby versions are officially supported:
2730
2738
  <dt>Rubinius</dt>
2731
2739
  <dd>
2732
2740
  Rubinius is officially supported (Rubinius >= 2.x). It is recommendended to
2733
- `gem install puma`.
2741
+ <tt>gem install puma</tt>.
2734
2742
  </dd>
2735
2743
 
2736
2744
  <dt>JRuby</dt>
2737
2745
  <dd>
2738
2746
  The latest stable release of JRuby is officially supported. It is not
2739
2747
  recommended to use C extensions with JRuby. It is recommended to
2740
- `gem install trinidad`.
2748
+ <tt>gem install trinidad</tt>.
2741
2749
  </dd>
2742
2750
  </dl>
2743
2751
 
@@ -2828,6 +2836,7 @@ To update the Sinatra sources in the future:
2828
2836
  cd myapp/sinatra
2829
2837
  git pull
2830
2838
  ```
2839
+
2831
2840
  ### Install Globally
2832
2841
 
2833
2842
  You can build the gem on your own:
@@ -28,9 +28,11 @@ module Sinatra
28
28
  end
29
29
 
30
30
  def preferred_type(*types)
31
- return accept.first if types.empty?
31
+ accepts = accept # just evaluate once
32
+ return accepts.first if types.empty?
32
33
  types.flatten!
33
- accept.detect do |pattern|
34
+ return types.first if accepts.empty?
35
+ accepts.detect do |pattern|
34
36
  type = types.detect { |t| File.fnmatch(pattern, t) }
35
37
  return type if type
36
38
  end
@@ -1414,34 +1416,66 @@ module Sinatra
1414
1416
  end
1415
1417
 
1416
1418
  def compile(path)
1417
- keys = []
1418
1419
  if path.respond_to? :to_str
1419
- ignore = ""
1420
- pattern = path.to_str.gsub(/[^\?\%\\\/\:\*\w]/) do |c|
1421
- ignore << escaped(c).join if c.match(/[\.@]/)
1422
- patt = encoded(c)
1423
- patt.gsub(/%[\da-fA-F]{2}/) do |match|
1424
- match.split(//).map {|char| char =~ /[A-Z]/ ? "[#{char}#{char.tr('A-Z', 'a-z')}]" : char}.join
1420
+ keys = []
1421
+
1422
+ # We append a / at the end if there was one.
1423
+ # Reason: Splitting does not split off an empty
1424
+ # string at the end if the split separator
1425
+ # is at the end.
1426
+ #
1427
+ postfix = '/' if path =~ /\/\z/
1428
+
1429
+ # Split the path into pieces in between forward slashes.
1430
+ #
1431
+ segments = path.split('/').map! do |segment|
1432
+ ignore = []
1433
+
1434
+ # Special character handling.
1435
+ #
1436
+ pattern = segment.to_str.gsub(/[^\?\%\\\/\:\*\w]/) do |c|
1437
+ ignore << escaped(c).join if c.match(/[\.@]/)
1438
+ patt = encoded(c)
1439
+ patt.gsub(/%[\da-fA-F]{2}/) do |match|
1440
+ match.split(//).map {|char| char =~ /[A-Z]/ ? "[#{char}#{char.tr('A-Z', 'a-z')}]" : char}.join
1441
+ end
1442
+ end
1443
+
1444
+ ignore = ignore.uniq.join
1445
+
1446
+ # Key handling.
1447
+ #
1448
+ pattern.gsub(/((:\w+)|\*)/) do |match|
1449
+ if match == "*"
1450
+ keys << 'splat'
1451
+ "(.*?)"
1452
+ else
1453
+ keys << $2[1..-1]
1454
+ ignore_pattern = safe_ignore(ignore)
1455
+
1456
+ ignore_pattern
1457
+ end
1425
1458
  end
1426
1459
  end
1427
- pattern.gsub!(/((:\w+)|\*)/) do |match|
1428
- if match == "*"
1429
- keys << 'splat'
1430
- "(.*?)"
1460
+
1461
+ # Special case handling.
1462
+ #
1463
+ if segment = segments.pop
1464
+ if segment.match(/\[\^\\\./)
1465
+ parts = segment.rpartition(/\[\^\\\./)
1466
+ parts[1] = '[^'
1467
+ segments << parts.join
1431
1468
  else
1432
- keys << $2[1..-1]
1433
- ignore_pattern = safe_ignore(ignore)
1434
-
1435
- ignore_pattern
1469
+ segments << segment
1436
1470
  end
1437
1471
  end
1438
- [/\A#{pattern}\z/, keys]
1472
+ [/\A#{segments.join('/')}#{postfix}\z/, keys]
1439
1473
  elsif path.respond_to?(:keys) && path.respond_to?(:match)
1440
1474
  [path, path.keys]
1441
1475
  elsif path.respond_to?(:names) && path.respond_to?(:match)
1442
1476
  [path, path.names]
1443
1477
  elsif path.respond_to? :match
1444
- [path, keys]
1478
+ [path, []]
1445
1479
  else
1446
1480
  raise TypeError, path
1447
1481
  end
@@ -1,3 +1,3 @@
1
1
  module Sinatra
2
- VERSION = '1.4.1'
2
+ VERSION = '1.4.2'
3
3
  end
@@ -6,14 +6,14 @@ class CompileTest < Test::Unit::TestCase
6
6
  def self.converts pattern, expected_regexp
7
7
  it "generates #{expected_regexp.source} from #{pattern}" do
8
8
  compiled, _ = compiled pattern
9
- assert_equal expected_regexp, compiled
9
+ assert_equal expected_regexp, compiled, "Pattern #{pattern} is not compiled into #{expected_regexp.source}. Was #{compiled.source}."
10
10
  end
11
11
  end
12
12
  def self.parses pattern, example, expected_params
13
13
  it "parses #{example} with #{pattern} into params #{expected_params}" do
14
14
  compiled, keys = compiled pattern
15
15
  match = compiled.match(example)
16
- fail %Q{"#{example}" does not parse on pattern "#{pattern}".} unless match
16
+ fail %Q{"#{example}" does not parse on pattern "#{pattern}" (compiled pattern is #{compiled.source}).} unless match
17
17
 
18
18
  # Aggregate e.g. multiple splat values into one array.
19
19
  #
@@ -27,7 +27,7 @@ class CompileTest < Test::Unit::TestCase
27
27
  hash
28
28
  end
29
29
 
30
- assert_equal(expected_params, params)
30
+ assert_equal expected_params, params, "Pattern #{pattern} does not match path #{example}."
31
31
  end
32
32
  end
33
33
  def self.fails pattern, example
@@ -45,10 +45,10 @@ class CompileTest < Test::Unit::TestCase
45
45
 
46
46
  converts "/", %r{\A/\z}
47
47
  parses "/", "/", {}
48
-
48
+
49
49
  converts "/foo", %r{\A/foo\z}
50
50
  parses "/foo", "/foo", {}
51
-
51
+
52
52
  converts "/:foo", %r{\A/([^/?#]+)\z}
53
53
  parses "/:foo", "/foo", "foo" => "foo"
54
54
  parses "/:foo", "/foo.bar", "foo" => "foo.bar"
@@ -58,97 +58,126 @@ class CompileTest < Test::Unit::TestCase
58
58
  fails "/:foo", "/foo/bar"
59
59
  fails "/:foo", "/"
60
60
  fails "/:foo", "/foo/"
61
-
61
+
62
62
  converts "/föö", %r{\A/f%[Cc]3%[Bb]6%[Cc]3%[Bb]6\z}
63
63
  parses "/föö", "/f%C3%B6%C3%B6", {}
64
-
64
+
65
65
  converts "/:foo/:bar", %r{\A/([^/?#]+)/([^/?#]+)\z}
66
66
  parses "/:foo/:bar", "/foo/bar", "foo" => "foo", "bar" => "bar"
67
-
67
+
68
68
  converts "/hello/:person", %r{\A/hello/([^/?#]+)\z}
69
69
  parses "/hello/:person", "/hello/Frank", "person" => "Frank"
70
-
70
+
71
71
  converts "/?:foo?/?:bar?", %r{\A/?([^/?#]+)?/?([^/?#]+)?\z}
72
72
  parses "/?:foo?/?:bar?", "/hello/world", "foo" => "hello", "bar" => "world"
73
73
  parses "/?:foo?/?:bar?", "/hello", "foo" => "hello", "bar" => nil
74
74
  parses "/?:foo?/?:bar?", "/", "foo" => nil, "bar" => nil
75
75
  parses "/?:foo?/?:bar?", "", "foo" => nil, "bar" => nil
76
-
76
+
77
77
  converts "/*", %r{\A/(.*?)\z}
78
78
  parses "/*", "/", "splat" => ""
79
79
  parses "/*", "/foo", "splat" => "foo"
80
80
  parses "/*", "/foo/bar", "splat" => "foo/bar"
81
-
81
+
82
82
  converts "/:foo/*", %r{\A/([^/?#]+)/(.*?)\z}
83
83
  parses "/:foo/*", "/foo/bar/baz", "foo" => "foo", "splat" => "bar/baz"
84
-
84
+
85
85
  converts "/:foo/:bar", %r{\A/([^/?#]+)/([^/?#]+)\z}
86
86
  parses "/:foo/:bar", "/user@example.com/name", "foo" => "user@example.com", "bar" => "name"
87
-
87
+
88
88
  converts "/test$/", %r{\A/test(?:\$|%24)/\z}
89
89
  parses "/test$/", "/test$/", {}
90
-
90
+
91
91
  converts "/te+st/", %r{\A/te(?:\+|%2[Bb])st/\z}
92
92
  parses "/te+st/", "/te+st/", {}
93
93
  fails "/te+st/", "/test/"
94
94
  fails "/te+st/", "/teeest/"
95
-
95
+
96
96
  converts "/test(bar)/", %r{\A/test(?:\(|%28)bar(?:\)|%29)/\z}
97
97
  parses "/test(bar)/", "/test(bar)/", {}
98
-
98
+
99
99
  converts "/path with spaces", %r{\A/path(?:%20|(?:\+|%2[Bb]))with(?:%20|(?:\+|%2[Bb]))spaces\z}
100
100
  parses "/path with spaces", "/path%20with%20spaces", {}
101
101
  parses "/path with spaces", "/path%2Bwith%2Bspaces", {}
102
102
  parses "/path with spaces", "/path+with+spaces", {}
103
-
103
+
104
104
  converts "/foo&bar", %r{\A/foo(?:&|%26)bar\z}
105
105
  parses "/foo&bar", "/foo&bar", {}
106
-
106
+
107
107
  converts "/:foo/*", %r{\A/([^/?#]+)/(.*?)\z}
108
108
  parses "/:foo/*", "/hello%20world/how%20are%20you", "foo" => "hello%20world", "splat" => "how%20are%20you"
109
-
109
+
110
110
  converts "/*/foo/*/*", %r{\A/(.*?)/foo/(.*?)/(.*?)\z}
111
111
  parses "/*/foo/*/*", "/bar/foo/bling/baz/boom", "splat" => ["bar", "bling", "baz/boom"]
112
112
  fails "/*/foo/*/*", "/bar/foo/baz"
113
-
113
+
114
114
  converts "/test.bar", %r{\A/test(?:\.|%2[Ee])bar\z}
115
115
  parses "/test.bar", "/test.bar", {}
116
116
  fails "/test.bar", "/test0bar"
117
-
118
- converts "/:file.:ext", %r{\A/((?:[^\./?#%]|(?:%[^2].|%[2][^Ee]))+)(?:\.|%2[Ee])((?:[^\./?#%]|(?:%[^2].|%[2][^Ee]))+)\z}
117
+
118
+ converts "/:file.:ext", %r{\A/((?:[^\./?#%]|(?:%[^2].|%[2][^Ee]))+)(?:\.|%2[Ee])((?:[^/?#%]|(?:%[^2].|%[2][^Ee]))+)\z}
119
119
  parses "/:file.:ext", "/pony.jpg", "file" => "pony", "ext" => "jpg"
120
120
  parses "/:file.:ext", "/pony%2Ejpg", "file" => "pony", "ext" => "jpg"
121
121
  fails "/:file.:ext", "/.jpg"
122
-
123
- converts "/:name.?:format?", %r{\A/((?:[^\./?#%]|(?:%[^2].|%[2][^Ee]))+)(?:\.|%2[Ee])?((?:[^\./?#%]|(?:%[^2].|%[2][^Ee]))+)?\z}
122
+
123
+ converts "/:name.?:format?", %r{\A/((?:[^\./?#%]|(?:%[^2].|%[2][^Ee]))+)(?:\.|%2[Ee])?((?:[^/?#%]|(?:%[^2].|%[2][^Ee]))+)?\z}
124
124
  parses "/:name.?:format?", "/foo", "name" => "foo", "format" => nil
125
125
  parses "/:name.?:format?", "/foo.bar", "name" => "foo", "format" => "bar"
126
126
  parses "/:name.?:format?", "/foo%2Ebar", "name" => "foo", "format" => "bar"
127
+ parses "/:name?.?:format", "/.bar", "name" => nil, "format" => "bar"
128
+ parses "/:name?.?:format?", "/.bar", "name" => nil, "format" => "bar"
129
+ parses "/:name?.:format?", "/.bar", "name" => nil, "format" => "bar"
130
+ fails "/:name.:format", "/.bar"
127
131
  fails "/:name.?:format?", "/.bar"
128
-
132
+
129
133
  converts "/:user@?:host?", %r{\A/((?:[^@/?#%]|(?:%[^4].|%[4][^0]))+)(?:@|%40)?((?:[^@/?#%]|(?:%[^4].|%[4][^0]))+)?\z}
130
134
  parses "/:user@?:host?", "/foo@bar", "user" => "foo", "host" => "bar"
131
135
  parses "/:user@?:host?", "/foo.foo@bar", "user" => "foo.foo", "host" => "bar"
132
136
  parses "/:user@?:host?", "/foo@bar.bar", "user" => "foo", "host" => "bar.bar"
133
-
137
+
134
138
  # From https://gist.github.com/2154980#gistcomment-169469.
135
139
  #
136
140
  # converts "/:name(.:format)?", %r{\A/([^\.%2E/?#]+)(?:\(|%28)(?:\.|%2E)([^\.%2E/?#]+)(?:\)|%29)?\z}
137
141
  # parses "/:name(.:format)?", "/foo", "name" => "foo", "format" => nil
138
142
  # parses "/:name(.:format)?", "/foo.bar", "name" => "foo", "format" => "bar"
139
143
  fails "/:name(.:format)?", "/foo."
140
-
144
+
141
145
  parses "/:id/test.bar", "/3/test.bar", {"id" => "3"}
142
146
  parses "/:id/test.bar", "/2/test.bar", {"id" => "2"}
143
147
  parses "/:id/test.bar", "/2E/test.bar", {"id" => "2E"}
144
148
  parses "/:id/test.bar", "/2e/test.bar", {"id" => "2e"}
145
- fails "/:id/test.bar", "/%2E/test.bar"
146
-
149
+ parses "/:id/test.bar", "/%2E/test.bar", {"id" => "%2E"}
150
+
151
+ parses '/10/:id', '/10/test', "id" => "test"
152
+ parses '/10/:id', '/10/te.st', "id" => "te.st"
153
+
154
+ parses '/10.1/:id', '/10.1/test', "id" => "test"
155
+ parses '/10.1/:id', '/10.1/te.st', "id" => "te.st"
156
+ parses '/:foo/:id', '/10.1/te.st', "foo" => "10.1", "id" => "te.st"
157
+ parses '/:foo/:id', '/10.1.2/te.st', "foo" => "10.1.2", "id" => "te.st"
158
+ parses '/:foo.:bar/:id', '/10.1/te.st', "foo" => "10", "bar" => "1", "id" => "te.st"
159
+ fails '/:foo.:bar/:id', '/10.1.2/te.st' # We don't do crazy.
160
+
161
+ parses '/:a/:b.?:c?', '/a/b', "a" => "a", "b" => "b", "c" => nil
162
+ parses '/:a/:b.?:c?', '/a/b.c', "a" => "a", "b" => "b", "c" => "c"
163
+ parses '/:a/:b.?:c?', '/a.b/c', "a" => "a.b", "b" => "c", "c" => nil
164
+ parses '/:a/:b.?:c?', '/a.b/c.d', "a" => "a.b", "b" => "c", "c" => "d"
165
+ fails '/:a/:b.?:c?', '/a.b/c.d/e'
166
+
147
167
  parses "/:file.:ext", "/pony%2ejpg", "file" => "pony", "ext" => "jpg"
148
168
  parses "/:file.:ext", "/pony%E6%AD%A3%2Ejpg", "file" => "pony%E6%AD%A3", "ext" => "jpg"
149
169
  parses "/:file.:ext", "/pony%e6%ad%a3%2ejpg", "file" => "pony%e6%ad%a3", "ext" => "jpg"
150
170
  parses "/:file.:ext", "/pony正%2Ejpg", "file" => "pony正", "ext" => "jpg"
151
171
  parses "/:file.:ext", "/pony正%2ejpg", "file" => "pony正", "ext" => "jpg"
152
- fails "/:file.:ext", "/pony正..jpg"
172
+ parses "/:file.:ext", "/pony正..jpg", "file" => "pony正", "ext" => ".jpg"
153
173
  fails "/:file.:ext", "/pony正.%2ejpg"
174
+
175
+ converts "/:name.:format", %r{\A/((?:[^\./?#%]|(?:%[^2].|%[2][^Ee]))+)(?:\.|%2[Ee])((?:[^/?#%]|(?:%[^2].|%[2][^Ee]))+)\z}
176
+ parses "/:name.:format", "/file.tar.gz", "name" => "file", "format" => "tar.gz"
177
+ parses "/:name.:format1.:format2", "/file.tar.gz", "name" => "file", "format1" => "tar", "format2" => "gz"
178
+ parses "/:name.:format1.:format2", "/file.temp.tar.gz", "name" => "file", "format1" => "temp", "format2" => "tar.gz"
179
+
180
+ # From issue #688.
181
+ #
182
+ parses "/articles/10.1103/:doi", "/articles/10.1103/PhysRevLett.110.026401", "doi" => "PhysRevLett.110.026401"
154
183
  end
@@ -877,7 +877,7 @@ class RoutingTest < Test::Unit::TestCase
877
877
  application/x-pkcs7-mime
878
878
  application/x-pkcs7-signature
879
879
  )
880
-
880
+
881
881
  mime_types.each { |mime_type| assert mime_type.match(Sinatra::Request::HEADER_VALUE_WITH_PARAMS) }
882
882
  end
883
883
 
@@ -899,7 +899,17 @@ class RoutingTest < Test::Unit::TestCase
899
899
  assert_equal 'application/xml', body
900
900
  assert_equal 'application/xml;charset=utf-8', response.headers['Content-Type']
901
901
 
902
- get '/', {}, { :accept => 'text/html' }
902
+ get '/', {}, {}
903
+ assert ok?
904
+ assert_equal '', body
905
+ assert_equal 'application/xml;charset=utf-8', response.headers['Content-Type']
906
+
907
+ get '/', {}, { 'HTTP_ACCEPT' => '*/*' }
908
+ assert ok?
909
+ assert_equal '*/*', body
910
+ assert_equal 'application/xml;charset=utf-8', response.headers['Content-Type']
911
+
912
+ get '/', {}, { 'HTTP_ACCEPT' => 'text/html;q=0.9' }
903
913
  assert !ok?
904
914
 
905
915
  get '/foo', {}, { 'HTTP_ACCEPT' => 'text/html;q=0.9' }
@@ -907,6 +917,14 @@ class RoutingTest < Test::Unit::TestCase
907
917
  assert_equal 'text/html;q=0.9', body
908
918
 
909
919
  get '/foo', {}, { 'HTTP_ACCEPT' => '' }
920
+ assert ok?
921
+ assert_equal '', body
922
+
923
+ get '/foo', {}, { 'HTTP_ACCEPT' => '*/*' }
924
+ assert ok?
925
+ assert_equal '*/*', body
926
+
927
+ get '/foo', {}, { 'HTTP_ACCEPT' => 'application/xml' }
910
928
  assert !ok?
911
929
 
912
930
  get '/stream', {}, { 'HTTP_ACCEPT' => 'text/event-stream' }
@@ -914,6 +932,14 @@ class RoutingTest < Test::Unit::TestCase
914
932
  assert_equal 'text/event-stream', body
915
933
 
916
934
  get '/stream', {}, { 'HTTP_ACCEPT' => '' }
935
+ assert ok?
936
+ assert_equal '', body
937
+
938
+ get '/stream', {}, { 'HTTP_ACCEPT' => '*/*' }
939
+ assert ok?
940
+ assert_equal '*/*', body
941
+
942
+ get '/stream', {}, { 'HTTP_ACCEPT' => 'application/xml' }
917
943
  assert !ok?
918
944
  end
919
945
 
@@ -959,20 +985,6 @@ class RoutingTest < Test::Unit::TestCase
959
985
  end
960
986
  end
961
987
 
962
- it 'degrades gracefully when optional accept header is not provided' do
963
- mock_app {
964
- get '/', :provides => :xml do
965
- env['HTTP_ACCEPT']
966
- end
967
- get '/' do
968
- 'default'
969
- end
970
- }
971
- get '/'
972
- assert ok?
973
- assert_equal 'default', body
974
- end
975
-
976
988
  it 'respects user agent preferences for the content type' do
977
989
  mock_app { get('/', :provides => [:png, :html]) { content_type }}
978
990
  get '/', {}, { 'HTTP_ACCEPT' => 'image/png;q=0.5,text/html;q=0.8' }
@@ -986,8 +998,6 @@ class RoutingTest < Test::Unit::TestCase
986
998
  get('/', :provides => :xml) { content_type }
987
999
  get('/') { 'no match' }
988
1000
  end
989
- get '/'
990
- assert_body 'no match'
991
1001
  get '/', {}, { 'HTTP_ACCEPT' => 'foo/*' }
992
1002
  assert_body 'no match'
993
1003
  get '/', {}, { 'HTTP_ACCEPT' => 'application/*' }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sinatra
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.1
4
+ version: 1.4.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2013-03-15 00:00:00.000000000 Z
15
+ date: 2013-03-21 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: rack
@@ -236,7 +236,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
236
236
  version: '0'
237
237
  segments:
238
238
  - 0
239
- hash: 2287557311002662172
239
+ hash: 748751327798285916
240
240
  required_rubygems_version: !ruby/object:Gem::Requirement
241
241
  none: false
242
242
  requirements:
@@ -245,7 +245,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
245
245
  version: '0'
246
246
  segments:
247
247
  - 0
248
- hash: 2287557311002662172
248
+ hash: 748751327798285916
249
249
  requirements: []
250
250
  rubyforge_project:
251
251
  rubygems_version: 1.8.23