attache 2.1.1 → 2.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1438a328d3cedfa04d52dcbe33d1b168be8ccd98
4
- data.tar.gz: 0676c54d6050a8280247fa4e48ade32ec749edaf
3
+ metadata.gz: 228685a6b1038b73b233cf5165570252f271f447
4
+ data.tar.gz: df3611d3b73a8c2120b9fda08fab214bfaa55ecb
5
5
  SHA512:
6
- metadata.gz: 25f7bdb0321d6850f7e42002fa54670654260f670023d3a119b587302f704efc303f2ef2c6ba8bcb852d77b7f35a66f11332b6fd2dc260940f94090ed25f523b
7
- data.tar.gz: bea5d1625b2235168897f5978de5fb1dbb62a5a9ec65af10a1264e7204c5397939b0d5447129ca2fff3b72e79c09956f90298f533c6815788f108cf97a007a32
6
+ metadata.gz: d8556bbf47617561a3bafd4bacb72ae3445e52357ee1acd5e5fd92473f4d1fbfe9336a86a3c6af30df01392a207a3be05881d88290c3cbf95dff3335dc515899
7
+ data.tar.gz: 71ec695990a228854eb3ba24fdcb5462f70b106670fa370d08d89584e04ae7e4ab8f9d5788cbf800f6d312a0fc6093bd8e82a86af27b8e8f605907de28199ee8
data/README.md CHANGED
@@ -67,7 +67,7 @@ NOTE: some config files will be written into your current directory (see RubyGem
67
67
 
68
68
  #### Source code
69
69
 
70
- You can checkout the source code and run it like a regular [a Procfile-based app](ddollar.github.io/foreman/)
70
+ You can checkout the source code and run it like a regular [a Procfile-based app](https://ddollar.github.io/foreman/):
71
71
 
72
72
  ```
73
73
  git clone https://github.com/choonkeat/attache.git
@@ -143,7 +143,11 @@ Users will upload files directly into the `attache` server from their browser, b
143
143
  > ```
144
144
  > PUT /upload?file=image123.jpg
145
145
  > ```
146
- > file content is the http request body
146
+ > file content is the http request body as raw binary (preferred) or encoded as base64 uri like this:
147
+ > ```
148
+ > PUT /upload?file=image123.jpg
149
+ > data:image/jpeg;base64,/9j/4QBiR....
150
+ > ```
147
151
 
148
152
  The main app front end will receive a unique `path` for each uploaded file - the only information to store in the main app database.
149
153
 
@@ -152,6 +156,16 @@ The main app front end will receive a unique `path` for each uploaded file - the
152
156
  > ```
153
157
  > json response from attache after upload.
154
158
 
159
+ ##### Upload by url
160
+
161
+ > ```
162
+ > GET /upload_url?url=https://example.com/logo.png
163
+ > ```
164
+
165
+ Attache will download the file from `url` supplied and uploads it through the regular `/upload` handler. So be expecting the same json response after upload. works with `GET`, `POST`, `PUT`.
166
+
167
+ Data URIs (aka base64 encoded file binaries) can also be uploaded to the same `/upload_url` endpoint through the same `url` parameter.
168
+
155
169
  #### Download
156
170
 
157
171
  Whenever the main app wants to display the uploaded file, constrained to a particular size, it will use a helper method provided by the `attache` lib. e.g. `embed_attache(path)` which will generate the necessary, barebones markup.
data/config.ru CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'attache'
2
2
 
3
3
  use Attache::Delete
4
+ use Attache::UploadUrl
4
5
  use Attache::Upload
5
6
  use Attache::Download
6
7
  use Attache::Tus::Upload
@@ -4,6 +4,8 @@ require 'securerandom'
4
4
  require 'disk_store'
5
5
  require 'fileutils'
6
6
  require 'paperclip'
7
+ require 'net/http'
8
+ require 'tempfile'
7
9
  require 'sidekiq'
8
10
  require 'tmpdir'
9
11
  require 'logger'
@@ -50,6 +52,7 @@ require 'attache/job'
50
52
  require 'attache/resize_job'
51
53
  require 'attache/base'
52
54
  require 'attache/vhost'
55
+ require 'attache/upload_url'
53
56
  require 'attache/upload'
54
57
  require 'attache/delete'
55
58
  require 'attache/backup'
@@ -9,7 +9,7 @@ class Attache::Upload < Attache::Base
9
9
  case env['REQUEST_METHOD']
10
10
  when 'POST', 'PUT', 'PATCH'
11
11
  request = Rack::Request.new(env)
12
- params = request.params
12
+ params = request.GET # stay away from parsing body
13
13
  return config.unauthorized unless config.authorized?(params)
14
14
 
15
15
  relpath = generate_relpath(Attache::Upload.sanitize params['file'])
@@ -0,0 +1,67 @@
1
+ class Attache::UploadUrl < Attache::Base
2
+ def initialize(app)
3
+ @app = app
4
+ end
5
+
6
+ def _call(env, config)
7
+ case env['PATH_INFO']
8
+ when '/upload_url'
9
+
10
+ # always pretend to be `POST /upload`
11
+ env['PATH_INFO'] = '/upload'
12
+ env['REQUEST_METHOD'] = 'POST'
13
+
14
+ request = Rack::Request.new(env)
15
+ params = request.params
16
+ return config.unauthorized unless config.authorized?(params)
17
+
18
+ if params['url']
19
+ file, filename, content_type = download_file(params['url'])
20
+ filename = "index" if filename == '/'
21
+
22
+ env['CONTENT_TYPE'] = content_type || content_type_of(file.path)
23
+ env['rack.request.query_hash'] = (env['rack.request.query_hash'] || {}).merge('file' => filename)
24
+ env['rack.input'] = file
25
+ end
26
+ end
27
+ @app.call(env)
28
+ end
29
+
30
+ MAX_DEPTH = 30
31
+ def download_file(url, depth = 0)
32
+ raise Net::HTTPError, "Too many redirects" if depth > MAX_DEPTH
33
+ Attache.logger.info "Upload GET #{url}"
34
+
35
+ if url.match /\Adata:([^;,]+|)(;base64|),/
36
+ # data:[<mediatype>][;base64],<data>
37
+ # http://tools.ietf.org/html/rfc2397
38
+
39
+ data = URI.decode(url[url.index(',')+1..-1])
40
+ data = Base64.decode64(data) if $2 == ';base64'
41
+ content_type = ($1 == '' ? "text/plain" : $1)
42
+ filename = "data.#{content_type.gsub(/\W+/, '.')}"
43
+ return [StringIO.new(data), filename, content_type]
44
+ end
45
+
46
+ uri = uri.kind_of?(URI::Generic) ? url : URI.parse(url)
47
+ http = Net::HTTP.new(uri.host, uri.port)
48
+ http.use_ssl = true if uri.scheme == 'https'
49
+ req = Net::HTTP::Get.new(uri.request_uri)
50
+ req.initialize_http_header({"User-Agent" => ENV['USER_AGENT']}) if ENV['USER_AGENT']
51
+ req.basic_auth(uri.user, uri.password) if uri.user || uri.password
52
+ res = http.request(req)
53
+ case res.code
54
+ when /\A30[1,2]\z/
55
+ download_file URI.join(url, res['Location']).to_s, depth + 1
56
+
57
+ when /\A2\d\d\z/
58
+ f = Tempfile.new(["upload_url", File.extname(uri.path)])
59
+ f.write(res.body)
60
+ f.close
61
+ [f.tap(&:open), File.basename(uri.path)]
62
+
63
+ else
64
+ raise Net::HTTPError, "Failed #{res.code}"
65
+ end
66
+ end
67
+ end
@@ -1,3 +1,3 @@
1
1
  module Attache
2
- VERSION = "2.1.1"
2
+ VERSION = "2.2.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: attache
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.1
4
+ version: 2.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - choonkeat
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-02-05 00:00:00.000000000 Z
11
+ date: 2016-03-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -275,6 +275,7 @@ files:
275
275
  - lib/attache/tus.rb
276
276
  - lib/attache/tus/upload.rb
277
277
  - lib/attache/upload.rb
278
+ - lib/attache/upload_url.rb
278
279
  - lib/attache/version.rb
279
280
  - lib/attache/vhost.rb
280
281
  - public/index.html