Google Storage API - Resume Download, AJAX Error, CORS

Getting a weird mistake.

When a user wants to upload a file, he sends an AJAX request to my server. My server authenticates the server side with OAuth2 on Google’s servers, creates an access token, starts a renewable download, and transfers the renewable URI and access token to the browser.

The browser then loads directly into the Google repository.

Everything seems to be in order. The file doesn’t end up in storage without problems, but I still get the CORS error in Chrome, and I'm not sure where and why. Here is a simplified version of my javascript code:

var file = document.getElementById("fileInput").files[0]; var request = requestUpload(); var token = request.token; var uri = request.uri; var r = new XMLHttpRequest(); r.open('PUT', uri, true); r.setRequestHeader("Authorization", "Bearer "+token); r.send(file);` 

Pretty simple, but I still get this general error:

XMLHttpRequest cannot load https://www.googleapis.com/upload/storage/v1/b/*****. No 'Access-Control-Allow-Origin' header is present on the requested resource.

Despite the fact that it seems to be fully functional. Is Javascript requesting to see something that I am not allowed by default? I would not want to have mistakes.

The XMLHttpRequest object also fires an error event after loading is complete. I assume that the query expects some kind of feedback from Google that it does not receive, and JavaScript becomes the Latin alphabet of JavaScript, so most of the discussions I found relate to jQuery.

Thank you very much!

+6
source share
2 answers

I just ran into this exact problem. If I scratched my head a little, but I understood the solution. This is pretty poorly documented and the behavior doesn't make much sense, but if you look at the last marker point on this page

https://cloud.google.com/storage/docs/cross-origin

When using the revolving boot protocol, Origin from the first request (download) is always used to determine the Access-Control-Allow-Origin header in the response, even if another Origin is used for the subsequent request. Thus, you must use the same source for the first and subsequent requests, or if the first request has a different origin than subsequent requests, use the XML API with the CORS configuration set to *.

So, what I did, I added the Origin: http://example.com header Origin: http://example.com request for a renewable request to initialize the session from the server. Thus, all client requests matching this download session identifier will be checked for this origin.

The only thing that I still find strange is the OPTIONS preflight request made by the browser (at least for me), allowing anything, even if the PUT request failed.

+4
source

Even with this configuration, when you run gsutil cors get gs://your-bucket you will need to initiate the initial POST request according to @Craig's answer:

[{"maxAgeSeconds": 3600, "method": ["GET", "PUT", "POST", "HEAD", "DELETE"], "origin": ["*"], "responseHeader": ["*"]}] .

Using, for example, golang, it's easy to pass Origin to a gcloud request. With r http.Request , you can execute r.Header.Get("Origin") and pass it to the function that calls POST on gcloud. This is the function I wrote in golang:

 func GetUploadURL(bucket, object, contentType, origin string, expires time.Time) (string, error) { url, err := storage.SignedURL(bucket, object, &storage.SignedURLOptions{ GoogleAccessID: " your-service-account@your-gcloud-project.iam.gserviceaccount.com ", PrivateKey: pkey, // set this in package init() function Method: http.MethodPost, Expires: expires, ContentType: contentType, Headers: []string{"x-goog-resumable:start"}, }) if err != nil { return "", err } req, err := http.NewRequest("POST", url, nil) if err != nil { return "", err } req.Header.Set("Content-Type", contentType) req.Header.Set("x-goog-resumable", "start") req.Header.Set("Origin", origin) resp, err := http.DefaultClient.Do(req) if err != nil { return "", err } defer resp.Body.Close() return resp.Header.Get("Location"), nil } 
+1
source

Source: https://habr.com/ru/post/979073/


All Articles