Amplify PubSub not sending/receiving - no errors - amazon-web-services

I have been struggling with this implementation and figured I'd ask for some community perspective at this point.
I've implemented PubSub with a Lambda successfully and when tested in the cloud I am seeing messages in the IoT test environment. I believe, therefore, that my endpoint is functional.
When trying to implement the Amplify service via the docs (https://docs.amplify.aws/lib/pubsub/getting-started/q/platform/js/) I have been running into all sorts of issues. Worked through the "socket:undefined" issue by reinstalling lock file and node-modules. Now am not getting any errors but it simply is not connecting.
My code is below. Currently when I try to publish I'm getting a response of []. If I try to specify the provider I get this error - "Error: Could not find provider named AWSIoTProvider".
Note: I have been following various SOs - this one most recently:
Amplify PubSub javascript subscribe and publish using cognito authorization: how to?
import Amplify from 'aws-amplify';
import { AWSIoTProvider } from '#aws-amplify/pubsub/lib/Providers';
import PubSub from '#aws-amplify/pubsub';
Amplify.addPluggable(new AWSIoTProvider({
aws_pubsub_region: 'as-southeast-2',
aws_pubsub_endpoint: 'wss://{MY_IOT_ID}-ats.iot.ap-southeast-2.amazonaws.com/mqtt',
}));
Amplify.configure(config);
PubSub.configure();
PubSub.subscribe('myTopic1').subscribe({
next: data => console.log('Message received', data),
error: error => console.error(error),
complete: () => console.log('Done'),
});
Then I have a function that I'm calling for publish that returns the [] if I don't specify the provider and the error above if I specify it (shown below)
Unspecified:
await PubSub.publish('1234-abcd-9876/workitem', { msg: 'Hello to all subscribers!' })
.then(response => console.log('Publish response:', response))
.catch(err => console.log('Publish Pub Err:', err));
Specified:
await PubSub.publish('1234-abcd-9876/workitem', { msg: 'Hello to all subscribers!' }, { provider: 'AWSIoTProvider' })
.then(response => console.log('Publish response:', response))
.catch(err => console.log('Publish Pub Err:', err));
Does anyone have any thoughts as to what I might be doing wrong here or might try next?
Thanks!

Since you are saying the specific error you got is - "Error: Could not find provider named AWSIoTProvider".
so, change the import path for AWSIoTProvider to #aws-amplify/pubsub instead of using #aws-amplify/pubsub/lib/Providers.
import { AWSIoTProvider } from '#aws-amplify/pubsub;

Related

AWS Amplify post request fails with "status code 403 at node_modules/axios"

I configured and initialized AWS Amplify for my ReactNative/Expo app and added a REST Api. Im new to AWS in general, but im assuming that once I add the API, my project is populated with amplify/backend folders and files and is ready for consumption.
So i tried to create a simple post request to create an item in my DynamoDB table with
import { Amplify, API } from "aws-amplify";
import awsconfig from "./src/aws-exports";
Amplify.configure(awsconfig);
const enterData = async () => {
API.post("API", "/", {
body: {
dateID: "testing",
},
headers: {
Authorization: `Bearer ${(await Auth.currentSession())
.getIdToken()
.getJwtToken()}`
}
})
.then((result) => {
// console.log(JSON.parse(result));
})
.catch((err) => {
console.log(err);
});
};
const signIn = async () => {
Auth.signIn('test#test.com', 'testpassword')
.then((data) => {
console.log(data)
enterData() //enterData is attempted after signin is confirmed.
})
.catch((err) => {
console.log(err)
})
}
signIn()
I did not touch anything else in my project folder besides including the above in my App.tsx because im unsure if i need to and where. I got a 403 error code and it "points" to the axios package but im not sure if issue is related to aws integration.
I configured the REST Api with restricted access where Authenticated users are allowed to CRUD, and guests are allowed to Read. How could I even check if I am considered an "Authorized User" .
Yes, AWS Amplify API category uses Axios under the hood so axios is related to your problem.
Probably you get 403 because you didn't authorized, for Rest API's you need to set authorization headers,
I don't know how is your config but you can take help from this page. Please review the "Define Authorization Rules" section under the API(REST) section.
https://docs.amplify.aws/lib/restapi/authz/q/platform/js/#customizing-http-request-headers
To check authorization methods, you can use "Auth" class like that also you can see auth class usage in the above link.
import { Amplify, API, Auth } from "aws-amplify";
https://aws-amplify.github.io/amplify-js/api/classes/authclass.html

AWS Lambda URL fetch data from Rapid API

I'm new to AWS including Lambda (and stack over flow for that matter so go easy on me please). I want to be able to get data requests from https://rapidapi.com/api-sports/api/api-football and post the results to my S3 or Dynamo DB instances.
I've attempted creating an AWS Lambda URL function which only succeeds in returning null results. I have tried looking for a straight forward explanation of how to achieve this but im a bit stumped.
So i created a test Lambda URL function by copying the API code supplied by Rapid API (node JS fetch). I pasted it under this line of code export const handler = async(event) => {
So i ended up with this code
export const handler = async(event) => {
const options = {
method: 'GET',
headers: {
'X-RapidAPI-Host': 'api-football-v1.p.rapidapi.com',
'X-RapidAPI-Key': 'MY API KEY',
Authorization: 'Basic Og=='
}
};
fetch('https://api-football-v1.p.rapidapi.com/v3/players?team=42&season=2022&search=saka', options)
.then(response => response.json())
.then(response => console.log(response))
.catch(err => console.error(err))};
I also added the JSON schema provided by rapid API
I run the test in AWS and it says its succeeded but i get the below message and it returns null.
Test Event Name
JSON
Response
null
Function Logs
START RequestId: bfb5ddd4-56f8-466a-b3c1-7ed89f3edc2b Version:
$LATEST
2022-11-24T16:07:33.622Z
203cdbbc-a661-4256-91bb-2ada34d53042
ERROR TypeError: fetch failed
at Object.fetch (node:internal/deps/undici/undici:11118:11)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
cause: ConnectTimeoutError: Connect Timeout Error
at onConnectTimeout (node:internal/deps/undici/undici:6625:28)
at node:internal/deps/undici/undici:6583:50
at Immediate._onImmediate (node:internal/deps/undici/undici:6614:13)
at process.processImmediate (node:internal/timers:471:21) {
code: 'UND_ERR_CONNECT_TIMEOUT'
}
}
END RequestId: bfb5ddd4-56f8-466a-b3c1-7ed89f3edc2b
REPORT RequestId: bfb5ddd4-56f8-466a-b3c1-7ed89f3edc2b Duration: 194.65 ms Billed Duration: 195 ms Memory Size: 128 MB Max Memory Used: 73 MB
Request ID
bfb5ddd4-56f8-466a-b3c1-7ed89f3edc2b
Would anyone know what im doing wrong or be able to point me in the right direction?

Unable to fetch a valid error code when AWS Cognito authentication fails

I am using AWS Cognito for Authentication using user pools and I have all my APIs configured on the API gateway. I directly hit cognito from the Angular client, store the tokens returned by Cognito in local storage and use them in subsequent calls.
The problem however is, if the token I send from Angular has expired the Cognito authentication fails and no Integration backend is hit in this case. As a result, I am getting a 401 error in Chrome.
The interesting thing however is that this 401 code is not available to me in the HTTP response object that is passed to Angular. A default 0 code is received by the Angular and this seems to be the case with all the error code received from server (either cognito or backend).
I tried to explore around and found that the issue might be because the gateway is not sending proper CORS headers in the error cases. I have read following related docs but unfortunately I couldn't find out a way to resolve the issue.
Can someone suggest a solution to this.
Edit: I also read somewhere that it is a known AWS issue. Is that the case ?
You can manage the Cognito session before making the call to the API Gateway.
In the example below, the getSession method has a callback that prints out any error messages to the console, and returns.
////// Cognito.js
import {
CognitoUserPool,
CookieStorage
} from 'amazon-cognito-identity-js'
import config from '../config'
const cookieSettings = {
domain: '.xxxxxxxxxxx.com',
secure: true
}
export default {
cookieSettings,
pool: new CognitoUserPool({
UserPoolId: config.UserPoolId,
ClientId: config.ClientId,
Storage: new CookieStorage(cookieSettings)
})
}
//////
////// actions.js
import Cognito from './Cognito'
export function fetchUser() {
// get cognito user cookies
const cognitoUser = Cognito.pool.getCurrentUser()
if (cognitoUser != null) {
// try to get session from cognito
cognitoUser.getSession(function(err, session) {
if (err) {
console.log(err)
return;
}
fetch('https://api-gateway-url', {
headers: {
Authorization: 'Bearer ' + session.getAccessToken().getJwtToken(),
}
})
.then(response => response.json())
.then(json => console.log(json))
})
}
}

AWS X-Ray (with SailsJS) not logging things in the correct trace?

I am trying to use AWS X-Ray in my SailsJS application. I noticed missing subsegments - I added custom traces via AWSXRay.captureAsyncFunc but noticed they are missing. After some closer inspection, I think they actually ended up in a different trace. Lets say I call login API then another API later. I notice my login API trace is weird
Notice theres calls quite abit after the request should have ended.
Those requests should actually be in another segment:
I'd think they should appear after find device subsegment. Why are segments scrambled like that?
My setup: in http.js,
const AWSXRay = require('aws-xray-sdk');
const xrayEnabled = process.env.AWS_XRAY === 'yes'
module.exports.http = {
middleware: {
order: [
'startRequestTimer',
'cookieParser',
'session',
'myRequestLogger',
'bodyParser',
'handleBodyParserError',
'compress',
'methodOverride',
'poweredBy',
'awsXrayStart',
'router',
'awsXrayEnd',
'www',
'favicon',
'404',
'500',
],
awsXrayStart: xrayEnabled ? AWSXRay.express.openSegment(`cast-${process.env.NODE_ENV || 'noenv'}`) : (req, res, next) => next(),
awsXrayEnd: xrayEnabled ? AWSXRay.express.closeSegment() : (req, res, next) => next(),
Then I wrapped my promises like:
instrumentPromise(promise, name, metadata = {}) {
if (this.isXrayEnabled()) {
return new Promise((resolve, reject) => {
AWSXRay.captureAsyncFunc(name, (subsegment) => {
if (!subsegment) console.warn(`[XRAY] Failed to instrument ${name}`)
Object.keys(metadata).forEach(k => {
if (subsegment) subsegment.addMetadata(k, metadata[k])
})
console.time(`[XRAY TIME] ${name}`)
promise
.then((data) => {
if (subsegment) subsegment.close()
console.timeEnd(`[XRAY TIME] ${name}`)
resolve(data)
})
.catch(err => {
if (subsegment) subsegment.close()
console.timeEnd(`[XRAY TIME] ${name}`)
reject(err)
})
})
})
}
return promise
}
Is there any information I am missing here? What am I doing wrong?
I tried manual mode and its alot more reliable but I have to manually pass segment around. Whats wrong with automatic mode? I am kind of guessing it does not work well with async nature nodejs? Like the SDK is not able to differenciate between the various async requests? And may close or track segments in the wrong places? That said ... its supposed to work with express, why isit not working as expected ...
Another thing is how will a shared mysql connection pool be tracked correctly by X-Ray? Different segments will be using the same mysql pool. I assume this will not work work well at all?
The issue you encounter seems to be related to how CLS handle context binding with Promise. There is a opt-in promise patch introduced in this PR https://github.com/aws/aws-xray-sdk-node/pull/11. It has full discussion around the repros and fixes. That should resolve the issue with subsegments being attached to the wrong trace.
The SDK does support capturing pool.query. You can see examples here https://www.npmjs.com/package/aws-xray-sdk-mysql.

AppSync ReactNative Cognito Promise Rejection

I have a exception thrown by react native when the app is started and also logged in.
my config is
"authenticationType": "AMAZON_COGNITO_USER_POOLS",
"apiKey": null
cognito is working with appsync, but i donĀ“t know how to fix the alert message.
Any suggestions are welcomed thanks.
I have not worked with AWS appsync, so I don't know what might be the problem. I can just suggest you one thing,add promise resolver function. That way you can see what it's returning, and it will prevent showing any alert. Something like-
jwtToken: async () => (await Auth.currentSession()
.then(data => {
console.log("data",data);
return data
})
.catch(err => {
console.log("error",error);
return err
})).getIdToken().getJwtToken()