【问题标题】:JSON POST request for Rails 4.0 app gives response code 500Rails 4.0 应用程序的 JSON POST 请求提供响应代码 500
【发布时间】:2015-07-18 20:35:18
【问题描述】:

我在向我的 Rails 4.0 应用程序发布 JSON 请求以进行登录时遇到问题。我设置了一个非常小的登录-注销会话控制器,以便了解 Rails 如何接受JSON 请求,而不是摆弄像 devise 这样更丰富的库。在客户端和服务器端经过数小时的混淆以及混合和匹配方法之后,我相信问题在于我对 Rails 如何解析以字符串形式到达并可以通过 Rails 处理的 JSON 请求缺乏了解。用于登录和注销的会话控制器如下:

class SessionsController < ApplicationController
  respond_to do |format|
      format.html
      format.json {render json: params}
  end

  def new    
  end

  def create
    user = User.find_by(email: params[:session][:email].downcase)
    if user && user.authenticate(params[:session][:password])
      log_in user
      params[:session][:remember_me] == '1' ? remember(user) : forget(user)
      redirect_to user
    else
      flash.now[:danger] = 'Invalid email/password combination
      render 'new'
    end
  end

  def destroy
    log_out if logged_in?
    redirect_to root_url
  end
end

Rails 上的活动在收到 JSON 请求时显示如下:

Started POST "/login/" for ::1 at 2015-07-17 21:47:49 +0000
Processing by SessionsController#create as JSON
  Parameters: {"{session:{email: 'user@example.com',password: 'aaaaaa', remember_me: 1}}"=>"[FILTERED]"}
Completed 500 Internal Server Error in 5ms (ActiveRecord: 0.0ms)

NoMethodError (undefined method `[]' for nil:NilClass):
  app/controllers/sessions_controller.rb:13:in `create'

我尝试了许多变体,包括在键和关联值周围加上引号,只在键和值周围加上引号,但最终,JSON 请求将被提取为具有以下未解析格式的字符串:“{session ......}" 或 "session:{...}" 而不是像

这样的已解析哈希
"session"=>{"email"=>"user@example.com", "password"=>"[FILTERED]", "remember_me"=>"0"}

作为参考,我从浏览器成功登录得到的消息显示如下:

Started POST "/login" for ::1 at 2015-07-18 13:28:45 +0000
Processing by SessionsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"AmuA2AJUYmnnexUUTCYsLhyNTxUI1t4sf7rbW9WcD7/Amt33DMAR8QHQM5U9RT0oEd0Y5jN564r7bpVf9PjxAg==", "session"=>{"email"=>"user@example.com", "password"=>"[FILTERED]", "remember_me"=>"0"}, "commit"=>"Log in"}
  User Load (16.5ms)  SELECT  "users".* FROM "users" WHERE "users"."email" = ? LIMIT 1  [["email", "user@example.com"]]
   (0.1ms)  begin transaction
   (0.1ms)  commit transaction
Redirected to http://localhost:3000/users/1
Completed 302 Found in 313ms (ActiveRecord: 17.4ms)

任何帮助将不胜感激。

附录:

下面是登录视图的代码:

<% provide(:title, 'Login') %>
<h1>Log in</h1>
<div class='row'>
    <div class='col-md-6 col-md-offset-3'>
        <%= form_for(:session, url: login_path) do |f| %>

            <%= f.label :email %>
            <%= f.email_field :email, class:'form-control' %>

            <%= f.label :password %>
            <%= f.password_field :password, class:'form-control' %>

            <%= f.label :remember_me, class: 'checkbox inline' do%>
                <%= f.check_box :remember_me %>
                <span>Remember me on this computer</span>
            <%= f.text_area :buh, class:'form-control' %>
            <% end %>


            <%= f.submit 'Log in', class:'btn btn-primary'%>

            <p>New user? <%= link_to 'Sign up now!', signup_path %></p>
        <% end %>
    </div>
</div>

以及用于发布 http 请求的 Objective C 代码:

- (IBAction)loginPressed:(UIButton *)sender {
    NSInteger success = 0;

//payload below
    NSString *cookie = [self CSRFTokenFromURL:@"http://localhost:3000/login"];

    NSString *post = [[NSString alloc] initWithFormat:@"'session':{'email': '%@','password': '%@', 'remember_me': '1' }",username.text,password.text];
    NSLog(@"Postdata: %@",post);

    NSURL *url = [NSURL URLWithString: @"http://localhost:3000/login/"];

    NSData *postData = [post dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES];

    NSString *postLength = [NSString stringWithFormat:@"%lu", (unsigned long)[post length]];

    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
    [request setURL:url];
    [request setHTTPMethod: @"POST"];
    [request setValue:postLength forHTTPHeaderField:@"Content-Length"];
    [request setValue:token forHTTPHeaderField:@"X-CSRF-Token"];
    [request setValue:@"application/json" forHTTPHeaderField:@"Accept"];
    [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
    [request setHTTPBody:postData];

    NSError *error = [[NSError alloc] init];
    NSHTTPURLResponse *response = nil;
    NSData *urlData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];

    NSLog(@"Response code: %ld", [response statusCode]);

    if ([response statusCode] >= 200 && [response statusCode] < 300) {
        NSString *responseData = [[NSString alloc] initWithData:urlData encoding:NSUTF8StringEncoding];
        NSLog(@"Response ==> %@", responseData);

        NSError *error = nil;
        NSDictionary *jsonData = [NSJSONSerialization JSONObjectWithData:urlData
                                                                 options:NSJSONReadingMutableContainers
                                                                   error:&error];
        success = [jsonData[@"success"] integerValue];
        NSLog(@"Success: %ld",(long)success);

        if (success == 1) {
            NSLog(@"Login SUCCESS");
        } else {
            NSString *error_msg = (NSString *) jsonData[@"error_message"];
            [self alertStatus:error_msg :@"Sign in Failed!" :0];
        }
    }
}

再次,我这样做是为了让自己了解 Rails 使用 JSON httprequests 的基本方式,而不是使用 RESTKit、AFNetworking、Devise 或其他各种库来处理登录会话的创建,介于 Objective C 和 Rails 之间,这就是我保留 Objective C 的原因,因为我认为它会使原始请求变得比必要的更混乱。

【问题讨论】:

  • 如果请求包含标头Content-Type: application/json,则应自动为您解析参数。查看发出请求的前端代码(任何 HTML 和 JavaScript)可能很有用。
  • 看来你的参数是字符串。如何创建请求?
  • james246:我没有任何 HTML 或 JS 的请求,虽然我已经添加了要使用浏览器提交的表单的视图代码,现在我已经包含在我的原始帖子以及用于构建和发布请求的 Objective C。
  • BroiSatse:我通过在刚刚添加的表单上发布或通过 Objective C 生成的 JSON 请求来创建它。
  • 您的 objectve C 代码在这里出错。看看这个问题来解决它:stackoverflow.com/questions/16698387/…

标签: ruby-on-rails ruby json ruby-on-rails-4


【解决方案1】:

如果您仔细查看参数,您会发现它们的格式不正确,我建议您使用 curl 进行测试:

curl -H "Content-Type: application/json" -X POST -d '"session":{"email":"user@example.com", "password":"yourpass", "remember_me":"0"}' http://localhost:3000/login

【讨论】:

  • 鲁斯塔姆:谢谢。我尝试了您提供的代码,正如您所预测的那样,测试失败了,并且使用了我一直在使用的另一种格式,它通过了我想要的哈希解析。代码如下:curl -H "Content-Type: application/json" -X POST -d '{"session":{"email":"user@example.com", "password":"yourpass", "remember_me":"0"}}' http://localhost:3000/login
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-30
  • 1970-01-01
  • 1970-01-01
  • 2016-07-21
  • 1970-01-01
相关资源
最近更新 更多