AnyCable request.params 在生产中为空

Posted

技术标签:

【中文标题】AnyCable request.params 在生产中为空【英文标题】:AnyCable request.params is empty in production 【发布时间】:2021-07-09 06:56:48 【问题描述】:

我有一个带有 Rails 和 Anycable 的 Docker 设置。只有在 production 中 request.params 不返回任何内容。在开发中,这不是问题。

如果我尝试连接到wss://api.test.to:8443/live?uid=yyy&token=xxx

进行了连接尝试,但在我的connection.rb 中,request.params 始终返回一个空对象。

这是我相当标准的connection.rb。

module ApplicationCable
  class Connection < ActionCable::Connection::Base
    identified_by :current_user

    def connect
      self.current_user = find_verified_user
    end

    private

    def find_verified_user
      auth_header = request.params[:token]
      uid_header = request.params[:uid]

      logger.debug(request.params[:token]) # logs nothing
      logger.debug(request.to_yaml) # logs request object with no parameters included.
      
      begin
        decoded = JsonWebToken.decode(auth_header) 
      rescue JWT::VerificationError, JWT::ExpiredSignature, JWT::DecodeError => error_string
        logger.debug("AUTH ERROR: " + error_string.to_s)
        return reject_unauthorized_connection # If decoding the JWT failed, reject auth.
      end
      
      user_decoded = User.find(decoded[:user_id])

      if user_decoded.id === uid_header
        return user_decoded
      else
        return reject_unauthorized_connection
      end
    end
    
  end
end

docker-compose.yml:

version: '3.8'

services:
  app:
    image: app-backend
    build:
      context: .
      dockerfile: Dockerfile
    command: bundle exec rails s -b 0.0.0.0
    depends_on:
      - database
      - redis
    volumes:
      - .:/app:cached
      - gem_cache:/usr/local/bundle/gems:cached
    env_file: production.env
    environment:
      RAILS_ENV: production

  database:
    image: postgres:13-alpine
    ports:
      - '5432:5432'
    volumes:
      - db_data:/var/lib/postgresql/data
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql:delegated
    healthcheck:
      test: pg_isready -U postgres -h 127.0.0.1
      interval: 5s

  redis:
    image: redis:alpine
    volumes:
      - redis_data:/data
    ports:
      - 6379
    healthcheck:
      test: redis-cli ping
      interval: 1s
      timeout: 3s
      retries: 30

  rpc:
    entrypoint: ["bundle", "exec", "anycable"]
    build:
      context: .
    volumes:
      - .:/app:cached
      - gem_cache:/usr/local/bundle/gems:cached
    env_file: production.env
    environment:
      RAILS_ENV: production
      ANYCABLE_REDIS_URL: redis://redis:6379/0
      ANYCABLE_RPC_HOST: 0.0.0.0:50051
      ANYCABLE_DEBUG: 0
    depends_on:
      app:
        condition: service_started
      database:
        condition: service_healthy
      redis:
        condition: service_healthy

  anycable:
    image: anycable/anycable-go:latest-alpine
    entrypoint: ["anycable-go", "-ssl_cert=/var/ssl/certbot/conf/live/api.pasta.to/fullchain.pem", "-ssl_key=/var/ssl/certbot/conf/live/api.pasta.to/privkey.pem", "--path=/live", "--log_level=debug", "--debug"]
    ports:
      - '8443:8443'
    environment:
      ANYCABLE_HOST: "0.0.0.0"
      ANYCABLE_PORT: 8443
      ANYCABLE_REDIS_URL: redis://redis:6379/0
      ANYCABLE_RPC_HOST: rpc:50051
      ANYCABLE_DEBUG: 1
    volumes:
      - ./ssl:/var/ssl
    depends_on:
      rpc:
        condition: service_started
      app:
        condition: service_started

  nginx:
    image: ymuski/nginx-quic:latest
    command: "/bin/sh -c 'while :; do sleep 6h & wait $$!; nginx -s reload; done & nginx -g \"daemon off;\"'"
    volumes:
      - ./ssl:/var/ssl
      - ./nginx/prod/nginx.conf:/etc/nginx/nginx.conf
      - ./public:/var/web
    ports:
      - 80:80
      - 443:443
    depends_on:
      app:
        condition: service_started

volumes:
  gem_cache:
  db_data:
  redis_data:
  ssl_root:

生产.rb

Rails.application.configure do
  config.cache_classes = true

  config.eager_load = true
  
  config.consider_all_requests_local = true
  
  config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?
  
  config.active_storage.service = :local
  
  config.action_cable.url = 'wss://api.test.to:8443/live'
  
  config.action_cable.disable_request_forgery_protection = true

  config.log_level = :debug
  
  config.logger = Logger.new(STDOUT)

  config.log_tags = [ :request_id ]

  config.cache_store = :redis_cache_store, driver: :hiredis, url: "redis://redis:6379/2"
  
  config.action_mailer.perform_caching = false

  config.i18n.fallbacks = true

  config.active_support.deprecation = :notify

  config.log_formatter = ::Logger::Formatter.new

  if ENV["RAILS_LOG_TO_STDOUT"].present?
    logger           = ActiveSupport::Logger.new(STDOUT)
    logger.formatter = config.log_formatter
    config.logger    = ActiveSupport::TaggedLogging.new(logger)
  end

  config.active_record.dump_schema_after_migration = false
  config.active_record.verbose_query_logs = true
end

这是建立 websocket 连接时记录的内容:

https://user-images.githubusercontent.com/15372551/124969065-8e8e4680-e026-11eb-912d-2aa8e98f5607.png

【问题讨论】:

【参考方案1】:

我能够通过升级到最新版本的 anycable-rails > 1.0 来解决这个问题

【讨论】:

以上是关于AnyCable request.params 在生产中为空的主要内容,如果未能解决你的问题,请参考以下文章

细说 Request[]与Request.Params[]

Request.Params 和 Request.Form 啥时候不同?

Request.Params

Request,Request.QueryString,Request.Params,Request.Form,Request.ServerVariables之间的区别

asp.net 后台 Request.Params时遇到前台发送的中文字符 , 得到乱码怎么解决?

login auth failed errormsg :http request params error啥意思