yartem
@yartem
frontend newbie

Updated!!! Rails 5.2 API-mode. Как избавиться от ActiveSupport::MessageVerifier::InvalidSignature при попытке передать form-data?

Имею Nuxt/Rails приложение. Надо с фронта отправить картинку на бэкенд. Делаю следующим образом:

save() {
  const params = new FormData()
  const testimonial = this.testimonial
  delete testimonial.image_name

  for (const field in testimonial) {
    params.append(field, testimonial[field])
  }

  const request = this.id
    ? this.$axios.put(`${this.loadUrl}/${this.id}`, params, {
        headers: {
          'Content-Type': 'multipart/form-data'
        }
      })
    : this.$axios.post(this.loadUrl, params, {
        headers: {
          'Content-Type': 'multipart/form-data'
        }
      })
  
  request
    .then(({ status }) => {
      if (Number(status) === 200) this.success = 'Отзыв успешно обновлён'
      if (Number(status) === 201) this.success = 'Отзыв успешно добавлен'
      setTimeout(() => {
        this.$router.push('/testimonials/')
      }, 1000)
    })
    .catch(error => {
      this.error = error + ''
    })
}


Вот заголовки, которые формируются при отработке метода:
General:
  Request URL: http://localhost:3000/admin/v1/testimonials
  Request Method: POST
  Status Code: 500 Internal Server Error
  Remote Address: [::1]:3000
  Referrer Policy: no-referrer-when-downgrade
Responce Headers:
  Access-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETE, OPTIONS, HEAD
  Access-Control-Allow-Origin: *
  Access-Control-Expose-Headers: 
  Access-Control-Max-Age: 1728000
  Content-Length: 14476
  Content-Type: application/json; charset=UTF-8
  Vary: Origin
  X-Request-Id: f8d6116f-31c7-4644-97c0-e92502fe0f06
  X-Runtime: 0.057866
Request Headers:
  Accept: application/json, text/plain, */*
  Accept-Encoding: gzip, deflate, br
  Accept-Language: ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7
  Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxIiwic2NwIjoidXNlciIsImF1ZCI6bnVsbCwiaWF0IjoxNTYyMjQ4MjIyLCJleHAiOjE1NjIyNTE4MjIsImp0aSI6ImM0Y2Y4NjViLTUxOTEtNDk0Ni04YTg3LTQ3MmZjYzczYzA5NCJ9.7wNl04ar8u6TmK8OEirKJecQCjJxF_hgVtfnknQKyWk
  Cache-Control: no-cache
  Connection: keep-alive
  Content-Length: 2186254
  Content-Type: multipart/form-data; boundary=----WebKitFormBoundary3BAEPvtfoHgJ0XC4
  Host: localhost:3000
  Origin: http://localhost:4000
  Pragma: no-cache
  Referer: http://localhost:4000/testimonials/edit/
  User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36 OPR/60.0.3255.170
Form Data:
  name: Иван
  patronymic: 
  surname: 
  userpic: 
  company: 
  object_photo_1: (binary)
  object_photo_2: null
  object_photo_3: null
  video: 
  text: Отзыв


Сервер плюётся пятисотой ошибкой:
Started POST "/admin/v1/testimonials" for ::1 at 2019-07-04 17:39:58 +0300
Processing by Admin::TestimonialsController#create as JSON
  Parameters: {"name"=>"Иван", "patronymic"=>"", "surname"=>"", "userpic"=>"", "company"=>"", "object_photo_1"=>#<ActionDispatch::Http::UploadedFile:0x00007fa8ec2b6b18 @tempfile=#<Tempfile:/tmp/RackMultipart20190704-8689-cyzaac.jpg>, @original_filename="filename.jpg", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"object_photo_1\"; filename=\"filename.jpg\"\r\nContent-Type: image/jpeg\r\n">, "object_photo_2"=>"null", "object_photo_3"=>"null", "video"=>"", "text"=>"Отзыв"}
  User Load (0.4ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  ↳ /home/yart/.rvm/gems/ruby-2.5.1/gems/activerecord-5.2.3/lib/active_record/log_subscriber.rb:98
  JwtBlacklist Exists (0.6ms)  SELECT  1 AS one FROM "jwt_blacklists" WHERE "jwt_blacklists"."jti" = $1 LIMIT $2  [["jti", "c4cf865b-5191-4946-8a87-472fcc73c094"], ["LIMIT", 1]]
  ↳ /home/yart/.rvm/gems/ruby-2.5.1/gems/activerecord-5.2.3/lib/active_record/log_subscriber.rb:98
Unpermitted parameter: :format
Completed 500 Internal Server Error in 4ms (ActiveRecord: 1.1ms)



ActiveSupport::MessageVerifier::InvalidSignature (ActiveSupport::MessageVerifier::InvalidSignature):

app/controllers/admin/testimonials_controller.rb:19:in `create'


Вот модель:
class Testimonial < ApplicationRecord
  has_one_attached :userpic
  has_one_attached :object_photo_1
  has_one_attached :object_photo_2
  has_one_attached :object_photo_3

  validates :name, presence: true
  validates :video, presence: true, if: Proc.new { |t| t.text.blank? }
  validates :text, presence: true, if: Proc.new { |t| t.video.blank? }
end


Вот кусок контроллера, который имеет отношение к обсуждаемому вопросу:
class Admin::TestimonialsController < ApplicationController
  before_action :authenticate_user!

# . . .

  def create
    testimonial = Testimonial.new(t_params)

    if testimonial.save
      testimonial = find_testimonial(testimonial.id)
      render json: testimonial, status: :created
    else
      render json: {errors: testimonial.errors}, status: :bad_request
    end
  end

# . . .

private

# . . .

  def t_params
    params.each { |param| param = nil if param == "null" }

    safe_params = params.permit :name, :patronymic, :surname, :userpic, :company,
                                :object_photo_1, :object_photo_2, :object_photo_3,
                                :video, :text, :id
    params = ActionController::Parameters.new(testimonial: safe_params)

    params.require(:testimonial).permit :name, :patronymic, :surname, :userpic, :company,
                                        :object_photo_1, :object_photo_2, :object_photo_3,
                                        :video, :text, :id
  end

# . . .

end


Вот то, что отдаёт в результате своей работы t_params:
<ActionController::Parameters {"testimonial" => <ActionController::Parameters {
  "name" => "Иван",
  "patronymic" => "",
  "surname" => "",
  "userpic" => "",
  "company" => "",
  "object_photo_1" => #<ActionDispatch::Http::UploadedFile:0x000055cd83f1b390 @tempfile=#<Tempfile:/tmp/RackMultipart20190704-346-19rgkj4.jpg>, @original_filename="filename.jpg", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"object_photo_1\"; filename=\"Scan_20160802_153425.jpg\"\r\nContent-Type: image/jpeg\r\n">,
  "object_photo_2" => "null",
  "object_photo_3" => "null",
  "video" => "",
  "text" => "Отзыв"
} permitted: true>} permitted: false>


Ну и вопрос: в какой именно момент мне надо отрывать руки? Я уже с ног сбился в поисках ошибки и в попытках отгрузить на сервак этот долбаный файл!

PS На описание модуля MessageVerifier я ходил. Он занимается, как раз, проверкой присылаемых сообщений на авторизацию. И таки фронтенд мой её отдаёт, что видно из заголовков. Более того, при попытке отправить неавторизованный запрос, я исправно получаю 401 ошибку.

Чем занимается модуль InvalidSignature — тайна, покрытая мраком. По-крайней мере вот тут я вижу только белую страницу с красным заголовком:
5d1e189d565a4977044758.png

Здесь аналогичная картина...

UPDATE

Выяснились новые детали и подробности, описание которых заняло слишком много места и я вылез за местные лимиты. Поэтому перенёс это описание в отдельный вопрос. Ну и вот то, что касается непосредственно данного вопроса: чем занимается InvalidSignature я таки выяснил. Отправляется таким как я, если метод verify из MessageVerifier считает, что обрабатываемое сообщение не было подписано правильно либо не было закодировано в Base64. И не надо меня спрашивать, что всё это значит. Я выяснил также и причины появления этого InvalidSignature: он появляется тогда, когда я отправляю null вместо файла. Остальное вот тут: Rails 5.2 API-mode. Как пофиксить ActiveRecord::St...
  • Вопрос задан
  • 483 просмотра
Пригласить эксперта
Ответы на вопрос 1
@notwrite
У вас недоверенный параметр format откудато лезет. Посмотрите что отправляет браузер с картинкой
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы