El método params del controlador Sinatra está vacío en la solicitud de publicación JSON
(2)
Para responder a esta pregunta, primero tendremos que ver algunas solicitudes HTTP (que no son más que simples ''mensajes'' de telnet
; esto se puede recrear fácilmente a mano). Primero, ¿qué sucede cuando envía un <form>
HTML normal? La solicitud POST
se verá muy similar a esto (probablemente con algunos parámetros adicionales, pero no tenemos que preocuparnos por eso ahora):
POST /submit-form HTTP/1.1
Host: localhost
Content-Type: application/x-www-form-urlencoded
Content-Length: 12
name=JohnDoe
Escribir ese carácter por carácter (reemplazando /sample-form
con cualquiera que sea la URL para cualquier acción de formulario, y el Host
con su IP o nombre de host) será lo mismo que enviaría su navegador. Lo importante para aprender de esto es la sintaxis de los parámetros: formname=formvalue
. ¡Sinatra interpreta el cuerpo de la solicitud POST
en el hash params
usando esta sintaxis! Por lo tanto, las solicitudes JSON, al ser sustancialmente incompatibles con esto, no se mostrarán en el hash params
debido a esto.
Sin embargo, lo que estás haciendo en tu bloque before
muestra la solución adecuada. Si bien los params
de los anteriores serían {''name'' => ''JohnDoe''}
, request.body.read
devolverá el cuerpo original, name=JohnDoe
.
Al saber esto, uno puede llegar a entender por qué funciona su solución ''hacky'': el cuerpo original de la solicitud POST
es interpretado por JSON.parse
, y luego se inserta en el hash de params
vacío. La razón por la que parece intrépido es que params
es un intermediario innecesario en este ejemplo. Lo siguiente debe hacer el trabajo:
post ''/locations/new'' do
@json = JSON.parse(request.body.read)
# @json now contains a hash of the submitted JSON content
end
Sin embargo, una solución que ejerza mejores prácticas solo respondería si se proporciona contenido JSON o responderá de manera diferente si se envía un formulario estándar. Como se vio en el ejemplo anterior de la solicitud HTTP POST
, un formulario HTML se identifica con el tipo MIME de la application/x-www-form-urlencoded
, mientras que JSON se identifica con la application/json
. Si desea obtener información específica sobre la verificación del tipo MIME de la solicitud POST
, consulte esta pregunta con algunas respuestas excelentes sobre cómo hacer esto con Sinatra.
Tengo una aplicación de Sinatra y en la mayoría de mis controladores json entra y se recoge automáticamente en el objeto params. Sin embargo, tengo una acción posterior que no obtiene los parámetros en absoluto a menos que juegue un truco con un método anterior para extraer la solicitud. Los parámetros de cuerpo los analizan como JSON y los combinan en el hash de parámetros.
Aquí está el controlador, junto con el método de filtro:
before do
if request.request_method == "POST"
body_parameters = request.body.read
params.merge!(JSON.parse(body_parameters))
end
end
post ''/locations/new'' do
content_type :json
puts "params after post params method = #{params.inspect}"
... other code ...
end
La salida que veo es básicamente que los parámetros en la acción del controlador en realidad están allí correctamente. Sin embargo, si comento fuera de la llamada los parámetros están vacíos.
El antes en sí se siente como un hack. Espero que esos parámetros lleguen en cualquier lugar ... Debo estar haciendo algo mal allí, pero no sé qué es.
Cualquier ayuda sería muy apreciada...
Tuvo un problema similar: la publicación de parámetros JSON de java al servicio sinatra
Encontré una mejor solución para lidiar con ella, agregando un middleware para hacer lo mismo por mí. Utilicé la gema del bastidor. Los siguientes son los cambios que hice en mi código:
EDITAR: use git para obtener la versión específica, donde soluciona el problema cuando el tipo de contenido es application/json;charset=UTF-8
Gemfile:
gem ''rack-contrib'', git: ''[email protected]:rack/rack-contrib'', ref: ''b7237381e412852435d87100a37add67b2cfbb63''
config.ru:
use Rack::PostBodyContentTypeParser
fuente: http://jaywiggins.com/2010/03/using-rack-middleware-to-parse-json/