Ruby on Rails 对所有路由响应“无路由匹配”,而 rack routes 命令按预期显示它们

Ruby on Rails responds "no route matches" for all routes while rack routes command shows them as expected

提问人:lembon 提问时间:5/19/2023 更新时间:5/20/2023 访问量:109

问:

情况

我绝对是 Ruby 的新手,但对 Django、Node 和其他技术有一定的经验。 我正在尝试在我的本地运行我的雇主的遗留项目,该项目实际上是在生产中运行的。我做的第一件事是将其docker化。Puma 服务器启动良好,它连接到 postgres 数据库,对根 127.0.0.1:3000 的响应正常,带有 Rails 默认欢迎页面。甚至 swagger 也会显示预期的端点,甚至 /rails/info/routes 也会完美地显示路由。此外,耙子路由显示完全相同:

user@local:~/path_to/project$ sudo docker compose exec app rake routes
                               Prefix Verb   URI Pattern                                                                              Controller#Action                                                                 api/v1/users#index
                                      POST   /api/users(.:format)                                                                     api/v1/users#create
                             api_user GET    /api/users/:id(.:format)                                                                 api/v1/users#show
                                      PATCH  /api/users/:id(.:format)                                                                 api/v1/users#update
                                      PUT    /api/users/:id(.:format)                                                                 api/v1/users#update
                                      DELETE /api/users/:id(.:format)                                                                 api/v1/users#destroy
                       api_auth_login POST   /api/auth/login(.:format)                                                                api/v1/authentication#login

但是当我向 /api/auth/login 发出请求时,它会响应:

    {
    "status": 404,
    "error": "Not Found",
    "exception": "#<ActionController::RoutingError: No route matches [POST] \"/api/auth/login\">",
    "traces": {
        "Application Trace": [],
        "Framework Trace": [
            {
                "exception_object_id": 47259696989680,
                "id": 0,
                "trace": "actionpack (6.0.3.7) lib/action_dispatch/middleware/debug_exceptions.rb:36:in `call'"
            },
            {
                "exception_object_id": 47259696989680,
                "id": 1,
                "trace": "actionpack (6.0.3.7) lib/action_dispatch/middleware/show_exceptions.rb:33:in `call'"
            }, 
[...]

控制器

├── controllers
│   ├── api
│   │   └── v1
│   │       ├── api_controller.rb
│   │       ├── authentication_controller.rb
│   │       ├── axes_controller.rb
│   │       ├── invites_controller.rb
│   │       ├── metrics_controller.rb
│   │       ├── organizations_controller.rb
│   │       └── users_controller.rb
│   └── application_controller.rb

authentication_controller.rb

module Api::V1
  class AuthenticationController < ApiController
    before_action :authorize_request, except: :login
    include AuthHelper
    def login
      @user = User.find_by(game_id: params[:game_id], email: params[:email])
      if @user&& @user.valid_password?(params[:password])
        render json: generateToken(@user), status: :ok
      else
        render json: { error: 'unauthorized' }, status: :unauthorized
      end
    end

    private

    def login_params
      params.permit(:email, :password, :game_id)
    end
   
  end
end

config/routes.rb

Rails.application.routes.draw do
  
  mount Rswag::Ui::Engine => '/api-docs'
  mount Rswag::Api::Engine => '/api-docs'
  devise_for :users
  # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
  namespace :api do
    scope module: :v1, constraints: ApiVersion.new('v1') do

      resources :axes
      get '/metrics', to: 'metrics#get_metrics'
      get '/requests', to: 'organizations#requests'
      resources :organizations
      resources :invites
      resources :users do 
        post 'forgot_password', on: :collection
        post 'reset_password', on: :collection
        post 'google_auth', on: :collection
        get 'check_hash', on: :collection
        get 'export', on: :collection
      end
      post '/auth/login', to: 'authentication#login'
      post '/addmember', to: 'users#addUserOrganization'
      get '/*a', to: 'application#not_found'
    end
  end
end

我不知道还能尝试什么。请帮忙!!

Ruby-on-Rails 路线

评论

0赞 dbugger 5/19/2023
请出示您尝试拨打的电话。
2赞 Alex 5/19/2023
您对 API 路由有约束,这些约束也必须与请求匹配。ApiVersion.new('v1')
0赞 lembon 5/19/2023
我正在尝试向 127.0.0.1:3000/api/auth/login 发出 POST 请求。这就是它在生产中的工作方式。我也尝试过.../api/v1/auth/login,结果相同。
0赞 lembon 5/19/2023
@Alex这是问题所在,但约束需要一些自定义标头。谢谢。

答:

1赞 lembon 5/19/2023 #1

我没有意识到约束,现在正在寻找 ApiVersion 类......

class ApiVersion
  attr_reader :version, :default

   def initialize(version, default = false)
    @version = version
    @default = default
  end

   # check whether version is specified or is default
  def matches?(request)
    check_headers(request.headers) || default
  end

   private

   def check_headers(headers)

    accept = headers[:accept]
    accept && accept.include?("application/vnd.some_string.#{version}+json")
  end
end

所以添加标题

Accept: "application/vnd.some_string.v1+json"

做到了。