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
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).
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.
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",
})
// ...
})
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.
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);
}
}