2011-12-14 19 views
16

Estoy tratando de solucionar un problema donde Rails no está decodificando los datos de JSON POST.Rails La solicitud JSON no se analiza correctamente en los parámetros de publicación

Los registros del servidor muestran:

2011-12-14T06:44:44+00:00 app[web.2]: Started POST 
2011-12-14T06:44:44+00:00 app[web.2]: Processing by PostsController#create as */* 
2011-12-14T06:44:44+00:00 app[web.2]: Parameters: {"{\"athlete_id\":\"\",\"known_as\":\"abc\",\"email\":\"[email protected]\",\"result\":\"112233\",\"rx\":false,\"mods\":\"thkjth\",\"notes\":\"\"}"=>nil, "affiliate_id"=>"testaffiliate", "wod_id"=>"12345"} 

Tenga en cuenta que la cadena JSON no está siendo analizada - Carriles se le asigna como clave en el hash, que apunta a un valor nulo. ¿Alguien tiene alguna idea antes de escribir un before_filter que intente con JSON.parse con todas las claves de params?

No creo que esto sea relevante ya que estoy enviando y recibiendo datos bien, pero este problema ocurre durante una Solicitud CORS desde IE (usando XDomainRequest).

Respuesta

9
before_filter :fix_ie_params, only: [:create, :update] 

Para Thin:

def fix_ie_params 
    if request.format == '*/*' 
    # try to JSON decode in case of IE XDR 
    begin 

     params.merge! ActiveSupport::JSON.decode(request.body.string) 

    rescue Exception=>e 
     # todo: log exception 
    end 
    end 
end 

Para unicornio y Phusion pasajeros:

def fix_ie_params 
    if request.format == '*/*' 
    # try to JSON decode in case of IE XDR 
    begin 

     request.body.rewind 
     params.merge! ActiveSupport::JSON.decode(request.body.read) 

    rescue Exception=>e 
     # todo: log exception 
    end 
    end 
end 
+0

Encontré que al hacer esto (en unicornio) I el cuerpo de la solicitud incluida en los params como una clave: '{'theBodyOfRequest' => nil,: controller => users,: action => 'update'}' Dependiendo de su caso de uso esto podría causar problemas. Como es el primer param, agregué 'params.shift' para eliminarlo. – Peter

+0

@collin, sí - Los datos que estaba PUBLICANDO eran originalmente JSON '{: foo =>" bar "}' (que fue codificado para enviar) por lo que los parámetros en el controlador se veían así: '{" {\ "foo \" => \ "bar \"} => nil, "controller" => "users" ...} ' – Peter

+0

@Peter, que suena como el problema original que describí en la pregunta, ¿no? ¿Estás seguro de que su filtro se está ejecutando? – colllin

16

Puede pasar esto configurando el encabezado Content-Type en "application/json". Puede informar al controlador lo que espera devolver con el encabezado Aceptar establecido en "aplicación/json".

El siguiente comando con ambas cabeceras:

curl -d '{ "company": { "name": "acme", "address": "123 Carrot Street" } }' http://0.0.0.0:3000/mysite --header "Accept: application/json" --header "Content-Type: application/json" 

genera este en los registros de:

Started POST "/mysite" for 127.0.0.1 at 2012-01-11 16:09:48 -0800 
    Processing by MyController#create as JSON 
    Parameters: {"company"=>{"name"=>"acme", "address"=>"123 Carrot Street"}, "wassup"=>{"company"=>{"name"=>"acme", "address"=>"123 Carrot Street"}, "controller"=>"wassup", "action"=>"create"}} 
Completed 200 OK in 5ms (Views: 2.0ms | ActiveRecord: 0.0ms) 

Este comando con el encabezado Accept:

curl -d '{ "company": { "name": "acme", "address": "123 Carrot Street" } }' http://0.0.0.0:3000/mysite --header "Accept: application/json" 

genera estos registros:

Started POST "/mysite" for 127.0.0.1 at 2012-01-11 16:07:26 -0800 
    Processing by MyController#create as JSON 
    Parameters: {"{ \"company\": { \"name\": \"acme\", \"address\": \"123 Carrot Street\" } }"=>nil} 
Completed 200 OK in 7ms (Views: 5.0ms | ActiveRecord: 0.0ms) 

Y finalmente este comando con la cabecera Content-Type:

curl -d '{ "company": { "name": "acme", "address": "123 Carrot Street" } }' http://0.0.0.0:3000/mysite --header "Content-Type: application/json" 

genera estos registros:

Started POST "/mysite" for 127.0.0.1 at 2012-01-11 16:08:11 -0800 
    Processing by MyController#create as */* 
    Parameters: {"company"=>{"name"=>"acme", "address"=>"123 Carrot Street"}, "wassup"=>{"company"=>{"name"=>"acme", "address"=>"123 Carrot Street"}, "controller"=>"wassup", "action"=>"create"}} 
Completed 200 OK in 4ms (Views: 2.0ms | ActiveRecord: 0.0ms) 

Aviso los parámetros analizados y procesamiento de mensajes de cambio sutilmente con cada uno tipo de encabezado

+3

Muchas gracias por su respuesta! Desafortunadamente, con XDomainRequest no tengo control sobre los encabezados. (Consulte los puntos 3 y 4 en [este artículo] (http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx).) Así que Creo que esta es probablemente la respuesta correcta, pero no acaba de resolver mi problema. ¿Sabes si hay alguna manera de decirle al controlador que asuma que todo es una solicitud JSON? ¿O al menos establecer el tipo de contenido predeterminado en JSON? – colllin

+1

El json se analiza en el miembro de params (en rails 3.1) en params_parser.rb que contiene ActionDispatch :: ParamsParser y es una pieza de middleware. Puede agregar otra pieza de middleware que infiere el tipo de solicitud entrante y la configura de manera adecuada. Sin embargo, si va a hacer eso, debería poner algo de lógica en el controlador para hacer eso con su código particular y no alterar el resto de la pila de middleware. – Grant

Cuestiones relacionadas