问题
I have a problem with Rails API app active storage. I have React from where i want to upload file.
import React from "react";
import {DirectUpload} from "activestorage";
class SignIn extends React.Component {
constructor(props) {
super(props);
this.state = {
file: null
};
this.handleFileChange = this.handleFileChange.bind(this);
this.handleFileSubmit = this.handleFileSubmit.bind(this);
}
handleFileChange(e){
this.setState({file: e.target.files[0]})
}
handleFileSubmit(){
const upload = new DirectUpload(this.state.file, "/rails/active_storage/direct_uploads");
upload.create((error, blob) => {
if(error){
console.log(error)
} else {
console.log(blob)
}
})
}
render() {
return (
<React.Fragment>
<Form>
<Form.Item>
<Input type="file" onChange={this.handleFileChange}/>
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit">
Register
</Button>
</Form.Item>
</Form>
</React.Fragment>
);
}
}
But on submit i got error Completed 422 Unprocessable Entity in 1ms (ActiveRecord: 0.0ms)
Started POST "/rails/active_storage/direct_uploads" for 127.0.0.1 at 2019-05-09 22:59:54 +0200
Processing by ActiveStorage::DirectUploadsController#create as JSON
Parameters: {"blob"=>{"filename"=>"file.jpg", "content_type"=>"image/jpeg", "byte_size"=>27095, "checksum"=>"8u95dXg39vap1Cq/2fgfbg=="}, "direct_upload"=>{"blob"=>{"filename"=>"file.jpg", "content_type"=>"image/jpeg", "byte_size"=>27095, "checksum"=>"8u95dXg39vap1Cq/2fgfbg=="}}}
Can't verify CSRF token authenticity.
Completed 422 Unprocessable Entity in 1ms (ActiveRecord: 0.0ms)
ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken):
actionpack (5.2.3) lib/action_controller/metal/request_forgery_protection.rb:211:in `handle_unverified_request'
actionpack (5.2.3) lib/action_controller/metal/request_forgery_protection.rb:243:in `handle_unverified_request'
devise (4.6.2) lib/devise/controllers/helpers.rb:255:in `handle_unverified_request'
actionpack (5.2.3) lib/action_controller/metal/request_forgery_protection.rb:238:in `verify_authenticity_token'
activesupport (5.2.3) lib/active_support/callbacks.rb:426:in `block in make_lambda'
activesupport (5.2.3) lib/active_support/callbacks.rb:198:in `block (2 levels) in halting'
actionpack (5.2.3) lib/abstract_controller/callbacks.rb:34:in `block (2 levels) in <module:Callbacks>'
activesupport (5.2.3) lib/active_support/callbacks.rb:199:in `block in halting'
activesupport (5.2.3) lib/active_support/callbacks.rb:513:in `block in invoke_before'
I set in application_controller.rb protect_from_forgery with: :null_session
but i still got error.
回答1:
I had the same problem. Two ways to solve this :
1. Monkey patch (Not recommended)
in config/initializers/direct_uploads.rb
:
require 'active_storage/direct_uploads_controller'
class ActiveStorage::DirectUploadsController
protect_from_forgery with: :null_session
end
2. Custom controller (recommended)
Let's say you have and API endpoint to /api/v1
:
config/routes.rb
namespace :api do
scope module: 'v1', path: 'v1' do
resources :direct_uploads, only: [:create]
end
end
app/controllers/api/v1/direct_uploads_controller.rb
class Api::V1::DirectUploadsController < ActiveStorage::DirectUploadsController
# Should only allow null_session in API context, so request is JSON format
protect_from_forgery with: :null_session, if: Proc.new { |c| c.request.format == 'application/json' }
# Also, since authenticity verification by cookie is disabled, you should implement you own logic :
before_action :verify_user
private
def verify_user
raise unless User.find(doorkeeper_token[:resource_owner_id])
end
end
And change the DirectUpload instanciation with the right endpoint :
const upload = new DirectUpload(this.state.file, "/api/v1/direct_uploads");
Hope this helps. Cheers !
来源:https://stackoverflow.com/questions/56067616/rails-api-activestorage-directupload-produce-422-error-invalidauthenticitytoken