Skip to content
Permalink
Browse files

Add empty OPTIONS route for presign_endpoint

Newer Uppy versions make an additional OPTIONS request before the GET
presign request. This is not a CORS preflight request (those are made
automatically by the browser for non-idempotent verbs like POST, PUT,
and DELETE), it's an explicit request that Uppy client seems to make for
every route now.

The intention is to fetch additional information from the Uppy Companion
app. Since our presign endpoint is not actually Uppy Companion, we just
return an empty response, which seems to be fine for Uppy.

The fact that this route was missing wasn't causing any actual problems,
as Uppy would still continue the upload regardless of whether the
OPTIONS request succeeded. This change is just so that developers don't
see a failed request in browser's network inspector.

Fixes #436
  • Loading branch information
janko committed Feb 3, 2020
1 parent 3e227b2 commit 0a6adbbdbaa42f144eaa5bd89882d95747c829af
Showing with 29 additions and 7 deletions.
  1. +2 −0 CHANGELOG.md
  2. +14 −2 lib/shrine/plugins/presign_endpoint.rb
  3. +13 −5 test/plugin/presign_endpoint_test.rb
@@ -1,5 +1,7 @@
## master

* `presign_endpoint` – Add `OPTIONS` route that newer versions of Uppy check (@janko)

* `derivatives` – Add `:create_on_promote` option for auto-creating derivatives on promotion (@janko)

* `s3` – Add back support for client-side encryption (@janko)
@@ -81,9 +81,14 @@ def call(env)

status, headers, body = catch(:halt) do
error!(404, "Not Found") unless ["", "/"].include?(request.path_info)
error!(405, "Method Not Allowed") unless request.get?

handle_request(request)
if request.get?
handle_request(request)
elsif request.options?
handle_options_request(request)
else
error!(405, "Method Not Allowed")
end
end

headers["Content-Length"] ||= body.map(&:bytesize).inject(0, :+).to_s
@@ -109,6 +114,13 @@ def handle_request(request)
make_response(presign, request)
end

# Uppy client sends an OPTIONS request to fetch information about the
# Uppy Companion. Since our Rack app is only acting as Uppy Companion, we
# just return a successful response.
def handle_options_request(request)
[200, {}, []]
end

# Generates the location using `Shrine#generate_uid`, and extracts the
# extension from the `filename` query parameter. If `:presign_location`
# option is given, calls that instead.
@@ -107,18 +107,26 @@ def endpoint
assert_equal "image/jpeg", response.body_json["fields"]["Content-Type"]
end

it "accepts only GET requests" do
response = app.put "/"
assert_equal 405, response.status
assert_equal "text/plain", response.headers["Content-Type"]
assert_equal "Method Not Allowed", response.body_binary
it "accepts OPTIONS request" do
response = app.options "/"

assert_equal 200, response.status
assert_equal Hash["Content-Length" => "0"], response.headers
assert_equal "", response.body_binary
end

it "accepts only root requests" do
response = app.get "/presign"
assert_equal 404, response.status
end

it "doesn't accept verbs other than GET or OPTIONS" do
response = app.put "/"
assert_equal 405, response.status
assert_equal "text/plain", response.headers["Content-Type"]
assert_equal "Method Not Allowed", response.body_binary
end

describe "Shrine.presign_response" do
it "returns the Rack response triple" do
env = {

0 comments on commit 0a6adbb

Please sign in to comment.
You can’t perform that action at this time.