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 +9 -0
- data/README.es.md +37 -35
- data/README.md +19 -10
- data/lib/sinatra/base.rb +53 -19
- data/lib/sinatra/version.rb +1 -1
- data/test/compile_test.rb +59 -30
- data/test/routing_test.rb +28 -18
- metadata +4 -4
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)
|
data/README.es.md
CHANGED
@@ -15,7 +15,7 @@ get '/' do
|
|
15
15
|
end
|
16
16
|
```
|
17
17
|
|
18
|
-
Instalá
|
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
|
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
|
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
|
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
|
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
|
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:
|
416
|
-
métodos de renderización van a renderizar
|
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
|
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,
|
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
|
1144
|
-
|
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
|
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`
|
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
|
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)
|
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
|
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
|
-
|
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
|
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
|
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
|
-
|
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
|
-
|
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
|
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,
|
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
|
-
|
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
|
-
|
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
|
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
|
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.
|
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.
|
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
|
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
|
-
|
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
|
-
|
496
|
-
methods will render any strings passed to them
|
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
|
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
|
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
|
-
|
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
|
-
|
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:
|
data/lib/sinatra/base.rb
CHANGED
@@ -28,9 +28,11 @@ module Sinatra
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def preferred_type(*types)
|
31
|
-
|
31
|
+
accepts = accept # just evaluate once
|
32
|
+
return accepts.first if types.empty?
|
32
33
|
types.flatten!
|
33
|
-
|
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
|
-
|
1420
|
-
|
1421
|
-
|
1422
|
-
|
1423
|
-
|
1424
|
-
|
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
|
-
|
1428
|
-
|
1429
|
-
|
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
|
-
|
1433
|
-
ignore_pattern = safe_ignore(ignore)
|
1434
|
-
|
1435
|
-
ignore_pattern
|
1469
|
+
segments << segment
|
1436
1470
|
end
|
1437
1471
|
end
|
1438
|
-
[/\A#{
|
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,
|
1478
|
+
[path, []]
|
1445
1479
|
else
|
1446
1480
|
raise TypeError, path
|
1447
1481
|
end
|
data/lib/sinatra/version.rb
CHANGED
data/test/compile_test.rb
CHANGED
@@ -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
|
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])((?:[
|
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])?((?:[
|
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
|
-
|
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
|
-
|
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
|
data/test/routing_test.rb
CHANGED
@@ -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 '/', {}, {
|
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.
|
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
|
+
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:
|
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:
|
248
|
+
hash: 748751327798285916
|
249
249
|
requirements: []
|
250
250
|
rubyforge_project:
|
251
251
|
rubygems_version: 1.8.23
|