paperclip-storage-aliyun 0.1.0 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d8531e6601564efe368735f05147b68f4401c495
4
- data.tar.gz: e2317360addbbce35acd8bf2947a532cdf11f8c2
3
+ metadata.gz: 54dcd2f097b32d6998ae9ea559f6b2e0ea5cb722
4
+ data.tar.gz: 608cf463dc92fd1eb2f2ce11948d34a0943ace91
5
5
  SHA512:
6
- metadata.gz: 1f7ce3fda9227a3937a1d04e7acce987c60028187496261c493176f87e016fcaba3083fc7a9977b28af313ac9a92b0ffef6af5ba092a052f40baaac65f7b52e6
7
- data.tar.gz: abef51e1bbeb91ac622f74ed61f17bde84026d91eba1ebf423b11833ff770b2a4912d385ec09de6728d16f4d5d0bfafb44517696f0b43e268d4cc6cd3b10753d
6
+ metadata.gz: 5ba28411b91204475eb8918bc39b4bd1ce95be879adcb7111b346da88b953f02662c787852d045eae0b1288c74e9c4cd8a7cad291e9eded84908eeea43ce2d5a
7
+ data.tar.gz: 72fc6dc869c817eb34159e7a0af899277df51d14cdba62920e4f3b80158ae95ddc230b9fee20ffa9a385445ee62d233eba57cec4ff802373926f4f2328c1fc5f
@@ -18,21 +18,29 @@ module Aliyun
18
18
  # The alias host
19
19
  attr_reader :aliyun_alias_host
20
20
 
21
+ attr_reader :aliyun_protocol
22
+
23
+ attr_reader :aliyun_protocol_relative_url
24
+
21
25
  # Initialize the OSS connection
22
26
  #
23
27
  # @param [Hash] An options to specify connection details
24
28
  # @option access_id [String] used to set "Authorization" request header
25
29
  # @option access_key [String] the access key
26
30
  # @option bucket [String] bucket used to access
27
- # @option data_center [String] available data center name, e.g. 'hangzhou'
31
+ # @option data_center [String] available data center name, e.g. 'cn-hangzhou'
28
32
  # @option internal [true, false] if the service should be accessed through internal network
29
33
  # @option host_alias [String] the alias of the host, such as the CDN domain name
34
+ # @option protocol [String] 'http' or 'https', default to 'http'
35
+ # @option protocol_relative_url [true, false] if to use protocol relative url, https://en.wikipedia.org/wiki/Wikipedia:Protocol-relative_URL
30
36
  # @note both access_id and acces_key are related to authorization algorithm:
31
37
  # https://docs.aliyun.com/#/pub/oss/api-reference/access-control&signature-header
32
38
  def initialize(options = {})
33
39
  @aliyun_access_id = options[:access_id]
34
40
  @aliyun_access_key = options[:access_key]
35
41
  @aliyun_bucket = options[:bucket]
42
+ @aliyun_protocol_relative_url = !!options[:protocol_relative_url]
43
+ @aliyun_protocol = options[:protocol] || 'http'
36
44
 
37
45
  @aliyun_upload_host = "#{@aliyun_bucket}.#{get_endpoint(options)}"
38
46
  @aliyun_internal_host = "#{@aliyun_bucket}.#{get_endpoint(options.merge(internal: true))}"
@@ -40,7 +48,7 @@ module Aliyun
40
48
  @aliyun_alias_host = options[:host_alias] || @aliyun_upload_host
41
49
  end
42
50
 
43
- # Return the meta informations for the a file specified by the path
51
+ # Return the meta informations for a file specified by the path
44
52
  # https://docs.aliyun.com/#/pub/oss/api-reference/object&HeadObject
45
53
  #
46
54
  # @param path [String] the path of file storaged in Aliyun OSS
@@ -60,8 +68,16 @@ module Aliyun
60
68
  # :x_oss_request_id=>"55BD83A5D4C05BDFF4A329E0"}}
61
69
  #
62
70
  def head(path)
71
+ path = format_path(path)
72
+ bucket_path = get_bucket_path(path)
73
+ date = gmtdate
74
+ headers = {
75
+ 'Host' => @aliyun_upload_host,
76
+ 'Date' => date,
77
+ 'Authorization' => sign('HEAD', bucket_path, '', '', date)
78
+ }
63
79
  url = path_to_url(path)
64
- RestClient.head(url).headers
80
+ RestClient.head(url, headers).headers
65
81
  rescue RestClient::ResourceNotFound
66
82
  {}
67
83
  end
@@ -93,7 +109,7 @@ module Aliyun
93
109
  'Host' => @aliyun_upload_host,
94
110
  'Expect' => '100-Continue'
95
111
  }
96
- response = RestClient.put(URI.encode(url), file, headers)
112
+ response = RestClient.put(url, file, headers)
97
113
  response.code == 200 ? path_to_url(path) : nil
98
114
  end
99
115
 
@@ -113,7 +129,7 @@ module Aliyun
113
129
  'Authorization' => sign('DELETE', bucket_path, '', '', date)
114
130
  }
115
131
  url = path_to_url(path)
116
- response = RestClient.delete(URI.encode(url), headers)
132
+ response = RestClient.delete(url, headers)
117
133
  response.code == 204 ? url : nil
118
134
  end
119
135
 
@@ -132,7 +148,7 @@ module Aliyun
132
148
  'Authorization' => sign('GET', bucket_path, '', '', date)
133
149
  }
134
150
  url = path_to_url(path)
135
- response = RestClient.get(URI.encode(url), headers)
151
+ response = RestClient.get(url, headers)
136
152
  response.body
137
153
  end
138
154
 
@@ -176,7 +192,7 @@ module Aliyun
176
192
  # @param path [String] the path to retrieve the file on remote storage
177
193
  # @return [String] the expected full path, e.g. "http://martin-test.oss-cn-hangzhou.aliyuncs.com/oss-api.pdf"
178
194
  def path_to_url(path)
179
- path =~ %r{^https?://} ? path : "http://#{aliyun_upload_host}/#{path}"
195
+ URI.encode(path =~ %r{^https?://} ? path : "http://#{aliyun_upload_host}/#{path}")
180
196
  end
181
197
 
182
198
  private
@@ -2,33 +2,41 @@ require 'aliyun/errors'
2
2
 
3
3
  module Aliyun
4
4
  module DataCenter
5
- # https://docs.aliyun.com/#/pub/oss/product-documentation/domain-region
5
+ # https://help.aliyun.com/document_detail/31837.html
6
6
  AVAILABLE_DATA_CENTERS = %w(
7
7
  oss-cn-hangzhou
8
+ oss-cn-shanghai
8
9
  oss-cn-qingdao
9
10
  oss-cn-beijing
10
- oss-cn-hongkong
11
+ oss-cn-zhangjiakou
12
+ oss-cn-huhehaote
11
13
  oss-cn-shenzhen
12
- oss-cn-shanghai
14
+ oss-cn-heyuan
15
+ oss-cn-chengdu
16
+ oss-cn-hongkong
13
17
  oss-us-west-1
18
+ oss-us-east-1
14
19
  oss-ap-southeast-1
20
+ oss-ap-southeast-2
21
+ oss-ap-southeast-3
22
+ oss-ap-southeast-5
23
+ oss-ap-northeast-1
24
+ oss-ap-south-1
25
+ oss-eu-central-1
26
+ oss-eu-west-1
27
+ oss-me-east-1
15
28
  )
16
29
 
17
30
  def get_endpoint(options)
18
- data_center = find_center(options[:data_center])
31
+ data_center = options[:data_center]
19
32
 
20
- unless data_center && AVAILABLE_DATA_CENTERS.include?(data_center)
33
+ data_center = 'oss-' + data_center unless data_center.match(/^oss/)
34
+
35
+ unless AVAILABLE_DATA_CENTERS.include?(data_center)
21
36
  fail InvalildDataCenter, "Unsupported Data Center #{options[:data_center]} Detected"
22
37
  end
23
38
 
24
39
  "#{data_center}#{options[:internal] ? '-internal' : ''}.aliyuncs.com"
25
40
  end
26
-
27
- def find_center(data_center)
28
- return if /^(oss|cn|us|ap|oss-cn)$/.match(data_center)
29
-
30
- regexp = Regexp.new(data_center)
31
- AVAILABLE_DATA_CENTERS.find { |center| regexp.match(center) }
32
- end
33
41
  end
34
42
  end
@@ -16,20 +16,28 @@ module Paperclip
16
16
  end
17
17
  end
18
18
 
19
+ def build_aliyun_object_url(host, style)
20
+ if oss_connection.aliyun_protocol_relative_url
21
+ "//#{host}/#{path(style).sub(%r{\A/}, '')}"
22
+ else
23
+ "#{oss_connection.aliyun_protocol}://#{host}/#{path(style).sub(%r{\A/}, '')}"
24
+ end
25
+ end
26
+
19
27
  def aliyun_upload_url(style = default_style)
20
- "http://#{oss_connection.aliyun_upload_host}/#{path(style).sub(%r{\A/}, '')}"
28
+ build_aliyun_object_url(oss_connection.aliyun_upload_host, style)
21
29
  end
22
30
 
23
31
  def aliyun_internal_url(style = default_style)
24
- "http://#{oss_connection.aliyun_internal_host}/#{path(style).sub(%r{\A/}, '')}"
32
+ build_aliyun_object_url(oss_connection.aliyun_internal_host, style)
25
33
  end
26
34
 
27
35
  def aliyun_external_url(style = default_style)
28
- "http://#{oss_connection.aliyun_external_host}/#{path(style).sub(%r{\A/}, '')}"
36
+ build_aliyun_object_url(oss_connection.aliyun_external_host, style)
29
37
  end
30
38
 
31
39
  def aliyun_alias_url(style = default_style)
32
- "http://#{oss_connection.aliyun_alias_host}/#{path(style).sub(%r{\A/}, '')}"
40
+ build_aliyun_object_url(oss_connection.aliyun_alias_host, style)
33
41
  end
34
42
 
35
43
  def exists?(style = default_style)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: paperclip-storage-aliyun
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Martin Hong
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-11-01 00:00:00.000000000 Z
12
+ date: 2020-08-08 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: paperclip
@@ -45,26 +45,11 @@ executables: []
45
45
  extensions: []
46
46
  extra_rdoc_files: []
47
47
  files:
48
- - ".editorconfig"
49
- - ".gitignore"
50
- - ".rspec"
51
- - ".rubocop.yml"
52
- - Gemfile
53
- - README.md
54
48
  - lib/aliyun/connection.rb
55
49
  - lib/aliyun/data_center.rb
56
50
  - lib/aliyun/errors.rb
57
51
  - lib/paperclip-storage-aliyun.rb
58
52
  - lib/paperclip/storage/aliyun.rb
59
- - paperclip-storage-aliyun.gemspec
60
- - spec/aliyun_spec.rb
61
- - spec/attachments/girl.jpg
62
- - spec/attachments/masu.pdf
63
- - spec/fixtures/schema.rb
64
- - spec/lib/paperclip/storage/aliyun_spec.rb
65
- - spec/spec_helper.rb
66
- - spec/support/post.rb
67
- - spec/support/rails.rb
68
53
  homepage: https://github.com/Martin91/paperclip-storage-aliyun
69
54
  licenses:
70
55
  - MIT
@@ -85,9 +70,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
85
70
  version: '0'
86
71
  requirements: []
87
72
  rubyforge_project:
88
- rubygems_version: 2.4.8
73
+ rubygems_version: 2.5.2.3
89
74
  signing_key:
90
75
  specification_version: 4
91
76
  summary: Extend a Aliyun OSS storage for paperclip
92
77
  test_files: []
93
- has_rdoc:
@@ -1,13 +0,0 @@
1
- # EditorConfig is awesome: http://EditorConfig.org
2
-
3
- # top-most EditorConfig file
4
- root = true
5
-
6
- # Unix-style newlines with a newline ending every file
7
- [*]
8
- charset = utf-8
9
- indent_style = space
10
- indent_size = 2
11
- end_of_line = lf
12
- insert_final_newline = true
13
- trim_trailing_whitespace = true
data/.gitignore DELETED
@@ -1,3 +0,0 @@
1
- Gemfile.lock
2
- .yardoc/
3
- doc/
data/.rspec DELETED
@@ -1 +0,0 @@
1
- --color
@@ -1,11 +0,0 @@
1
- Style/Documentation:
2
- Enabled: false
3
-
4
- Metrics/AbcSize:
5
- Max: 18
6
-
7
- Metrics/LineLength:
8
- Max: 120
9
-
10
- Metrics/MethodLength:
11
- Enabled: false
data/Gemfile DELETED
@@ -1,16 +0,0 @@
1
- source 'https://ruby.taobao.org'
2
-
3
- gemspec
4
-
5
- group :test do
6
- gem 'activerecord', '~> 4.0.0'
7
- # A database backend that translates database interactions into no-ops. Using
8
- # NullDB enables you to test your model business logic - including after_save
9
- # hooks - without ever touching a real database.
10
- gem 'activerecord-nulldb-adapter'
11
- gem 'rspec', '~> 3.3.0'
12
- # Use rubocop to lint our Ruby codes
13
- gem 'rubocop', '~> 0.34.2'
14
- gem 'pry'
15
- gem 'pry-nav'
16
- end
data/README.md DELETED
@@ -1,47 +0,0 @@
1
- Aliyun Open Storage Service for Paperclip
2
- ===
3
- This gem implement the support for [Aliyun open storage service(OSS)](http://oss.aliyun.com) to [Paperclip](https://github.com/thoughtbot/paperclip).
4
-
5
- #### Installation
6
- ```shell
7
- gem install paperclip-storage-aliyun
8
- ```
9
- Or, if you are using a bundler, you can append the following line into your **Gemfile**:
10
- ```ruby
11
- gem 'paperclip-storage-aliyun'
12
- ```
13
-
14
- #### Configuration
15
- In order to make all the things work, you should do some important configurations through a initializer:
16
-
17
- If you are developing a Rails application, you can append a new initializer like:
18
- ```ruby
19
- # [rails_root]/config/initializers/paperclip-aliyun-configuration.rb
20
- Paperclip::Attachment.default_options[:aliyun] = {
21
- access_id: '3VL9XMho8iCushj8',
22
- access_key: 'VAUI2q7Tc6yTh1jr3kBsEUzZ84gEa2',
23
- bucket: 'xx-test',
24
- data_center: 'hangzhou',
25
- internal: false
26
- }
27
- ```
28
- Then, in the model which defines the attachment, specify your storage and other options, for example:
29
- ```ruby
30
- # [rails_root]/app/models/image.rb
31
- class Image < ActiveRecord::Base
32
- has_attached_file :attachment, {
33
- storage: :aliyun,
34
- styles: { thumbnail: "60x60#"},
35
- path: 'public/system/:class/:attachment/:id_partition/:style/:filename',
36
- url: ':aliyun_upload_url'
37
- }
38
- end
39
- ```
40
-
41
- Similar to Paperclip::Storage::S3, there are four options for the url by now:
42
- - `:aliyun_upload_url` : the url based on the options you give
43
- - `:aliyun_internal_url` : the internal url, no matter what `options[:aliyun][:internal]` is
44
- - `:aliyun_external_url` : the external url, no matter what `options[:aliyun][:internal]` is
45
- - `:aliyun_alias_url` : the alias url based on the `host_alias` you give, typically used together with CDN
46
-
47
- Please note the values above are all strings, not symbols. You could still make your own url if only you know what you are doing.
@@ -1,16 +0,0 @@
1
- Gem::Specification.new do |s|
2
- s.name = 'paperclip-storage-aliyun'
3
- s.platform = Gem::Platform::RUBY
4
- s.require_path = 'lib'
5
- s.summary = 'Extend a Aliyun OSS storage for paperclip'
6
- s.description = 'Extend a Aliyun OSS storage for paperclip'
7
- s.version = '0.1.0'
8
- s.files = `git ls-files`.split("\n")
9
- s.authors = ['Martin Hong', 'Aidi Stan']
10
- s.email = 'hongzeqin@gmail.com'
11
- s.homepage = 'https://github.com/Martin91/paperclip-storage-aliyun'
12
- s.license = 'MIT'
13
-
14
- s.add_runtime_dependency 'paperclip', '>= 3.5.2'
15
- s.add_runtime_dependency 'rest-client', '>= 1.6.7'
16
- end
@@ -1,59 +0,0 @@
1
- require 'spec_helper'
2
-
3
- require 'net/http'
4
-
5
- describe Aliyun::Connection do
6
- before :all do
7
- @connection = ::Aliyun::Connection.new OSS_CONNECTION_OPTIONS
8
- @path = 'a/a.jpg'
9
- end
10
-
11
- describe '#initialize' do
12
- it 'raise error when use invalid data center' do
13
- expect do
14
- ::Aliyun::Connection.new data_center: 'guangzhou'
15
- end.to raise_error(Aliyun::InvalildDataCenter)
16
- end
17
- end
18
-
19
- describe '#put' do
20
- it 'upload the attachment' do
21
- url = @connection.put @path, load_attachment('girl.jpg')
22
- response_code = Net::HTTP.get_response(URI.parse(url)).code
23
- expect(response_code).to eq('200')
24
- end
25
-
26
- it 'support setting content type' do
27
- content_type = 'application/pdf'
28
- path = 'pdfs/masu.pdf'
29
- @connection.put path, load_attachment('masu.pdf'), content_type: content_type
30
- file_meta = @connection.head(path)
31
- expect(file_meta[:content_type]).to eq(content_type)
32
-
33
- @connection.delete path
34
- end
35
- end
36
-
37
- describe '#delete' do
38
- it 'delete the attachment' do
39
- url = @connection.delete @path
40
- response_code = Net::HTTP.get_response(URI.parse(url)).code
41
- expect(response_code).to eq('404')
42
- end
43
- end
44
-
45
- describe '#exists?' do
46
- before :all do
47
- @connection.put @path, load_attachment('girl.jpg')
48
- end
49
-
50
- it 'return true if the file has been uploaded' do
51
- expect(@connection.exists?(@path)).to be_truthy
52
- end
53
-
54
- it "return false if the specified file didn't exist" do
55
- @connection.delete @path
56
- expect(@connection.exists?(@path)).to be_falsey
57
- end
58
- end
59
- end
Binary file
Binary file
@@ -1,8 +0,0 @@
1
- require 'active_record'
2
- require 'paperclip'
3
-
4
- ActiveRecord::Schema.define do
5
- create_table :posts, force: true do |t|
6
- t.attachment :attachment
7
- end
8
- end
@@ -1,73 +0,0 @@
1
- require 'spec_helper'
2
- require 'open-uri'
3
- require 'net/http'
4
- require 'support/post'
5
-
6
- describe Paperclip::Storage::Aliyun do
7
- before :all do
8
- @file = load_attachment('girl.jpg')
9
- @post = Post.create attachment: @file
10
- end
11
-
12
- after :all do
13
- @post.destroy! if @post && @post.respond_to?(:id)
14
- @file.close
15
- end
16
-
17
- describe '#flush_writes' do
18
- it 'uploads the attachment to Aliyun' do
19
- response = open(@post.attachment.url)
20
- expect(response).to be_truthy
21
- end
22
-
23
- it 'get uploaded file from Aliyun' do
24
- attachment = open @post.attachment.url
25
- expect(attachment.size).to eq(@file.size)
26
- end
27
-
28
- it 'set content type according to the original file' do
29
- attachment = load_attachment('masu.pdf')
30
- post = Post.create attachment: attachment
31
- headers = RestClient.head(post.attachment.url).headers
32
- expect(headers[:content_type]).to eq('application/pdf')
33
-
34
- post.destroy
35
- end
36
- end
37
-
38
- describe '#exists?' do
39
- it 'returns true if the file exists on Aliyun' do
40
- expect(@post.attachment).to exist
41
- end
42
-
43
- it "returns false if the file doesn't exist on Aliyun" do
44
- post = Post.new attachment: @file
45
- expect(post.attachment).not_to exist
46
- end
47
-
48
- it 'not raise exception when attachment not saved' do
49
- post = Post.create
50
- expect { post.attachment.exists? }.not_to raise_error
51
- end
52
- end
53
-
54
- describe '#copy_to_local_file' do
55
- it 'copies file from Aliyun to a local file' do
56
- destination = File.join(Bundler.root, 'tmp/photo.jpg')
57
- @post.attachment.copy_to_local_file(:original, destination)
58
- expect(File.exist?(destination)).to be_truthy
59
-
60
- File.delete destination
61
- end
62
- end
63
-
64
- describe '#flush_deletes' do
65
- it 'deletes the attachment from Aliyun' do
66
- attachment_url = @post.attachment.url
67
- @post.destroy
68
-
69
- response_code = Net::HTTP.get_response(URI.parse(attachment_url)).code
70
- expect(response_code).to eq('404')
71
- end
72
- end
73
- end
@@ -1,27 +0,0 @@
1
- require 'pry'
2
- require 'pry-nav'
3
- require 'paperclip-storage-aliyun'
4
-
5
- Paperclip.logger.level = ::Logger::UNKNOWN
6
- Dir[Bundler.root.join('spec/support/**/*.rb')].each(&method(:require))
7
-
8
- # Aliyun defaults
9
- OSS_CONNECTION_OPTIONS = {
10
- access_id: '3VL9XMho8iCuslj8',
11
- access_key: 'VAUI2q7Tc6yTf1jr3kBsEUzZ84gEa2',
12
- bucket: 'martin-test',
13
- data_center: 'hangzhou',
14
- internal: false
15
- # host_alias: nil
16
- }
17
-
18
- # Paperclip defaults
19
- Paperclip::Attachment.default_options[:storage] = :aliyun
20
- Paperclip::Attachment.default_options[:aliyun] = OSS_CONNECTION_OPTIONS
21
- Paperclip::Attachment.default_options[:path] = 'public/system/:class/:attachment/:id_partition/:style/:filename'
22
- Paperclip::Attachment.default_options[:url] = ':aliyun_upload_url'
23
-
24
- # Utility methods
25
- def load_attachment(file_name)
26
- File.open(Bundler.root.join("spec/attachments/#{file_name}"), 'rb')
27
- end
@@ -1,24 +0,0 @@
1
- require 'active_record'
2
- require 'nulldb'
3
- require 'paperclip'
4
-
5
- class Post < ActiveRecord::Base
6
- include Paperclip::Glue
7
-
8
- has_attached_file :attachment
9
- do_not_validate_attachment_file_type :attachment
10
- end
11
-
12
- RSpec.configure do |config|
13
- config.before(:all) do
14
- FileUtils.mkdir_p File.join(Bundler.root, 'tmp')
15
- ActiveRecord::Base.establish_connection(
16
- adapter: 'nulldb',
17
- schema: File.join(Bundler.root, 'spec/fixtures/schema.rb')
18
- )
19
- end
20
-
21
- config.after(:all) do
22
- ActiveRecord::Base.remove_connection
23
- end
24
- end
@@ -1,10 +0,0 @@
1
- require 'paperclip'
2
-
3
- module Paperclip
4
- module Interpolations
5
- module Rails
6
- def self.root
7
- end
8
- end
9
- end
10
- end