Google Storage API - Handling Partially Uploaded Files, JavaScript Fetch API, Cross-Origin Resource Sharing Issue

Experiencing an unusual error.

When a user attempts to upload a file, an AJAX request is sent to the server. The server then authenticates with OAuth2 to Google's servers, generates an access token, initiates a resumable upload process, and provides the resumable upload URI and access token back to the browser.

Subsequently, the browser directly uploads the file to Google Storage.

Despite successfully transmitting the file to the Storage Bucket, a CORS error persists in Chrome without clear indication of its origin or cause. Below 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);`

While seemingly straightforward, the following common error continues to occur:

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

Despite functionality, I am puzzled by this persistent error message. Could it be that JavaScript is requesting unauthorized information by default? I aim for a seamless operation without any errors.

After completion of uploading, the XMLHttpRequest object triggers an error event, suggesting that perhaps the request expects feedback from Google that is not being received. This issue seems to be confounding JavaScript developers, with much discussion revolving around jQuery instead.

Your assistance is greatly appreciated!

Answer №1

I recently encountered a similar issue that had me puzzled for a while, but I managed to find a solution. The documentation on this topic is lacking, and the behavior can be confusing at times. However, after reviewing the last bullet point on the following page

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

When utilizing the resumable upload protocol, the Origin from the initial (start upload) request determines the Access-Control-Allow-Origin header in the response, even if subsequent requests use a different Origin. Therefore, it is recommended to either maintain the same origin for all requests or, if the first request has a different origin, utilize the XML API with CORS configuration set to *.

To address this issue, I included the Origin: http://example.com request header in the resumable session initiation request from the server. This ensured that all client requests pertaining to that upload session id matched against that specific origin.

One puzzling aspect I noticed was that the browser's OPTIONS preflight request seemed to allow everything despite the PUT request failing in my case.

Answer №2

When running the gsutil cors get gs://your-bucket command with this setup, it is necessary to trigger the initial POST request as described in @Craig's response:

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

If you are using golang, passing the Origin to the gcloud request can be easily achieved. By taking an r http.Request input, you can extract the origin by executing r.Header.Get("Origin") and passing it to a function that triggers the POST on gcloud. Here is an example of such a function written in golang:

func GetUploadURL(bucket, object, contentType, origin string, expires time.Time) (string, error) {
    url, err := storage.SignedURL(bucket, object, &storage.SignedURLOptions{
        GoogleAccessID: "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="b9c0d6cccb94cadccbcfd0dadc94d8dadad6ccd7cdf9c0d6cccb94dedad5d6ccdd94c9cbd6d3dcdacd97d0d8d497decadccbcfd0dadcd8dadad6ccd7cd97dad6d4">[email protected]</a>",
        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
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Unable to get onChange function to work with multiple input fields in React

I am attempting to implement a feature where an additional input field is added when the user clicks on the "Add input" button, and then store those input values in an object: const {useState } = React; const InviteUser = () => { const [userDetail ...

Utilizing an Application Programming Interface in React Native

Recently diving into React Native, I embarked on creating a basic app leveraging the Marvel API along with an API wrapper. My aim is to implement an infinite scroll view using VirtualizedList. Here's where I could use some guidance: What should be pas ...

Is XMLHttpRequest just sitting idle...?

As a newcomer to the world of javascript and AJAX, I've been stuck on a single problem for the past 8 hours. Despite my best efforts, I just can't seem to figure out what's going wrong. On my website, I have an image with an onclick event ca ...

Tips for sorting ng-Table using an array of numerous values

I am currently working on implementing angular-selectize.js (https://github.com/machineboy2045/angular-selectize) into my project. This will create a search box that allows for entering multiple values to filter all cells in an ng-Table without the need to ...

Verify if the link includes https:// while using angularjs

In my angular app, there is a lot of data stored in JSON format. [ {"link": "https://stackoverflow.com"}, {"link": "https://stackoverflow.com"}, {"link": "id-aW783D"}, //This data is incorrect {"link": "https://stackoverflow.com"} ] However, the ...

Activate browser scrollbar functionality

Below is the HTML code snippet: <html> <head> <style> #parent { position : absolute; width : 500px; height : 500px; } #top { position : absolute; width : 100%; height: 100%; z-index : 5; } #bottom { position : absolute; width : 100%; ...

I have a quick question: What is the most effective method for creating PDF templates with Angular and .NET 6, specifically for designs that feature heavy

Seeking the optimal solution for creating PDF templates using Angular and .NET 6? Specifically looking to design templates that heavily feature tables. In my exploration of efficient PDF template creation with Angular and .NET 6, I ventured into using pdf ...

Generating a unique user ID similar to Zerodha's user ID using Node.js/JavaScript

For a project I'm working on, I need to create random and unique User IDs. I came across Zerodha's user IDs which are easy to remember. In Zerodha user IDs: The first two characters are always letters followed by four numbers. I want to generat ...

Tips for triggering a postback with jquery autocomplete when an option is selected

TEST AREA I've put together a basic demo of jquery-ui autocomplete. QUERY How do I trigger a postback when a selection is made from the autocomplete list? HTML <select id="ddl"></select> <input id="field" type="text"></input& ...

Deciphering the occurrence of jQuery-Mobile page firing events: the mystery behind dialog pages appearing upon closure

I'm still fairly new to jQuery-Mobile and I'm trying to wrap my head around what exactly happens when a page or dialog is loaded. To help illustrate the confusion I'm experiencing, I put together a small collection of files that showcase th ...

Create a file by generating JSON data in an ASP.NET MVC post controller and then return the file

I am currently working on an ajax post request: function downloadElevationMap() { var jsonData = ko.toJSON(mod.SelectedItem); $.ajax({ url: '/Home/GetData/', type: 'POST', contentType: "application/jso ...

Using $scope.$on name parameter as an attribute within an AngularJS directive

My goal is to create a directive that allows me to pass in an attribute string, which will then be used as the "name" parameter when subscribing to events using $scope.$on. The process involves: An object is broadcasted using $rootScope.$broadcast, label ...

JavaScript visibility disappearing intermittently

I have created a custom image viewer box that overlays a thumbnail gallery page. The image viewer should appear when a user clicks on a thumbnail. However, currently, the viewer only pops up briefly and then disappears again. I am looking for a way to mak ...

Modify the filtered class of ng-repeat using the $index value from the controller

Here is my ng-repeat code: <div class="{{event.who_seen_it | newEvent}}" ng-repeat="event in eventList" ng-click="openEvet(event.title,$index)"> <h3 class="event-title">{{event.title}}</h3> </div> I am using the {{event.who_se ...

What are the fundamentals of type conversion in struts2?

In my struts.xml file, I have the following code: <s:textfield id="thresholdParameter_1" name="gmathreshold.distinctBnumberRatio"> </s:textfield></td> The gmathreshold is a bean with a member variable distinctBnumberRatio which is a ...

Tips for integrating Twitter sharing functionality in React JS

I am looking for a way to enable users to easily share images from my website on Twitter. Although I tried using the react-share module, it does not provide an option to directly share images. This is the snippet of code I currently have: import { Sh ...

What events precede and follow a keydown action in a Textarea field?

I need to prevent users from pressing function keys (F1, F2, etc.), the tab key, and any other characters from being added. The code below is supposed to achieve this on my website but it's not working. document.getElementById("code").addEventList ...

Encountering an Error When Trying to Post to WebMethod Using AJAX

First Step: The initial step in this process involves defining a script on the home.aspx page. The script is as follows: function ShowCurrentTime() { var post = ({ method: "POST", url: "home.aspx/GetData", dataType: 'json ...

Codeigniter unable to fetch data sent via AJAX

I am in need of assistance with my mobile app development project. I am using phonegap/cordova for the app and codeigniter for the web service. The app includes a registration function where data is sent via Ajax to a codeigniter controller and saved in a ...

The Next.js API endpoint is struggling to process cross-domain POST requests

Dealing with a POST request in my NextJS application has been challenging. This particular post request is originating from a different domain. To address this issue, I included a receptor.ts file in the /pages/api directory: import { NextApiRequest, Next ...