Yandex Disk WebDav PROPPATCH


As a part of my idea of Yandex Disk as ActiveStorage service implementation, I decided to implement PROPPATCH method into yandex disk gem.

As described in webdav documentation - all what we need - make a special PROPPATCH request with PATH of our folder or file.

I’ve added simple feature here: publication branch with this functionality support.

Or you can use main repo, feature already merged to master branch.

Let’s take a look into WebDav request implementation as described above:

PROPPATCH /public_folder/readme.txt HTTP/1.1
User-Agent: my_application/0.0.1
Host: webdav.yandex.ru
Authorization: OAuth 0c4182a7c2cf4521964a72ff57a34a07
Content-Length: 158
<propertyupdate xmlns="DAV:">
 <set>
   <prop>
     <public_url xmlns="urn:yandex:disk:meta">true</public_url>
   </prop>
 </set>
</propertyupdate>

Let’s take a look into my Yandex::Disk::Client::Request::Publication implementation:

require 'nokogiri'

class Yandex::Disk::Client::Request::Publication
  BODY = 
  '<propertyupdate xmlns="DAV:">
    <set>
      <prop>
        <public_url xmlns="urn:yandex:disk:meta">true</public_url>
      </prop>
    </set>
  </propertyupdate>'
  HEADERS = {
  }

  def initialize http, path
    @http = http
    @path = path
  end

  def perform
    response = @http.run_request :proppatch, @path, BODY, HEADERS
    parse_result = parse(response.body)
    { :public_url => parse_result.public_url }
  end

  private

  class AttributesParser < Nokogiri::XML::SAX::Document
    attr_reader :public_url

    def start_element name, attributes = []
      case name
        when 'public_url'
          @public_url = true
      end
    end

    def characters string
      @public_url = string if @public_url
    end
  end

  def parse body
    attributes_parser = AttributesParser.new

    parser = Nokogiri::XML::SAX::Parser.new(attributes_parser)
    parser.parse(body)

    attributes_parser
  end
end

One important thing here - we specify new :proppatch method for the Faraday request, and need to extend it like this:

Faraday::Connection::METHODS << :proppatch

Let’s create sample example, and make our file public:

irb(main):001:0> client = Yandex::Disk::Client.new(:access_token => 'XXXXXXXXXX')
=> #<Yandex::Disk::Client:0x00007ffd5c0bd5b8 @timeout=300, @http=#<Faraday::Connection:0x00007ffd5c0bd4a0 @parallel_manager=nil, @headers={"User-Agent"=>"Faraday v0.9.2"}, @params={}, @options=#<Faraday::RequestOptions (empty)>, @ssl=#<Faraday::SSLOptions (empty)>, @default_parallel_manager=nil, @builder=#<Faraday::RackBuilder:0x00007ffd5c0bd180 @handlers=[Faraday::Request::Authorization, Faraday::Adapter::Excon]>, @url_prefix=#<URI::HTTPS https://webdav.yandex.ru/>, @proxy=nil>>


irb(main):002:0> client.make_public('/FOLDER/file.png')
=> {:public_url=>"https://yadi.sk/i/XXXXXX"}

Great, now file marked as public, and we can access it via provided URL.