router.rb 2.54 KB
Newer Older
Marin Jankovski's avatar
Marin Jankovski committed
1 2 3
module Gitlab
  module Lfs
    class Router
4 5
      attr_reader :project, :user, :ci, :request

Kamil Trzcinski's avatar
WIP  
Kamil Trzcinski committed
6
      def initialize(project, user, ci, request)
Marin Jankovski's avatar
Marin Jankovski committed
7 8
        @project = project
        @user = user
Kamil Trzcinski's avatar
WIP  
Kamil Trzcinski committed
9
        @ci = ci
Marin Jankovski's avatar
Marin Jankovski committed
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
        @env = request.env
        @request = request
      end

      def try_call
        return unless @request && @request.path.present?

        case @request.request_method
        when 'GET'
          get_response
        when 'POST'
          post_response
        when 'PUT'
          put_response
        else
          nil
        end
      end

      private

      def get_response
        path_match = @request.path.match(/\/(info\/lfs|gitlab-lfs)\/objects\/([0-9a-f]{64})$/)
        return nil unless path_match

        oid = path_match[2]
        return nil unless oid

        case path_match[1]
        when "info/lfs"
40
          lfs.render_unsupported_deprecated_api
Marin Jankovski's avatar
Marin Jankovski committed
41 42 43 44 45 46 47 48 49 50 51 52 53
        when "gitlab-lfs"
          lfs.render_download_object_response(oid)
        else
          nil
        end
      end

      def post_response
        post_path = @request.path.match(/\/info\/lfs\/objects(\/batch)?$/)
        return nil unless post_path

        # Check for Batch API
        if post_path[0].ends_with?("/info/lfs/objects/batch")
54
          lfs.render_batch_operation_response
55 56
        elsif post_path[0].ends_with?("/info/lfs/objects")
          lfs.render_unsupported_deprecated_api
Marin Jankovski's avatar
Marin Jankovski committed
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
        else
          nil
        end
      end

      def put_response
        object_match = @request.path.match(/\/gitlab-lfs\/objects\/([0-9a-f]{64})\/([0-9]+)(|\/authorize){1}$/)
        return nil if object_match.nil?

        oid = object_match[1]
        size = object_match[2].try(:to_i)
        return nil if oid.nil? || size.nil?

        # GitLab-workhorse requests
        # 1. Try to authorize the request
        # 2. send a request with a header containing the name of the temporary file
        if object_match[3] && object_match[3] == '/authorize'
          lfs.render_storage_upload_authorize_response(oid, size)
        else
          tmp_file_name = sanitize_tmp_filename(@request.env['HTTP_X_GITLAB_LFS_TMP'])
          lfs.render_storage_upload_store_response(oid, size, tmp_file_name)
        end
      end

      def lfs
        return unless @project

Kamil Trzcinski's avatar
WIP  
Kamil Trzcinski committed
84
        Gitlab::Lfs::Response.new(@project, @user, @ci, @request)
Marin Jankovski's avatar
Marin Jankovski committed
85 86 87 88 89 90 91 92 93 94 95 96 97 98
      end

      def sanitize_tmp_filename(name)
        if name.present?
          name.gsub!(/^.*(\\|\/)/, '')
          name = name.match(/[0-9a-f]{73}/)
          name[0] if name
        else
          nil
        end
      end
    end
  end
end