imedo (owner)

Revisions

gist: 217666 Download_button fork
public
Description:
File uploads with webrat in Ruby on Rails 2.0.2
Public Clone URL: git://gist.github.com/217666.git
Embed All Files: show embed
session.rb #
1
2
3
4
5
6
7
8
9
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
module ActionController
  module Integration
    class Session
 
      class MultiPartNeededException < Exception
      end
 
      private
        class StubCGI < CGI
          attr_accessor :stdinput, :stdoutput, :env_table
 
          def initialize(env, stdinput = nil)
            self.env_table = env
            self.stdoutput = StringIO.new
 
            super
 
            stdinput.set_encoding(Encoding::BINARY) if stdinput.respond_to?(:set_encoding)
            stdinput.force_encoding(Encoding::BINARY) if stdinput.respond_to?(:force_encoding)
            @stdinput = stdinput.is_a?(IO) ? stdinput : StringIO.new(stdinput || '')
          end
        end
 
        # Performs the actual request.
        def process(method, path, parameters = nil, headers = nil)
          data = requestify(parameters)
          path = interpret_uri(path) if path =~ %r{://}
          path = "/#{path}" unless path[0] == ?/
          @path = path
          env = {}
 
          if method == :get
            env["QUERY_STRING"] = data
            data = nil
          end
 
          env.update(
            "REQUEST_METHOD" => method.to_s.upcase,
            "REQUEST_URI" => path,
            "HTTP_HOST" => host,
            "REMOTE_ADDR" => remote_addr,
            "SERVER_PORT" => (https? ? "443" : "80"),
            "CONTENT_TYPE" => "application/x-www-form-urlencoded",
            "CONTENT_LENGTH" => data ? data.length.to_s : nil,
            "HTTP_COOKIE" => encode_cookies,
            "HTTPS" => https? ? "on" : "off",
            "HTTP_ACCEPT" => accept
          )
 
          (headers || {}).each do |key, value|
            key = key.to_s.upcase.gsub(/-/, "_")
            key = "HTTP_#{key}" unless env.has_key?(key) || key =~ /^HTTP_/
            env[key] = value
          end
 
          unless ActionController::Base.respond_to?(:clear_last_instantiation!)
            ActionController::Base.module_eval { include ControllerCapture }
          end
 
          ActionController::Base.clear_last_instantiation!
 
          cgi = StubCGI.new(env, data)
          ActionController::Dispatcher.dispatch(cgi, ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS, cgi.stdoutput)
          @result = cgi.stdoutput.string
          @request_count += 1
 
          @controller = ActionController::Base.last_instantiation
          @request = @controller.request
          @response = @controller.response
 
          # Decorate the response with the standard behavior of the TestResponse
          # so that things like assert_response can be used in integration
          # tests.
          @response.extend(TestResponseBehavior)
 
          @html_document = nil
 
          parse_result
          return status
        rescue MultiPartNeededException
          boundary = "----------XnJLe9ZIbbGUYtzPQJ16u1"
          status = process(method, path, multipart_body(parameters, boundary), (headers || {}).merge({"CONTENT_TYPE" => "multipart/form-data; boundary=#{boundary}"}))
          return status
        end
 
        # Convert the given parameters to a request string. The parameters may
        # be a string, +nil+, or a Hash.
        def requestify(parameters, prefix=nil)
          if TestUploadedFile === parameters
            raise MultiPartNeededException
          elsif Hash === parameters
            return nil if parameters.empty?
            parameters.map { |k,v| requestify(v, name_with_prefix(prefix, k)) }.join("&")
          elsif Array === parameters
            parameters.map { |v| requestify(v, name_with_prefix(prefix, "")) }.join("&")
          elsif prefix.nil?
            parameters
          else
            "#{CGI.escape(prefix)}=#{CGI.escape(parameters.to_s)}"
          end
        end
 
        def multipart_requestify(params, first=true)
          returning Hash.new do |p|
            params.each do |key, value|
              k = first ? CGI.escape(key.to_s) : "[#{CGI.escape(key.to_s)}]"
              if Hash === value
                multipart_requestify(value, false).each do |subkey, subvalue|
                  p[k + subkey] = subvalue
                end
              else
                p[k] = value
              end
            end
          end
        end
 
        def multipart_body(params, boundary)
          multipart_requestify(params).map do |key, value|
            if value.respond_to?(:original_filename)
              File.open(value.path) do |f|
                f.set_encoding(Encoding::BINARY) if f.respond_to?(:set_encoding)
 
                <<-EOF
--#{boundary}\r
Content-Disposition: form-data; name="#{key}"; filename="#{CGI.escape(value.original_filename)}"\r
Content-Type: #{value.content_type}\r
Content-Length: #{File.stat(value.path).size}\r
\r
#{f.read}\r
EOF
              end
            else
<<-EOF
--#{boundary}\r
Content-Disposition: form-data; name="#{key}"\r
\r
#{value}\r
EOF
            end
          end.join("")+"--#{boundary}--\r"
        end
    end
  end
end