How to make a POST request from Flutter to Amplify REST API - javascript

Following the getting started documentation for Amplify Flutter REST API, the auto-generated POST request below for ExpressJS results in the following error:
SyntaxError: Unexpected token ' in JSON at position 1
at JSON.parse
The GET request returns fine, but when changing to POST and adding the body field below from the documentation the error is returned. How can a POST request be successfully called from Flutter using the Amplify REST API?
Flutter GET Request - (no error)
Future<void> callAPI() async {
try {
RestOptions options = RestOptions(
path: '/example',
apiName: 'ExpressJSRESTAPI'
);
RestOperation restOperation = Amplify.API.get(
restOptions: options
);
RestResponse response = await restOperation.response;
print('GET call succeeded');
print(new String.fromCharCodes(response.data));
} on ApiException catch (e) {
print('GET call failed: $e');
}
}
Flutter POST Request (throws error)
Future<void> callAPI() async {
try {
RestOptions options = RestOptions(
path: '/example',
body: Uint8List.fromList('{\'name\':\'Mow the lawn\'}'.codeUnits),
apiName: 'ExpressJSRESTAPI'
);
RestOperation restOperation = Amplify.API.post(
restOptions: options
);
RestResponse response = await restOperation.response;
print('POST call succeeded');
print(new String.fromCharCodes(response.data));
} on ApiException catch (e) {
print('POST call failed: $e');
}
}
ExpressJS GET request path
app.get('/example', function(req, res) {
// Add your code here
res.json({success: 'get call succeed!', url: req.url});
});
ExpressJS POST request path
app.post('/example', function(req, res) {
// Add your code here
res.json({success: 'post call succeed!', url: req.url, body: req.body})
});

From the documentation, notice the reverse slash (\) in your RestOptions' fromList arguments.
RestOptions options = RestOptions(
path: '/todo',
body: Uint8List.fromList('{\'name\':\'Mow the lawn\'}'.codeUnits)
);

Based on the github discussion here the issue happening due to unneeded escape character.
Change your body parameter to this:
body: Uint8List.fromList('{"name":"Mow the lawn now!"}'.codeUnits)
or
body: ascii.encode('{"name":"Mow the lawn"}')

Related

nuxt app deployed to Netlify: fetch to api working locally, but not on deployed site: getting a 404

I have a Nuxt.js app that I'm trying to deploy to Netlify - and everything works on my local machine, but the fetch request to the api returns a 404 when it's deployed to Netlify. I don't know how to make that server route available to my client when it's deployed.
the fetch request in my api-client.js file looks like this:
async fetchInfo(state) {
let response = await fetch(`/api/info/${state}`);
let data = await response.json();
return data;
}
and the api looks like this (in api/index.js file):
const rp = require('request-promise');
const apiKey = process.env.POLICY_API_KEY;
export default function (req, res, next) {
if (req.url.includes("/info")) {
let stateAbbr = req.originalUrl.slice(-2);
rp({
uri: `https://third-party-api-here.com/states/${stateAbbr}/`,
method: 'GET',
headers: {
'token': apiKey,
},
json: true
}).then(function success(response) {
if (response) {
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify(response));
return;
}
}).catch(function error(response) {
console.log('error', response.error);
});
return;
}
next();
}
I think this might have something to do with CORS? I'm getting this error in the browser when I try to hit that route in the deployed app:
GET https://my-app-name.netlify.app/api/info/MN 404
SyntaxError: Unexpected token < in JSON at position 0
As mentioned in the comment above, you need to have a Node.js of some sort.
Hence, hosting on Heroku fixed OP's issue (Netlify is only for static files).

Stripe webhooks error "No signatures found matching the expected signature for payload"

Been stuck on this error for a while now and I've followed stripes documentation and express example on github, but still have no success.
I am using express in Firebase functions:
export const app = express();
/* -------------------------------------------------------------------------- */
/* Middleware */
/* -------------------------------------------------------------------------- */
app.use(cors({ origin: true }));
app.use(favicon(__dirname + '/public/favicon.ico'));
app.use(helmet());
app.use(
(
req: express.Request,
res: express.Response,
next: express.NextFunction
): void => {
functions.logger.log('ORIGINAL URL:', req.originalUrl);
if (req.originalUrl === '/stripe/webhooks/account/update') {
functions.logger.log('THIS IS THE WEBHOOK, USING RAW');
next();
} else {
express.json({ strict: false })(req, res, next);
}
}
);
// #####################################################################
app.post(
'/stripe/webhooks/account/update',
express.raw({ type: 'application/json' }),
(req: express.Request, res: express.Response): void => {
functions.logger.log('IN STRIPE ACCOUNT UPDATE WEBHOOK');
const sig = req.headers['stripe-signature'];
let event: Stripe.Event;
try {
event = stripe.webhooks.constructEvent(
req.body,
sig,
functions.config().stripe.webhooks.account.update.test
);
} catch (err) {
const message = `❌ Webhook Error: ${err.message}`;
functions.logger.error(message);
res.status(400).send(message);
return;
}
functions.logger.log('STRIPE WEBHOOK EVENT: ', event);
// Handle the event
switch (event.type) {
case 'account.updated': {
const account = event.data.object;
console.log(account);
// Then define and call a function to handle the event account.updated
break;
}
default:
functions.logger.error(`🤷‍♀️ Unhandled event type ${event.type}`);
}
// Return a 200 res to acknowledge receipt of the event
res.send();
}
);
The console logs from the above end up as:
2022-04-15T14:16:01.457790660Zapincqt400t2dxo Function execution started
Info
2022-04-15T14:16:01.492Zapincqt400t2dxo ORIGINAL URL: /stripe/webhooks/account/update
Info
2022-04-15T14:16:01.492Zapincqt400t2dxo THIS IS THE WEBHOOK, USING RAW
Info
2022-04-15T14:16:01.494Zapincqt400t2dxo IN STRIPE ACCOUNT UPDATE WEBHOOK
Error
2022-04-15T14:16:01.498Zapincqt400t2dxo ❌ Webhook Error: No signatures found matching the expected signature for payload. Are you passing the raw request body you received from Stripe? https://github.com/stripe/stripe-node#webhook-signing
Debug
2022-04-15T14:16:01.512803969Zapincqt400t2dxo Function execution took 55 ms. Finished with status: response error
I have also console logged my stripe webhook secret to ensure its there and it is correct.
Further more I have hardcoded the secret and still have the same result.
Does anyone see any problems here?
This is a common issue. If you're sure the secret is correct, then something is modifying the inbound request body. You need the raw body. Take a look at this Github issue for common solutions.

Axios returns a response code of 400 when making Basic Authentication

I am trying to get an acesss token from an api endpoint in postman using the basic authentication flow.
app.post('/epic', async (req:Request, res) => {
const code = req.query.code as string
const url = "https://api.epicgames.dev/epic/oauth/v1/token"
const values = new URLSearchParams({
code,
client_id,
client_secret,
scope: "basic_profile",
grant_type: "authorization_code",
})
console.log(code, values)
try {
const res = await axios.post(url, values, {
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
})
console.log(res.data)
return res.data
} catch (error: any) {
console.error(error.message)
throw new Error(error.message)
}
})
It keeps returning a 400 bad request. am i doing something wrong?
UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch()
req.query gives you the query parameters in the URL (e.g. https://www.somewebsite.com/api?code=supersecretcode), whilst in postman you're providing it as the body of the request. You can go about this two ways:
Use query parameters in the URL instead of in the body in your postman request - this is as simple as moving everything that's in your request body to the URL (http://localhost:4000/epic?code=supersecretcode&grant_type=authorization_code&scope=basic_profile)
Parse the request body in your server. I'm using the helpful body-parser package in this example:
const bodyParser = require("body-parser")
app.use(bodyParser.urlencoded({ extended: false })
app.post('/epic', async (req: Request, res) => {
const { code } = req.body
const url = "https://api.epicgames.dev/epic/oauth/v1/token"
const values = new URLSearchParams({
code,
client_id,
client_secret,
scope: "basic_profile",
grant_type: "authorization_code",
})
// ...
})

How do I connect service to a Cloud Foundry app?

I'm new to IBM cloud and I'm trying to build an application where I can write a text, press a button and that text is analysed by the service tone analyser returning a JSON so I can show it.
I have created an instance of said service and I have connected it to my application (a toolchain) using the 'connections' tab on the service.
I also have this code on the app.js file on my app:
const ToneAnalyzerV3 = require('ibm-watson/tone-analyzer/v3');
const { IamAuthenticator } = require('ibm-watson/auth');
const toneAnalyzer = new ToneAnalyzerV3({
version: '2019-10-10',
authenticator: new IamAuthenticator({
apikey: [API key found in service credentials],
}),
url: [API url found in service credentials],
});
app.get('/', function(req, res) {
res.render('index');
});
app.post('/api/tone', async function(req, res, next) {
try {
const { result } = await toneAnalyzer.tone(req.body);
res.json(result);
} catch (error) {
next(error);
}
});
The problem is that when I make the following call on my javascript:
$.post( "/api/tone", {text: textInput}, function(data){
console.log(data);
});
I get the error: 500 (Internal Server Error).
Does anybody know what I am doing wrong?
The issue is that you are sending req.body to be analysed for tone. If you take a look at the API Docs - https://cloud.ibm.com/apidocs/tone-analyzer?code=node#tone - you will see that you only need to send
const toneParams = {
toneInput: { 'text': text },
contentType: 'application/json',
};
I doubt very much that req.body has a toneInput field, and if it does have contentType it may not be set to one of the allowable values.

How to send request from Express server to another server?

I am trying to fetch data from Express server from another external server.
That is search api, which is post request and I am from client get body params.
Then try to send that params on another server:
http://search-api.com/d/explore?
public static async search(req: Express.Request, res: Express.Response) {
try {
const data = await axios.post(
`http://search-api.com/d/explore?user_id=${
req.body.id
}`,
{
query: req.body.query,
topics: req.body.topics
}
);
res.send(data);
} catch (err) {
ErrorHandler.handle('Error fetching search response.', err, res);
}
}
This is response Error:
[ERROR] default - "Error fetching search response."
Error: Request failed with status code 422
I was check params exist and they are ok.
Does anyone have idea what can be the problem here?
UPDATED:
This is how body of request should looks:
Probably you have forgot about http:// protocol on beginning; also, you have wwww instead of www, but I assume that it's just dummy text there:
public static async search(req: Express.Request, res: Express.Response) {
try {
const data = await axios.post(
`http://www.search-api.com/d/explore?user_id=${
req.body.id
}`,
{
query: req.body.query,
topics: req.body.topics
}
);
res.send(data);
} catch (err) {
ErrorHandler.handle('Error fetching search response.', err, res);
}
}

Categories

Resources