amplify-js icon indicating copy to clipboard operation
amplify-js copied to clipboard

Cannot call REST api from web worker using aws-ampliy

Open alex-breen opened this issue 1 year ago • 13 comments

Before opening, please confirm:

JavaScript Framework

React

Amplify APIs

REST API

Amplify Version

v6

Amplify Categories

api

Backend

Amplify CLI

Environment information

# Put output below this line
  System:
    OS: Windows 11 10.0.22621
    CPU: (6) x64 Intel(R) Core(TM) i5-9600K CPU @ 3.70GHz
    Memory: 3.06 GB / 15.94 GB
  Binaries:
    Node: 18.18.0 - C:\Program Files\nodejs\node.EXE
    npm: 10.1.0 - C:\Program Files\nodejs\npm.CMD
  Browsers:
    Chrome: 120.0.6099.217
    Edge: Chromium (120.0.2210.133)
    Internet Explorer: 11.0.22621.1
  npmPackages:
    @aws-amplify/ui-react: ^6.1.1 => 6.1.1
    @aws-amplify/ui-react-internal:  undefined ()
    @aws-amplify/ui-react-storage: ^3.0.10 => 3.0.10
    @types/react: ^18.2.43 => 18.2.47
    @types/react-dom: ^18.2.17 => 18.2.18
    @vitejs/plugin-react: ^4.2.1 => 4.2.1
    aws-amplify: ^6.0.12 => 6.0.12
    aws-amplify/adapter-core:  undefined ()
    aws-amplify/analytics:  undefined ()
    aws-amplify/analytics/kinesis:  undefined ()
    aws-amplify/analytics/kinesis-firehose:  undefined ()
    aws-amplify/analytics/personalize:  undefined ()
    aws-amplify/analytics/pinpoint:  undefined ()
    aws-amplify/api:  undefined ()
    aws-amplify/api/server:  undefined ()
    aws-amplify/auth:  undefined ()
    aws-amplify/auth/cognito:  undefined ()
    aws-amplify/auth/cognito/server:  undefined ()
    aws-amplify/auth/enable-oauth-listener:  undefined ()
    aws-amplify/auth/server:  undefined ()
    aws-amplify/datastore:  undefined ()
    aws-amplify/in-app-messaging:  undefined ()
    aws-amplify/in-app-messaging/pinpoint:  undefined ()
    aws-amplify/push-notifications:  undefined ()
    aws-amplify/push-notifications/pinpoint:  undefined ()
    aws-amplify/storage:  undefined ()
    aws-amplify/storage/s3:  undefined ()
    aws-amplify/storage/s3/server:  undefined ()
    aws-amplify/storage/server:  undefined ()
    aws-amplify/utils:  undefined ()
    eslint: ^8.55.0 => 8.56.0
    eslint-plugin-react: ^7.33.2 => 7.33.2
    eslint-plugin-react-hooks: ^4.6.0 => 4.6.0
    eslint-plugin-react-refresh: ^0.4.5 => 0.4.5
    react: ^18.2.0 => 18.2.0
    react-dom: ^18.2.0 => 18.2.0
    vite: ^5.0.8 => 5.0.11
  npmGlobalPackages:
    @forge/cli: 4.1.1
    atlas-connect: 0.8.1
    firebase-tools: 10.7.0
    mongodb-realm-cli: 2.4.2
    npm-check-updates: 12.5.9
    npm: 10.1.0
    serve: 14.2.1

Describe the bug

From a web worker (on Chrome), invoking a get request to Amplify REST API fails with the following error. GET call failed: InvalidApiName: API name is invalid.

The same request running in the main thread is successful.

Expected behavior

Works the same as when invoked in the main thread.

Reproduction steps

Please see code in snippet below.

Code Snippet

// Put your code below this line.
// WEB WORKER CODE (FAILS)
/* eslint-disable no-restricted-globals */
import { get } from "aws-amplify/api";
console.log("Worker started");

async function getFcn() {
    try {
        const restOperation = get({
            apiName: 'sandbox1',
            path: '/sandbox1'
        });
        const response = await restOperation.response;
        console.log('GET call succeeded: ', response);
    } catch (error) {
        console.log('GET call failed: ', error);
    }
}
getFcn();

// MAIN THREAD CODE (WORKS - see get request within useEffect)
import '@aws-amplify/ui-react/styles.css';
import { get } from 'aws-amplify/api';
import { useEffect, useMemo } from 'react';

const Page = () => {
    const myWorker = useMemo(() => {
        return new Worker(new URL("./worker1.js", import.meta.url), {
            type: "module"
        })
    }, [])

    myWorker.postMessage('Hi worker')
    myWorker.onmessage = function (e) {
        console.log('Message received from worker', e);
    }

    useEffect(() => {
        async function getFcn() {
            try {
                const restOperation = get({
                    apiName: 'sandbox1',
                    path: '/sandbox1'
                });
                const response = await restOperation.response;
                console.log('GET call succeeded: ', response);
            } catch (error) {
                console.log('GET call failed: ', error);
            }
        }
        getFcn();
    }, []);

    return (
        <div>
            Hello again
        </div>
    )
};

export default Page;

Log output

Browser console log below. (Note, no network log as I don't think an attempt to make the call is made.) ``` // Put your logs below this line GET call failed: InvalidApiName: API name is invalid. at assertValidationError (http://localhost:3000/node_modules/.vite/deps/aws-amplify_api.js?v=77a22174:7280:11) at resolveApiUrl (http://localhost:3000/node_modules/.vite/deps/aws-amplify_api.js?v=77a22174:7288:3) at http://localhost:3000/node_modules/.vite/deps/aws-amplify_api.js?v=77a22174:7381:15 at job (http://localhost:3000/node_modules/.vite/deps/aws-amplify_api.js?v=77a22174:7211:69) at createCancellableOperation (http://localhost:3000/node_modules/.vite/deps/aws-amplify_api.js?v=77a22174:7243:24) at publicHandler (http://localhost:3000/node_modules/.vite/deps/aws-amplify_api.js?v=77a22174:7378:51) at get3 (http://localhost:3000/node_modules/.vite/deps/aws-amplify_api.js?v=77a22174:7404:32) at get4 (http://localhost:3000/node_modules/.vite/deps/aws-amplify_api.js?v=77a22174:7412:23) at getFcn (http://localhost:3000/src/worker1.js?type=module&worker_file:8:31) at http://localhost:3000/src/worker1.js?type=module&worker_file:18:1

</details>


### aws-exports.js

amplifyconfiguration.json:

{ "aws_project_region": "us-east-1", "aws_cognito_identity_pool_id": "us-east-1:0598a33f-9357-4ba8-9cb2-876da7c9bb85", "aws_cognito_region": "us-east-1", "aws_user_pools_id": "us-east-1_JAAkzlaKS", "aws_user_pools_web_client_id": "27s2qe07qgpp0mf7083dian9ua", "oauth": { "domain": "sandboxauth167bef521-67bef521-dev.auth.us-east-1.amazoncognito.com", "scope": [ "phone", "email", "openid", "profile", "aws.cognito.signin.user.admin" ], "redirectSignIn": "http://localhost:3000/", "redirectSignOut": "http://localhost:3000/", "responseType": "code" }, "federationTarget": "COGNITO_USER_POOLS", "aws_cognito_username_attributes": [ "EMAIL" ], "aws_cognito_social_providers": [ "GOOGLE" ], "aws_cognito_signup_attributes": [ "EMAIL" ], "aws_cognito_mfa_configuration": "OFF", "aws_cognito_mfa_types": [ "SMS" ], "aws_cognito_password_protection_settings": { "passwordPolicyMinLength": 8, "passwordPolicyCharacters": [] }, "aws_cognito_verification_mechanisms": [ "EMAIL" ], "aws_cloud_logic_custom": [ { "name": "sandbox1", "endpoint": "https://n66fgb5l98.execute-api.us-east-1.amazonaws.com/dev", "region": "us-east-1" } ] }


### Manual configuration

_No response_

### Additional configuration

_No response_

### Mobile Device

_No response_

### Mobile Operating System

_No response_

### Mobile Browser

_No response_

### Mobile Browser Version

_No response_

### Additional information and screenshots

_No response_

alex-breen avatar Jan 18 '24 19:01 alex-breen

Thanks for creating this issue from the Discord Office Hours session today, @alex-breen. Can you clarify how you're initializing Amplify within the web worker or if it's being imported? And based on the error that you're seeing, can you double check that the API names in the web worker exactly match what's in your config (i.e. casing/spelling)?

cwomack avatar Jan 18 '24 22:01 cwomack

  • I am importing 'aws-amplify/api'. Like this; import { get } from "aws-amplify/api";
  • The API names are the same. I copied the same code from the main thread component, where the call works.

Side note - I (clumsily) tried a few different things with the web worker to try to make it work. I imported a window polyfill - no change. I called Amplify.configure(amplifyconfig) inside the webworker - I no longer got the invalidAPIName error, but instead got errors about not having authentication credentials. I added authCode into the options field - but I still got errors about missing creds.

alex-breen avatar Jan 18 '24 23:01 alex-breen

Ok, thanks for the quick response and glad to hear we’re past the original error then at least! It sounds like what’s happening here is you’ve got some type of network requests needing authenticated credentials happening in the web worker. Can you maybe share some additional context here about what you’re trying to do with the web worker?

If you’re trying to offload some of the work to the web worker, you may want to make any networks requests within the main thread but then hand off the response and other work to the web worker after it’s been received for additional processing. If you’re trying to do all this work in the web worker, that error seems like it’ll require you passing credentials into the other thread and require you writing your own credential and token providers (which we wouldn’t recommend).

cwomack avatar Jan 18 '24 23:01 cwomack

Thanks @cwomack, that's helpful.

Here is the context about why I'm using a web worker:

  • I use a web worker to run a machine learning transformer that would block the main thread if it weren't separated.
  • After the transformer is done, the worker makes a post to a Lamda function (using the API path set up using Amplify CLI).
  • When the Lambda is done, it returns a result to the web worker. After some processing, the web worker passes a result back to the main thread.

So, as an alternate method, if I can't invoke the get call from the web worker, I can pass the result back to the main thread and make the post to the API/Lambda from there (like you suggested, just in reverse). The reason I wanted to avoid doing that is so I didn't have to pass large payloads of data between the worker and the main thread. And just to keep the logic in one place.

alex-breen avatar Jan 19 '24 00:01 alex-breen

@alex-breen, we're going to mark this as a feature request at this point to track better support out of the box for web workers. Appreciate you giving the additional context and use cases here.

cwomack avatar Mar 07 '24 16:03 cwomack