paperclip-storage-aliyun 0.1.0 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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