为什么 Rails RSpec 响应显示 302 而不是 401? [英] Why does Rails RSpec response show 302 instead of 401?

查看:56
本文介绍了为什么 Rails RSpec 响应显示 302 而不是 401?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经被这个问题困扰了好几天了,我不知道它有什么问题.几个月前我开始使用 Ruby on Rails,目前我正在学习使用 API 进行身份验证.我在这里那里,但他们都没有帮助.

I have been stuck on this problem for several days and I don't know what is wrong with it. I started Ruby on Rails few months ago and I am currently learning authentication with API. I have looked at other similar topics here and there but none of them helped.

我的问题是每当我在此代码上运行 RSpec(位于 spec/api/v1/controllers/posts_controller_spec.rb)

My problem is whenever I run RSpec on this code (located at spec/api/v1/controllers/posts_controller_spec.rb)

require 'rails_helper'

RSpec.describe Api::V1::PostsController, type: :controller do
  let(:my_user) { create(:user) }
  let(:my_topic) { create(:topic) }
  let(:my_post) { create(:post, topic: my_topic, user: my_user) }

  context "unauthenticated user" do

    it "PUT update returns http unauthenticated" do
      put :update, topic_id: my_topic.id, id: my_post.id, post: {title: my_post.title, body: my_post.body}
      expect(response).to have_http_status(401)
    end
    ...

我一直在接受

...
spec/api/v1/controllers/posts_controller_spec.rb -e "unauthenticated user"
Run options: include {:full_description=>/unauthenticated\ user/}
FFF

Failures:

  1) PostsController unauthenticated user PUT update returns http unauthenticated
     Failure/Error: expect(response).to have_http_status(401)
       expected the response to have status code 401 but it was 302
     # ./spec/api/v1/controllers/posts_controller_spec.rb:12:in `block (3 levels) in <top (required)>'

如果这有帮助,我的控制器 app/controllers/api/v1/posts_controller_spec.rb

If this helps, my controller, app/controllers/api/v1/posts_controller_spec.rb has

class Api::V1::PostsController < Api::V1::BaseController
  before_action :authenticate_user, except: [:index, :show]
  before_action :authorize_user, except: [:index, :show]


     def update
       post = Post.find(params[:id])

       if post.update_attributes(post_params)
         render json: post.to_json, status: 200
       else
         render json: {error: "Post update failed", status: 400}, status: 400
       end
     end
    ...

我的 base_controller

My base_controller

class Api::V1::BaseController < ApplicationController

  skip_before_action :verify_authenticity_token

  rescue_from ActiveRecord::RecordNotFound, with: :not_found
  rescue_from ActionController::ParameterMissing, with: :malformed_request

  def authenticate_user
    authenticate_or_request_with_http_token do |token, options|
      @current_user = User.find_by(auth_token: token)
    end
  end

  def authorize_user
    unless @current_user && @current_user.admin?
      render json: {error: "Not Authorized", status: 403}, status: 403
    end
  end

  def malformed_request
    render json: {error: "The request could not be understood by the server due to malformed syntax. The client SHOULD NOT repeat the request without modifications.", status: 400}, status: 400
  end

  def not_found
    render json: {error: "Record not found", status: 404}, status: 404
  end
end

最后,routes.rb 显示:

Lastly, routes.rb shows:

  namespace :api do
   namespace :v1 do
     resources :users, only: [:index, :show, :create, :update]
     resources :topics, except: [:edit, :new] do
       resources :posts, only: [:update, :create, :destroy]
     end
   end
 end

我有一种强烈的预感,我的 before_action 是罪魁祸首,但我无法确定我做错了什么.我使用类似的 RSpec 测试和我的 Topic RSpec 通过在主题上做了类似的事情(帖子嵌套在主题中),而我的帖子 RSpec 惨遭失败.

I have a strong hunch that my before_action is the culprit, but I can't pinpoint what I did wrong. I have done similar thing on Topics (Posts are nested within Topics) using similar RSpec testing and my Topic RSpec passes, whereas my Posts RSpec fail miserably.

谁能帮我指出我做错了什么,我怎样才能通过 RSpec 测试而不显示 302 状态代码?

Can someone please help me to point out what I did wrong, and how can I pass the RSpec test and not show 302 status code?

另外,为什么显示 302 状态代码?

As an extra, why did it show 302 status code?

推荐答案

问题是你正在使用

before_action :authenticate_user, 除了:[:index, :show],可能是 Devise 的助手,对吗?如果是这样,当您尝试在未登录的情况下访问资源时,此助手会将您重定向到登录页面,这是您在使用浏览器时预期会发生的事情,而浏览器不是您的案件.您可以找到一些替代方案,覆盖设计行为,我的解决方案是定义我的 authenticate_user! 方法,如果用户未登录,则使用另一个设计助手方法返回 401,如下所示:

before_action :authenticate_user, except: [:index, :show], probably the helper from Devise, correct? If so, when you try to access a resource without being logged in, this helper will redirect you to the login page, something that you expect to happen when you're using a browser, which is not your case. You can find some alternatives, overwriting the Devise behavior, my solution was to define my authenticate_user! method to return a 401 if the user was not signed in, using another devise helper method, something like this:

    def authenticate_user!
      if user_signed_in?
        @user = current_user
      else
        head :unauthorized
      end 
    end 

这只是对我有用的情况,你的可能不同.

This is just the case that worked for me, yours may be different.

这篇关于为什么 Rails RSpec 响应显示 302 而不是 401?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆