qiniu-rs 1.0.0
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.
- data/.gitignore +19 -0
- data/.rspec +1 -0
- data/Gemfile +6 -0
- data/LICENSE +22 -0
- data/README.md +38 -0
- data/Rakefile +2 -0
- data/lib/qiniu/rs/auth.rb +74 -0
- data/lib/qiniu/rs/config.rb +54 -0
- data/lib/qiniu/rs/exceptions.rb +88 -0
- data/lib/qiniu/rs/image.rb +20 -0
- data/lib/qiniu/rs/io.rb +41 -0
- data/lib/qiniu/rs/log.rb +17 -0
- data/lib/qiniu/rs/rs.rb +63 -0
- data/lib/qiniu/rs/utils.rb +124 -0
- data/lib/qiniu/rs/version.rb +7 -0
- data/lib/qiniu/rs.rb +114 -0
- data/lib/qiniu-rs.rb +2 -0
- data/qiniu-rs.gemspec +24 -0
- data/spec/qiniu/rs/auth_spec.rb +58 -0
- data/spec/qiniu/rs/image_spec.rb +41 -0
- data/spec/qiniu/rs/io_spec.rb +42 -0
- data/spec/qiniu/rs/rs_spec.rb +116 -0
- data/spec/qiniu/rs/utils_spec.rb +49 -0
- data/spec/qiniu/rs/version_spec.rb +10 -0
- data/spec/qiniu/rs_spec.rb +147 -0
- data/spec/spec_helper.rb +12 -0
- metadata +143 -0
    
        data/.gitignore
    ADDED
    
    
    
        data/.rspec
    ADDED
    
    | @@ -0,0 +1 @@ | |
| 1 | 
            +
            --colour -f nested
         | 
    
        data/Gemfile
    ADDED
    
    
    
        data/LICENSE
    ADDED
    
    | @@ -0,0 +1,22 @@ | |
| 1 | 
            +
            Copyright (c) 2012 why404
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            MIT License
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            Permission is hereby granted, free of charge, to any person obtaining
         | 
| 6 | 
            +
            a copy of this software and associated documentation files (the
         | 
| 7 | 
            +
            "Software"), to deal in the Software without restriction, including
         | 
| 8 | 
            +
            without limitation the rights to use, copy, modify, merge, publish,
         | 
| 9 | 
            +
            distribute, sublicense, and/or sell copies of the Software, and to
         | 
| 10 | 
            +
            permit persons to whom the Software is furnished to do so, subject to
         | 
| 11 | 
            +
            the following conditions:
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            The above copyright notice and this permission notice shall be
         | 
| 14 | 
            +
            included in all copies or substantial portions of the Software.
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
         | 
| 17 | 
            +
            EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
         | 
| 18 | 
            +
            MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
         | 
| 19 | 
            +
            NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
         | 
| 20 | 
            +
            LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
         | 
| 21 | 
            +
            OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
         | 
| 22 | 
            +
            WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
         | 
    
        data/README.md
    ADDED
    
    | @@ -0,0 +1,38 @@ | |
| 1 | 
            +
            # 关于
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            此 Ruby SDK 适用于 Ruby 1.8.x, 1.9.x 版本,基于 [七牛云存储官方API](http://docs.qiniutek.com/v1/api/) 构建。使用此 SDK 构建您的网络应用程序,能让您以非常便捷地方式将数据安全地存储到七牛云存储上。无论您的网络应用是一个网站程序,还是包括从云端(服务端程序)到终端(手持设备应用)的架构的服务或应用,通过七牛云存储及其 SDK,都能让您应用程序的终端用户高速上传和下载,同时也让您的服务端更加轻盈。
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            ## 安装
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            在您 Ruby 应用程序的 `Gemfile` 文件中,添加如下一行代码:
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                gem 'qiniu-rs'
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            然后,在应用程序所在的目录下,可以运行 `bundle` 安装依赖包:
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                $ bundle
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            或者,可以使用 Ruby 的包管理器 `gem` 进行安装:
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                $ gem install qiniu-rs
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            ## 使用
         | 
| 20 | 
            +
             | 
| 21 | 
            +
            参考文档:[七牛云存储 Ruby SDK 使用指南](http://docs.qiniutek.com/v1/sdk/ruby/)
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            ## 贡献代码
         | 
| 24 | 
            +
             | 
| 25 | 
            +
            1. Fork
         | 
| 26 | 
            +
            2. 创建您的特性分支 (`git checkout -b my-new-feature`)
         | 
| 27 | 
            +
            3. 提交您的改动 (`git commit -am 'Added some feature'`)
         | 
| 28 | 
            +
            4. 将您的修改记录提交到远程 `git` 仓库 (`git push origin my-new-feature`)
         | 
| 29 | 
            +
            5. 然后到 github 网站的该 `git` 远程仓库的 `my-new-feature` 分支下发起 Pull Request
         | 
| 30 | 
            +
             | 
| 31 | 
            +
            ## 许可证
         | 
| 32 | 
            +
             | 
| 33 | 
            +
            Copyright (c) 2012 why404
         | 
| 34 | 
            +
             | 
| 35 | 
            +
            基于 MIT 协议发布:
         | 
| 36 | 
            +
             | 
| 37 | 
            +
            * [www.opensource.org/licenses/MIT](http://www.opensource.org/licenses/MIT)
         | 
| 38 | 
            +
             | 
    
        data/Rakefile
    ADDED
    
    
| @@ -0,0 +1,74 @@ | |
| 1 | 
            +
            # -*- encoding: utf-8 -*-
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'qiniu/rs/exceptions'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            module Qiniu
         | 
| 6 | 
            +
              module RS
         | 
| 7 | 
            +
                module Auth
         | 
| 8 | 
            +
                  class << self
         | 
| 9 | 
            +
                    include Utils
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                    def exchange_by_password!(username, password)
         | 
| 12 | 
            +
                      @username = username
         | 
| 13 | 
            +
                      @password = password
         | 
| 14 | 
            +
                      post_data = {
         | 
| 15 | 
            +
                        :client_id  => Config.settings[:client_id],
         | 
| 16 | 
            +
                        :grant_type => "password",
         | 
| 17 | 
            +
                        :username   => username,
         | 
| 18 | 
            +
                        :password   => password
         | 
| 19 | 
            +
                      }
         | 
| 20 | 
            +
                      code, data = http_request Config.settings[:auth_url], post_data
         | 
| 21 | 
            +
                      reset_token(data["access_token"], data["refresh_token"]) if code == 200
         | 
| 22 | 
            +
                      [code, data]
         | 
| 23 | 
            +
                    end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                    def exchange_by_refresh_token!(refresh_token)
         | 
| 26 | 
            +
                      post_data = {
         | 
| 27 | 
            +
                        :client_id     => Config.settings[:client_id],
         | 
| 28 | 
            +
                        :grant_type    => "refresh_token",
         | 
| 29 | 
            +
                        :refresh_token => refresh_token
         | 
| 30 | 
            +
                      }
         | 
| 31 | 
            +
                      code, data = http_request Config.settings[:auth_url], post_data
         | 
| 32 | 
            +
                      reset_token(data["access_token"], data["refresh_token"]) if code == 200
         | 
| 33 | 
            +
                      [code, data]
         | 
| 34 | 
            +
                    end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                    def reset_token(access_token, refresh_token)
         | 
| 37 | 
            +
                      @access_token  = access_token
         | 
| 38 | 
            +
                      @refresh_token = refresh_token
         | 
| 39 | 
            +
                    end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                    def call(url, data, retry_times = 0)
         | 
| 42 | 
            +
                      raise MissingAccessToken if @access_token.nil?
         | 
| 43 | 
            +
                      code, data = http_request url, data, {:access_token => @access_token}
         | 
| 44 | 
            +
                      if code == 401
         | 
| 45 | 
            +
                        raise MissingRefreshToken if @refresh_token.nil?
         | 
| 46 | 
            +
                        code, data = exchange_by_refresh_token!(@refresh_token)
         | 
| 47 | 
            +
                        if code == 401
         | 
| 48 | 
            +
                          raise MissingUsernameOrPassword if (@username.nil? || @password.nil?)
         | 
| 49 | 
            +
                          code, data = exchange_by_password!(@username, @password)
         | 
| 50 | 
            +
                        end
         | 
| 51 | 
            +
                        if code == 200
         | 
| 52 | 
            +
                          retry_times += 1
         | 
| 53 | 
            +
                          if Config.settings[:auto_reconnect] && retry_times < Config.settings[:max_retry_times]
         | 
| 54 | 
            +
                            return call(url, data, retry_times)
         | 
| 55 | 
            +
                          end
         | 
| 56 | 
            +
                        end
         | 
| 57 | 
            +
                      end
         | 
| 58 | 
            +
                      [code, data]
         | 
| 59 | 
            +
                    end
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                    def request(url, data = nil)
         | 
| 62 | 
            +
                      begin
         | 
| 63 | 
            +
                        code, data = Auth.call(url, data)
         | 
| 64 | 
            +
                      rescue [MissingAccessToken, MissingRefreshToken, MissingUsernameOrPassword] => e
         | 
| 65 | 
            +
                        Log.logger.error e
         | 
| 66 | 
            +
                        code, data = 401, {}
         | 
| 67 | 
            +
                      end
         | 
| 68 | 
            +
                      [code, data]
         | 
| 69 | 
            +
                    end
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                  end
         | 
| 72 | 
            +
                end
         | 
| 73 | 
            +
              end
         | 
| 74 | 
            +
            end
         | 
| @@ -0,0 +1,54 @@ | |
| 1 | 
            +
            # -*- encoding: utf-8 -*-
         | 
| 2 | 
            +
            #
         | 
| 3 | 
            +
            # USAGE WAY 1:
         | 
| 4 | 
            +
            # Qbox::Config.initialize_connect :client_id => "<ClientID>",
         | 
| 5 | 
            +
            #                                 :client_secret => "<ClientSecret>"
         | 
| 6 | 
            +
            #
         | 
| 7 | 
            +
            # USAGE WAY 2:
         | 
| 8 | 
            +
            # Qbox::Config.load "path/to/your_project/config/qiniu.yml"
         | 
| 9 | 
            +
            #
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            require "qiniu/rs/version"
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            module Qiniu
         | 
| 14 | 
            +
              module RS
         | 
| 15 | 
            +
                module Config
         | 
| 16 | 
            +
                  class << self
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                    DEFAULT_OPTIONS = {
         | 
| 19 | 
            +
                      :user_agent      => 'Qiniu-RS-Ruby-SDK-' + VERSION + '()',
         | 
| 20 | 
            +
                      :method          => :post,
         | 
| 21 | 
            +
                      :content_type    => 'application/x-www-form-urlencoded',
         | 
| 22 | 
            +
                      :auth_url        => "https://acc.qbox.me/oauth2/token",
         | 
| 23 | 
            +
                      :rs_host         => "http://rs.qbox.me:10100",
         | 
| 24 | 
            +
                      :io_host         => "http://io.qbox.me",
         | 
| 25 | 
            +
                      :client_id       => "<YOUR_APP_CLIENT_ID>",
         | 
| 26 | 
            +
                      :client_secret   => "<YOUR_APP_CLIENT_SECRET>",
         | 
| 27 | 
            +
                      :auto_reconnect  => true,
         | 
| 28 | 
            +
                      :max_retry_times => 5
         | 
| 29 | 
            +
                    }
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                    REQUIRED_OPTION_KEYS = [:client_id, :client_secret, :auth_url, :rs_host, :io_host]
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                    attr_reader :settings, :default_params
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                    def load config_file
         | 
| 36 | 
            +
                      if File.exist?(config_file)
         | 
| 37 | 
            +
                        config_options = YAML.load_file(config_file)
         | 
| 38 | 
            +
                        initialize_connect(config_options)
         | 
| 39 | 
            +
                      else
         | 
| 40 | 
            +
                        raise MissingConfError, config_file
         | 
| 41 | 
            +
                      end
         | 
| 42 | 
            +
                    end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                    def initialize_connect options = {}
         | 
| 45 | 
            +
                      @settings = DEFAULT_OPTIONS.merge(options)
         | 
| 46 | 
            +
                      REQUIRED_OPTION_KEYS.each do |opt|
         | 
| 47 | 
            +
                        raise MissingArgsError, [opt] unless @settings.has_key?(opt)
         | 
| 48 | 
            +
                      end
         | 
| 49 | 
            +
                    end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                  end
         | 
| 52 | 
            +
                end
         | 
| 53 | 
            +
              end
         | 
| 54 | 
            +
            end
         | 
| @@ -0,0 +1,88 @@ | |
| 1 | 
            +
            # -*- encoding: utf-8 -*-
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Qiniu
         | 
| 4 | 
            +
              module RS
         | 
| 5 | 
            +
             | 
| 6 | 
            +
                class Exception < RuntimeError
         | 
| 7 | 
            +
                  def to_s
         | 
| 8 | 
            +
                    inspect
         | 
| 9 | 
            +
                  end
         | 
| 10 | 
            +
                end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                class ResponseError < Exception
         | 
| 13 | 
            +
                  attr_reader :response
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                  def initialize(message, response = nil)
         | 
| 16 | 
            +
                    @response = response
         | 
| 17 | 
            +
                    super(message)
         | 
| 18 | 
            +
                  end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                  def http_code
         | 
| 21 | 
            +
                    @response.code.to_i if @response
         | 
| 22 | 
            +
                  end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                  def http_body
         | 
| 25 | 
            +
                    @response.body if @response
         | 
| 26 | 
            +
                  end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                  def inspect
         | 
| 29 | 
            +
                    "#{message}: #{http_body}"
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                class RequestFailed < ResponseError
         | 
| 34 | 
            +
                  def message
         | 
| 35 | 
            +
                    "HTTP status code #{http_code}"
         | 
| 36 | 
            +
                  end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                  def to_s
         | 
| 39 | 
            +
                    message
         | 
| 40 | 
            +
                  end
         | 
| 41 | 
            +
                end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                class MissingArgsError < Exception
         | 
| 44 | 
            +
                  def initialize(missing_keys)
         | 
| 45 | 
            +
                    key_list = missing_keys.map {|key| key.to_s}.join(' and the ')
         | 
| 46 | 
            +
                    super("You did not provide both required args. Please provide the #{key_list}.")
         | 
| 47 | 
            +
                  end
         | 
| 48 | 
            +
                end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                class MissingAccessToken < MissingArgsError
         | 
| 51 | 
            +
                  def initialize
         | 
| 52 | 
            +
                    super([:access_token])
         | 
| 53 | 
            +
                  end
         | 
| 54 | 
            +
                end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                class MissingRefreshToken < MissingArgsError
         | 
| 57 | 
            +
                  def initialize
         | 
| 58 | 
            +
                    super([:refresh_token])
         | 
| 59 | 
            +
                  end
         | 
| 60 | 
            +
                end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                class MissingUsernameOrPassword < MissingArgsError
         | 
| 63 | 
            +
                  def initialize
         | 
| 64 | 
            +
                    super([:username, :password])
         | 
| 65 | 
            +
                  end
         | 
| 66 | 
            +
                end
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                class InvalidArgsError < Exception
         | 
| 69 | 
            +
                  def initialize(invalid_keys)
         | 
| 70 | 
            +
                    key_list = invalid_keys.map {|key| key.to_s}.join(' and the ')
         | 
| 71 | 
            +
                    super("#{key_list} should not be empty.")
         | 
| 72 | 
            +
                  end
         | 
| 73 | 
            +
                end
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                class MissingConfError < Exception
         | 
| 76 | 
            +
                  def initialize(missing_conf_file)
         | 
| 77 | 
            +
                    super("Error, missing #{missing_conf_file}. You must have #{missing_conf_file} to configure your client id and secret.")
         | 
| 78 | 
            +
                  end
         | 
| 79 | 
            +
                end
         | 
| 80 | 
            +
             | 
| 81 | 
            +
                class NoSuchFileError < Exception
         | 
| 82 | 
            +
                  def initialize(missing_file)
         | 
| 83 | 
            +
                    super("Error, no such file #{missing_file}.")
         | 
| 84 | 
            +
                  end
         | 
| 85 | 
            +
                end
         | 
| 86 | 
            +
             | 
| 87 | 
            +
              end
         | 
| 88 | 
            +
            end
         | 
| @@ -0,0 +1,20 @@ | |
| 1 | 
            +
            # -*- encoding: utf-8 -*-
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Qiniu
         | 
| 4 | 
            +
              module RS
         | 
| 5 | 
            +
                module Image
         | 
| 6 | 
            +
                  class << self
         | 
| 7 | 
            +
                    include Utils
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                    def info(url)
         | 
| 10 | 
            +
                      Utils.http_request url + '/imageInfo', nil, {:method => :get}
         | 
| 11 | 
            +
                    end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                    def preivew_url(url, spec)
         | 
| 14 | 
            +
                      url + '/imagePreview/' + spec.to_s
         | 
| 15 | 
            +
                    end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                  end
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
              end
         | 
| 20 | 
            +
            end
         | 
    
        data/lib/qiniu/rs/io.rb
    ADDED
    
    | @@ -0,0 +1,41 @@ | |
| 1 | 
            +
            # -*- encoding: utf-8 -*-
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'mime/types'
         | 
| 4 | 
            +
            require 'digest/sha1'
         | 
| 5 | 
            +
            require 'qiniu/rs/exceptions'
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            module Qiniu
         | 
| 8 | 
            +
              module RS
         | 
| 9 | 
            +
                module IO
         | 
| 10 | 
            +
                  class << self
         | 
| 11 | 
            +
                    include Utils
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                    def put_auth(expires_in = nil, callback_url = nil)
         | 
| 14 | 
            +
                      url = Config.settings[:io_host] + "/put-auth/"
         | 
| 15 | 
            +
                      url += "#{expires_in}" if !expires_in.nil? && expires_in > 0
         | 
| 16 | 
            +
                      if !callback_url.nil? && !callback_url.empty?
         | 
| 17 | 
            +
                        encoded_callback_url = Utils.urlsafe_base64_encode(callback_url)
         | 
| 18 | 
            +
                        url += "/callback/#{encoded_callback_url}"
         | 
| 19 | 
            +
                      end
         | 
| 20 | 
            +
                      Auth.request(url)
         | 
| 21 | 
            +
                    end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                    def put_file(url, local_file, bucket = '', key = '', mime_type = '', custom_meta = '', callback_params = '')
         | 
| 24 | 
            +
                      raise NoSuchFileError unless File.exist?(local_file)
         | 
| 25 | 
            +
                      key = Digest::SHA1.hexdigest(local_file + Time.now.to_s) if key.empty?
         | 
| 26 | 
            +
                      entry_uri = bucket + ':' + key
         | 
| 27 | 
            +
                      if mime_type.empty?
         | 
| 28 | 
            +
                        mime = MIME::Types.type_for local_file
         | 
| 29 | 
            +
                        mime_type = mime.empty? ? 'application/octet-stream' : mime[0].content_type
         | 
| 30 | 
            +
                      end
         | 
| 31 | 
            +
                      action_params = '/rs-put/' + Utils.urlsafe_base64_encode(entry_uri) + '/mimeType/' + Utils.urlsafe_base64_encode(mime_type)
         | 
| 32 | 
            +
                      action_params += '/meta/' + Utils.urlsafe_base64_encode(custom_meta) unless custom_meta.empty?
         | 
| 33 | 
            +
                      callback_params = {:bucket => bucket, :key => key, :mime_type => mime_type} if callback_params.empty?
         | 
| 34 | 
            +
                      callback_query_string = Utils.generate_query_string(callback_params)
         | 
| 35 | 
            +
                      Utils.upload_multipart_data(url, local_file, action_params, callback_query_string)
         | 
| 36 | 
            +
                    end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                  end
         | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
              end
         | 
| 41 | 
            +
            end
         | 
    
        data/lib/qiniu/rs/log.rb
    ADDED
    
    
    
        data/lib/qiniu/rs/rs.rb
    ADDED
    
    | @@ -0,0 +1,63 @@ | |
| 1 | 
            +
            # -*- encoding: utf-8 -*-
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Qiniu
         | 
| 4 | 
            +
              module RS
         | 
| 5 | 
            +
                module RS
         | 
| 6 | 
            +
                  class << self
         | 
| 7 | 
            +
                    include Utils
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                    def stat(bucket, key)
         | 
| 10 | 
            +
                      Auth.request Config.settings[:rs_host] + '/stat/' + encode_entry_uri(bucket, key)
         | 
| 11 | 
            +
                    end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                    def get(bucket, key, save_as = nil, expires_in = nil, version = nil)
         | 
| 14 | 
            +
                      url = Config.settings[:rs_host] + '/get/' + encode_entry_uri(bucket, key)
         | 
| 15 | 
            +
                      url += '/base/' + version unless version.nil?
         | 
| 16 | 
            +
                      url += '/attName/' + Utils.urlsafe_base64_encode(save_as) unless save_as.nil?
         | 
| 17 | 
            +
                      url += '/expires/' + expires_in.to_s if !expires_in.nil? && expires_in > 0
         | 
| 18 | 
            +
                      Auth.request url
         | 
| 19 | 
            +
                    end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                    def delete(bucket, key)
         | 
| 22 | 
            +
                      Auth.request Config.settings[:rs_host] + '/delete/' + encode_entry_uri(bucket, key)
         | 
| 23 | 
            +
                    end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                    def publish(domain, bucket)
         | 
| 26 | 
            +
                      encoded_domain = Utils.urlsafe_base64_encode(domain)
         | 
| 27 | 
            +
                      Auth.request Config.settings[:rs_host] + "/publish/#{encoded_domain}/from/#{bucket}"
         | 
| 28 | 
            +
                    end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                    def unpublish(domain)
         | 
| 31 | 
            +
                      encoded_domain = Utils.urlsafe_base64_encode(domain)
         | 
| 32 | 
            +
                      Auth.request Config.settings[:rs_host] + "/unpublish/#{encoded_domain}"
         | 
| 33 | 
            +
                    end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                    def drop(bucket)
         | 
| 36 | 
            +
                      Auth.request Config.settings[:rs_host] + "/drop/#{bucket}"
         | 
| 37 | 
            +
                    end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                    def batch(command, bucket, keys)
         | 
| 40 | 
            +
                      execs = []
         | 
| 41 | 
            +
                      keys.each do |key|
         | 
| 42 | 
            +
                        encoded_uri = encode_entry_uri(bucket, key)
         | 
| 43 | 
            +
                        execs << "op=/#{command}/#{encoded_uri}"
         | 
| 44 | 
            +
                      end
         | 
| 45 | 
            +
                      Auth.request Config.settings[:rs_host] + "/batch?" + execs.join("&")
         | 
| 46 | 
            +
                    end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                    def batch_get(bucket, keys)
         | 
| 49 | 
            +
                      batch("get", bucket, keys)
         | 
| 50 | 
            +
                    end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                    def batch_stat(bucket, keys)
         | 
| 53 | 
            +
                      batch("stat", bucket, keys)
         | 
| 54 | 
            +
                    end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                    def batch_delete(bucket, keys)
         | 
| 57 | 
            +
                      batch("delete", bucket, keys)
         | 
| 58 | 
            +
                    end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                  end
         | 
| 61 | 
            +
                end
         | 
| 62 | 
            +
              end
         | 
| 63 | 
            +
            end
         | 
| @@ -0,0 +1,124 @@ | |
| 1 | 
            +
            # -*- encoding: utf-8 -*-
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'uri'
         | 
| 4 | 
            +
            require 'json'
         | 
| 5 | 
            +
            require 'base64'
         | 
| 6 | 
            +
            require 'rest_client'
         | 
| 7 | 
            +
            require 'qiniu/rs/exceptions'
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            module Qiniu
         | 
| 10 | 
            +
              module RS
         | 
| 11 | 
            +
                module Utils extend self
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                  def urlsafe_base64_encode content
         | 
| 14 | 
            +
                    Base64.encode64(content).strip.gsub('+', '-').gsub('/','_').gsub(/\r?\n/, '')
         | 
| 15 | 
            +
                  end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                  def urlsafe_base64_decode encoded_content
         | 
| 18 | 
            +
                    Base64.decode64 encoded_content.gsub('_','/').gsub('-', '+')
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                  def encode_entry_uri(bucket, key)
         | 
| 22 | 
            +
                    entry_uri = bucket + ':' + key
         | 
| 23 | 
            +
                    urlsafe_base64_encode(entry_uri)
         | 
| 24 | 
            +
                  end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                  def safe_json_parse(data)
         | 
| 27 | 
            +
                    JSON.parse(data)
         | 
| 28 | 
            +
                  rescue JSON::ParserError
         | 
| 29 | 
            +
                    {}
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                  def send_request_with url, data = nil, options = {}
         | 
| 33 | 
            +
                    options[:method] = Config.settings[:method] unless options[:method]
         | 
| 34 | 
            +
                    options[:content_type] = Config.settings[:content_type] unless options[:content_type]
         | 
| 35 | 
            +
                    header_options = {
         | 
| 36 | 
            +
                      :accept => :json,
         | 
| 37 | 
            +
                      :user_agent => Config.settings[:user_agent]
         | 
| 38 | 
            +
                    }
         | 
| 39 | 
            +
                    header_options.merge!('Authorization' => "Bearer #{options[:access_token]}") if options[:access_token]
         | 
| 40 | 
            +
                    case options[:method]
         | 
| 41 | 
            +
                    when :get
         | 
| 42 | 
            +
                      response = RestClient.get url, header_options
         | 
| 43 | 
            +
                    when :post
         | 
| 44 | 
            +
                      header_options.merge!(:content_type => options[:content_type])
         | 
| 45 | 
            +
                      response = RestClient.post url, data, header_options
         | 
| 46 | 
            +
                    end
         | 
| 47 | 
            +
                    code = response.respond_to?(:code) ? response.code.to_i : 0
         | 
| 48 | 
            +
                    if code != 200
         | 
| 49 | 
            +
                      raise RequestFailed.new(response)
         | 
| 50 | 
            +
                    else
         | 
| 51 | 
            +
                      data = {}
         | 
| 52 | 
            +
                      body = response.respond_to?(:body) ? response.body : {}
         | 
| 53 | 
            +
                      data = safe_json_parse(body) unless body.empty?
         | 
| 54 | 
            +
                    end
         | 
| 55 | 
            +
                    [code, data]
         | 
| 56 | 
            +
                  end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                  def http_request url, data = nil, options = {}
         | 
| 59 | 
            +
                    retry_times = 0
         | 
| 60 | 
            +
                    begin
         | 
| 61 | 
            +
                      retry_times += 1
         | 
| 62 | 
            +
                      send_request_with url, data, options
         | 
| 63 | 
            +
                    rescue Errno::ECONNRESET => err
         | 
| 64 | 
            +
                      if Config.settings[:auto_reconnect] && retry_times < Config.settings[:max_retry_times]
         | 
| 65 | 
            +
                        retry
         | 
| 66 | 
            +
                      else
         | 
| 67 | 
            +
                        Log.logger.error err
         | 
| 68 | 
            +
                      end
         | 
| 69 | 
            +
                    rescue => e
         | 
| 70 | 
            +
                      Log.logger.warn "#{e.message} => Utils.http_request('#{url}')"
         | 
| 71 | 
            +
                      code = 0
         | 
| 72 | 
            +
                      data = {}
         | 
| 73 | 
            +
                      body = {}
         | 
| 74 | 
            +
                      if e.respond_to? :response
         | 
| 75 | 
            +
                        res = e.response
         | 
| 76 | 
            +
                        code = res.code.to_i if res.respond_to? :code
         | 
| 77 | 
            +
                        body = res.respond_to?(:body) ? res.body : ""
         | 
| 78 | 
            +
                        data = safe_json_parse(body) unless body.empty?
         | 
| 79 | 
            +
                      end
         | 
| 80 | 
            +
                      [code, data]
         | 
| 81 | 
            +
                    end
         | 
| 82 | 
            +
                  end
         | 
| 83 | 
            +
             | 
| 84 | 
            +
                  def upload_multipart_data(url, filepath, action_string, callback_query_string = '')
         | 
| 85 | 
            +
                    code, data = 0, {}
         | 
| 86 | 
            +
                    begin
         | 
| 87 | 
            +
                      header_options = {
         | 
| 88 | 
            +
                        :accept => :json,
         | 
| 89 | 
            +
                        :user_agent => Config.settings[:user_agent]
         | 
| 90 | 
            +
                      }
         | 
| 91 | 
            +
                      post_data = {
         | 
| 92 | 
            +
                        :file => File.new(filepath, 'rb'),
         | 
| 93 | 
            +
                        :params => callback_query_string,
         | 
| 94 | 
            +
                        :action => action_string,
         | 
| 95 | 
            +
                        :multipart => true
         | 
| 96 | 
            +
                      }
         | 
| 97 | 
            +
                      response = RestClient.post url, post_data, header_options
         | 
| 98 | 
            +
                      body = response.respond_to?(:body) ? response.body : ""
         | 
| 99 | 
            +
                      data = safe_json_parse(body) unless body.empty?
         | 
| 100 | 
            +
                      code = response.code.to_i if response.respond_to?(:code)
         | 
| 101 | 
            +
                    rescue Errno::ECONNRESET => err
         | 
| 102 | 
            +
                      Log.logger.error err
         | 
| 103 | 
            +
                    rescue => e
         | 
| 104 | 
            +
                      Log.logger.warn "#{e.message} => Utils.http_request('#{url}')"
         | 
| 105 | 
            +
                      res = e.response
         | 
| 106 | 
            +
                      if e.respond_to? :response
         | 
| 107 | 
            +
                        res = e.response
         | 
| 108 | 
            +
                        code = res.code.to_i if res.respond_to? :code
         | 
| 109 | 
            +
                        body = res.respond_to?(:body) ? res.body : ""
         | 
| 110 | 
            +
                        data = safe_json_parse(body) unless body.empty?
         | 
| 111 | 
            +
                      end
         | 
| 112 | 
            +
                    end
         | 
| 113 | 
            +
                    [code, data]
         | 
| 114 | 
            +
                  end
         | 
| 115 | 
            +
             | 
| 116 | 
            +
                  def generate_query_string(params)
         | 
| 117 | 
            +
                    return params if params.is_a?(String)
         | 
| 118 | 
            +
                    total_param = params.map { |key, value| key.to_s+"="+value.to_s }
         | 
| 119 | 
            +
                    URI.escape(total_param.join("&"))
         | 
| 120 | 
            +
                  end
         | 
| 121 | 
            +
             | 
| 122 | 
            +
                end
         | 
| 123 | 
            +
              end
         | 
| 124 | 
            +
            end
         |