Paypal Oauth2 Axios results in circular structure - json

I'm trying to get a oauth token from the paypal sandbox using axios. The request looks like this:
const response = await axios.post(
'https://api-m.sandbox.paypal.com/v1/oauth2/token',
new URLSearchParams({
'grant_type': 'client_credentials'
}),
{
auth: {
username: process.env.PP_CLIENT,
password: process.env.PP_SECRET
},
headers: {
'Accept': 'application/x-www-form-urlencoded',
'Accept-Language': 'en_US'
}
}
);
console.log(`response: ${JSON.stringify(response.data)}`);
As far as I can tell this code used to work, because I used it before. However now I'm getting the error:
"Converting circular structure to JSON
--> starting at object with constructor 'ClientRequest'
| property 'socket' -> object with constructor 'TLSSocket'
--- property '_httpMessage' closes the circle"
I have confirmed that my credentials are correct by testing it with curl, which works and by copying it directly into the code. I've also tries fetch (which always yields an empty response)

Related

How to fix: "SyntaxError: JSON.parse: unexpected end of data at line 1 column 1 of the JSON data"

I'm working with React-Native right now, trying to pass formdata to a backend php-file as JSON. But everytime the form is submitted the console shows the following error "SyntaxError: JSON.parse: unexpected end of data at line 1 column 1 of the JSON data". With firefox I checked the request and response under network.
Under request it shows the JSON correctly, under response it shows the JSON correctly. 1 thing that stands out is that under Headers, it says that response Content-Type is text/html and that request Content-Type is text/plain. Could that be causing the issue? I wouldn't know what else to do since I already specify the Content-Type in the code.
Google Chrome says .then(response => response.json()) is causing the error.
await fetch('http://192.168.2.16/React-Native/endpoint.php', {
method: 'POST',
header: {
'Accept': 'application/json',
'Content-type': 'application/json',
},
body: JSON.stringify({
intensiteit: intensiteit,
soortStank: soort,
latitude: lat,
longitude: long,
buurt: neighbourhood,
}),
mode: 'no-cors',
})
.then(response => response.json())
.then(responseJson => {
Alert.alert(JSON.stringify(responseJson));
})
.catch(error => {
console.error(error);
});
The php-file:
$obj = file_get_contents('php://input');
$obj = json_decode($obj, true);
$result['soort'] = $obj['soortStank'];
echo json_encode($result);
And yes I looked at other posts, but they didn't help sadly. I also tried adding dataType: 'json', in there, but that didnt help.
The request from your front-end app to the back-end endpoint is a cross-origin request. Adding mode: 'no-cors' to the fetch request doesn't change this, so remove it to begin with.
Next, the php endpoint must include some header declarations to allow the cross-origin request to succeed.
Add the following to the top of the php file, replacing the http://localhost:9999 part with the origin you are sending the request from. When testing locally, it'll likely be identical apart from the port number. When running in production, be sure to replace it with the correct origin for your front-end app eg. https://www.example-app.com.
header("Allow-Access-Control-Origin: http://localhost:9999");
header('Content-Type: application/json');
This should work.
This is likely a problem of null values.
Replace null values with empty strings in the body.
Perhaps, you also just need to change the php file to:
$obj = file_get_contents('php://input');
$obj = json_decode($obj, true);
$result['soort'] = $obj['soortStank'] ?? '';
echo json_encode($result);

Surfacing query results from AWS RDS to public web page using Lambda, API Gateway and HTTP requests

I am trying to implement an SQL querying interface for an AWS RDS MySQL database in a public web page. Ideally, a user will type a SQL query into a search field, press a "Query" button, and an API Gateway request will trigger a Lambda function to pull, return and print to the web page the relevant data from the database.
So far, I have the following Lambda function (which I am able to successfully test):
const AWS = require('aws-sdk')
const RDS = new AWS.RDSDataService()
exports.handler = async (event, context) => {
console.log(JSON.stringify(event, null, 2)) // Log the entire event passed in
// Get the sqlStatement string value
// TODO: Implement a more secure way (e.g. "escaping") the string to avoid SQL injection
var sqlStatement = event.sqlStatement;
// The Lambda environment variables for the Aurora Cluster Arn, Database Name, and the AWS Secrets Arn hosting the master credentials of the serverless db
var DBSecretsStoreArn = process.env.DBSecretsStoreArn;
var DBAuroraClusterArn = process.env.DBAuroraClusterArn;
var DatabaseName = process.env.DatabaseName;
const params = {
awsSecretStoreArn: DBSecretsStoreArn,
dbClusterOrInstanceArn: DBAuroraClusterArn,
sqlStatements: sqlStatement,
database: DatabaseName
}
try {
let dbResponse = await RDS.executeSql(params).promise()
console.log(JSON.stringify(dbResponse, null, 2))
var json_response = JSON.stringify(dbResponse)
return json_response
} catch (error) {
console.log(error)
return error
}
}
This function, when tested with the following test format, returns a JSON blob I think.
Test event format:
{
"sqlStatement": "SELECT * FROM Table WHERE Name='JOHN DOE'"
}
Test event result:
..., {\"stringValue\":\"JOHN DOE\"},{\"stringValue\":\"2019-11-15\"},{\"stringValue\":\"AL\"},{\"stringValue\":\"1\"},{\"stringValue\":\"130\"},{\"stringValue\":\"Washington Co. Jail\"},{\"stringValue\":\"2019-10-31\"}, ...
I have the following API trigger details configured:
API endpoint: https://****************.amazonaws.com/prod/query
API Type: rest
Authorization: NONE
Method: POST
Resource path: /query
Stage: prod
I also have the following Lambda role configuration policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"secretsmanager:GetSecretValue",
"rds:*",
"rds-data:*"
],
"Resource": "*"
}
]
}
The API, meanwhile, has the following methods/configurations:
Aside from any potential problems in this setup (i.e. the link between the Lambda and the API trigger and the formats of data passed/queried/returned), I need to figure out how to actually call this whole process from the click of a Query button. So, for example, the user would be on the page, type SELECT * FROM Table WHERE Name="JOHN DOE" into an HTML element, click an HTML button "Query", and the process would implement; then, the query result would populate in whatever format (to be simple, a messy string for now, but ideally eventually in a bootstrap DataTable) inside another HTML element.
I currently have a config.js file that contains:
window._config = {
api: {
invokeUrl: 'https://******************.amazonaws.com/prod',
}
};
I also have a query.js file that contains a function (likely incorrect) attempt based on piecemeal tutorials online:
(function DisplayQuery($) {
var query = document.getElementById("sql-placeholder").value;
function passQuery(query) {
$.ajax({
method: 'POST',
url: _config.api.invokeUrl + '/query',
data: JSON.stringify({
sqlStatement: query
}),
contentType: 'application/json',
success: document.getElementById("text-box").innerHTML = result.value,
error: function ajaxError() {
console.error('Error requesting ride');
}
})
}
}(jQuery));
In my index.html file I have these search field and button elements:
<div class="active-cyan-4 mb-4">
<input id="sql-placeholder" class="form-control" type="text" placeholder="Write SQL here..." aria-label="Search">
</div>
<div class="col-md-1">
<button type="button" class="btn btn-primary" onclick="DisplayQuery()">Query</button>
</div>
Finally, this would be the test element where my string-format SQL query results would appear once they'd been returned by RDS --> Lambda --> API Gateway:
<div class="container-fluid">
<p class= "test-box-class" id="test-box"><i>This is a test box for database query connection</i></p>
</div>
This is a lot perhaps, but I'm wondering if anyone has any insight into how to make this process run, at least well enough so that hitting the Query button returns something to the web page.
After following #antonku's answer, The reason for the "Missing Authentication Token" error was, you are trying to access a "POST" http method in the browser, The browser requests URL using the "GET" http method.
You may also get the same error message when the URL is incorrect.
Add some console.log statements to see the api response in the front end
var DisplayQuery;
(function($) {
DisplayQuery = function() {
$.ajax({
method: 'POST',
url: _config.api.invokeUrl + '/query',
data: $('#sql-placeholder').val(),
contentType: 'application/json',
success: function(response) {
console.log('response: ', response);
$('#test-box').text(JSON.stringify(response))
},
error: function ajaxError(error) {
console.error('Error requesting ride');
}
})
}
}(jQuery));
There are a few issues with the code that makes the ajax request.
On button click DisplayQuery is called, however this name is used for the function that is immediately invoked on the initial page load. Instead on the button click you need to invoke the function that sends the ajax request.
The is also no need to JSON.stringify the input value since it's already a string.
Also, for the success key, it's required to provide a function that accepts the response.
Changing query.js in the following way should resolve these concerns:
var DisplayQuery;
(function($) {
DisplayQuery = function() {
$.ajax({
method: 'POST',
url: _config.api.invokeUrl + '/query',
data: $('#sql-placeholder').val(),
contentType: 'application/json',
success: function(response) {
$('#test-box').text(JSON.stringify(response))
},
error: function ajaxError() {
console.error('Error requesting ride');
}
})
}
}(jQuery));

JSON is Malformed in Fetch POST request using React Native

I have a function in a React Native app that is supposed to send data to a server that I'm hosting. This function seems to be throwing errors though every time I press submit and this function is called. The function should be sending a POST request to my webserver and receive information back. It has no problem receiving information but sending is another story... The current code below is giving me an error that says "JSON Parse error: Unrecognized token '<'. But as you can see in my code below I do not even have that symbol present in the 2nd parameter of the fetch function. Occasionally, when I tweak what I have I get an error that also says 'JSON Parse error: Unexpected EOF'. I am not sure how exactly this request is I guess 'malformed'. I am pulling it straight from the docs given by Facebook. I have also tried Axiom & XMLHttpRequest and I am still seeing similar JSON errors. Anyone?
login = () => {
// check if the username is being passed off properly...
//alert(this.state.username);
fetch('MYURL', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
username: this.state.username,
password: this.state.password,
})
})
.then(function(response){ return response.json(); }) // transforms response into data that is readable for this app...
.then(function(data) {
console.log(data);
})
.done();
}
When I shoot that post request in Postman I get back header "Content-Type: text/html; charset=UTF-8". So you don't get json back at all, that's why it doesn't work. I would venture that you have to add the correct application/json header in your backend.

Angular HttpClient post read headers from empty response

I'm trying to build my authentication on JWT. I'm using Spring filters to achieve that goal, and i'm returning positive (200) response with one header (Authorization) on successfull login. Unfortunately i'm still getting JSON parse problem from my Angular client.
Client code:
this.http.post<HttpResponse<void>>(EndPoint.LOGIN,
{'username': username, 'password': password } ,
{'headers' : new HttpHeaders ({'Content-Type' : 'application/json', 'responseType': 'text'})})
.subscribe(response => console.log(response.headers.get('Authorization')))
;
Response:
authorization →Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJHZXJhbHQiLCJleHAiOjE1MjAwNTk4MzN9.813r4QmVgrnrsm4HwZID1M56hD42PLe0BvbCu-bQoQWSnxllOE0iAjS-fc-BI8R8eGGE0WPSSL0OaKxz2lxDjA
content-length →0
Error:
message : "Unexpected end of JSON input"
It is working like a charm from REST client like Postman.
I was trying multiple things to get this done:
set responseType to text
add something to response body (error has changed - it can't parse first letter of new response body)
posting without generic HttpResponse object
No luck for now.
responseType is not a http header, but just an options for the http request
You also need to specify observe: response if you want to be able to retrieve the header
https://angular.io/guide/http#reading-the-full-response
Try that
this.http.post(EndPoint.LOGIN,
{'username': username, 'password': password } ,
{'headers' : new HttpHeaders ({'Content-Type' : 'application/json'}), 'responseType': 'text', observe:'response'})
.subscribe((response : any) => console.log(response.headers.get('Authorization')))
;

Trouble with posting JSON data (with node request) to Express server for saving into MongoDB

I use MongoDB as the back-end database for my node/Express application. To summarize the problem I am facing, I don't know how to set up the body-parser configuration in my Express app, because the server side application is not receiving the full JSON posted by the client application (also a node.js app). For the most part, the client is sending JSON in the request body to RESTful endpoints. The exception being a single case where a file needs to be uploaded and since that is a multipart body, I am using request and form-data to build that type of request and using multer on the server side to process the multipart request, since body-parser does not process such requests.
On the server-side (Express), I have the following configuration of the Express app:
let app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
On the node client, I am using the following code to build up a JSON-style JavaScript object and post it to a RESTful endpoint:
I am having difficulty composing the request on the client side, with node-request:
// class is a JavaScript/JSON object within scope of this code
let req = request.post({
//headers: { 'Content-Type': 'application/json' },
url: 'http://localhost:3000/classes',
//form: class
form: JSON.stringify(class)
}, function (err, resp, body) {
if (err) {
throw err;
}
});
Note that I attempted multiple versions of the above code by explicitly specifying the content type as application/JSON, as well as using JSON.stringify to convert the JavaScript object into a JSON string. The MongoDB collection (class) stores the following type of document, which contains foreign keys to two other collections (subject and student):
{
"_id" : ObjectId("57758f15f68da08c254ebee1"),
"name" : "Grade 5 - Section A",
"scores" : [{
"studentId" : ObjectId("5776bd36ffc8227405d364d2"),
"performance": [{
"subjectId" : ObjectId("577694ecbf6f3a781759c54a"),
"score" : 86,
"maximum" : 100,
"grade" : "B+"
}]
}]
}
In the server logs, I see the following error:
Tue, 05 Jul 2016 04:34:46 GMT classReportApp:routes:classes class received from client: { _id: 577b38e65967097c25876764, scores: [] }
RangeError: Invalid status code: 0
at ServerResponse.writeHead (_http_server.js:192:11)
at ServerResponse.writeHead (C:\Development\classReportApp\node_modules\morgan\node_modules\on-headers\index.js:55:19)
at ServerResponse._implicitHeader (_http_server.js:157:8)
at ServerResponse.OutgoingMessage.end (_http_outgoing.js:566:10)
at ServerResponse.send (C:\Development\classReportApp\node_modules\express\lib\response.js:205:10)
at ServerResponse.json (C:\Development\classReportApp\node_modules\express\lib\response.js:250:15)
at C:\Development\classReportApp\server-process\app.js:80:26
at Layer.handle_error (C:\Development\classReportApp\node_modules\express\lib\router\layer.js:71:5)
at trim_prefix (C:\Development\classReportApp\node_modules\express\lib\router\index.js:310:13)
at C:\Development\classReportApp\node_modules\express\lib\router\index.js:280:7
at Function.process_params (C:\Development\classReportApp\node_modules\express\lib\router\index.js:330:12)
which is strange because scores array of sub-documents is empty (scores: []), whereas on the client side, I am sending a non-empty array with some students' performances elements in it.
Have I violated the right way to post JSON to Express apps? How do I fix this?
Edited: 7/5/2016
I changed the body parser middle-ware configuration to use extended: true instead.
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
The node.js is still using the node-request module to compose and send the POST request, using the following code:
let req = request({
url: 'http://localhost:3000/classes',
method: 'POST',
json: class
}, function (err, resp, body) {
if (err) {
throw err;
}
else {
// process response
}
});
This works now, but what confuses me is that since the content type is application/json, how does the bodyParser.urlencoded({ extended: true }) (or false) matter?
Issue is with form: JSON.stringify(class) in your first request. form takes url encoded form input, stringified json won't work. check content-type header (application/x-www-form-urlencoded)
json: class in your 2nd snippet works as this handles json data and sets correct content type header correctly.
Try .toJSON() method over class before sending.