I want to insert data into a SQL Server database with nodejs API but I cannot send data from react-native. Data is not come to web API I tried axios.post and fetch method, I couldn't do this. What am I doing wrong? Could you help me?
This is my NODE JS WEB API:
app.post("/insert", function(req, res) {
(async function insert(ProName,ProDesc,OnDate) {
try {
let pool = await sql.connect(sqlConfig);
const request= pool.request();
request.input("ProName", sql.VarChar, ProName)
request.input("ProDesc", sql.VarChar, ProDesc)
request.input("OnDate", sql.VarChar, OnDate)
request.query('INSERT INTO Producttbl
(ProName,ProDesc,OnDate) VALUES(#ProName,#ProDesc,#OnDate)',
React native code:
state = {ProName:'',ProDesc:'',OnDate:''};
insert= () =>{
const {ProName,ProDesc,OnDate}=this.state;
axios({
method: 'post',
url: 'url/insert',
data: {
ProName,
ProDesc,
OnDate
},
}).then(response =>
this.setState({
ProName:response.ProName,
ProDesc:response.ProDesc,
OnDate:response.OnDate
});
})
<TextInput onChangeText={(ProName)=>this.setState({ProName})} />
JSON:
https://i.stack.imgur.com/zEwn2.png
Related
I'm using ReactJS to run my front-end and using Express for my back-end. I want to make a get request to my back-end using the "/paas" path to get a listing of all of my pods that are running inside my namespace in Rancher(Kubernetes).
The back-end then needs to be able to make an https request to my Rancher API endpoint and return the result to the front-end. I can make the successful call to Rancher API and see the data print to the screen on my back-end but I get lost when trying to send this data to the front-end and console log it out inside the browser.
Due to "pre-flight" errors, I can't just make a direct call to the Rancher endpoint inside of my App.js file. More info on this here. So I need to go the custom back-end route. I any case, it seems like this should be pretty straightforward. Any guidance would be appreciated.
App.js:
import React, { useEffect } from "react"
import axios from "axios"
function App() {
useEffect(() => {
const fecthPods = async () => {
try {
const response = await axios.get(`http://localhost:3001/paas`)
console.log(response.data)
} catch (err) {
if (err.response) {
// Not in the 200 response range
console.log(err.response.data)
console.log(err.response.status)
console.log(err.response.headers)
} else {
console.log(`Error: ${err.message}`)
}
}
}
fecthPods()
},[])
return (
<div>
Hello World!
</div>
);
}
export default App;
Back-end server.js:
import express from "express"
import cors from "cors"
import https from "https"
import bodyParser from "body-parser";
const app = express()
app.use(cors())
app.use("/data", (req, res) => {
res.json({ name: "Minion", favFood: "pizza"})
})
app.get("/paas", bodyParser.json(), (req, res) => {
const options = {
hostname: "k8.fqdn.com",
port: 443,
path: "/k8s/clusters/c-wwfc/v1/pods/mynamespace",
method: "GET",
headers: {
Authorization: "Bearer token:12345"
}
}
const request = https.get(options, (res) => {
let responseBody = ""
res.setEncoding("UTF-8")
res.on("data", (chunk) => {
console.log("---chunk", chunk.length);
responseBody += chunk;
});
res.on("end", () => {
let json = JSON.parse(responseBody)
// console.log(responseBody)
console.log("Response finished");
res.json({data: responseBody})
});
});
request.end()
res.json({ status: "complete", data: request.data})
})
app.listen(3001)
console.log("backend up on 3001")
I see a couple of errors on your backend code.
First, you are naming the res variable for the express middleware and also for the response received by the https module. In this way, you lose the possibility to access to the express response object in the on.('end') callback.
Secondly, you are triyng to respond to the client multiple times (inside the on.('end') callback and also directly inside the express middleware with the instruction res.json({ status: "complete", data: request.data}). Also, consider that the code you wrote is repliyng to the client before the call to the k8s cluster is made. And the response will always be a JSON with this data: { "status": "complete", "data": undefined}.
To fix all, try with this code (I will try to comment all edits):
app.get("/paas", bodyParser.json(), (req, res) => {
const options = {
hostname: "k8.fqdn.com",
port: 443,
path: "/k8s/clusters/c-wwfc/v1/pods/mynamespace",
method: "GET",
headers: {
Authorization: "Bearer token:12345"
}
}
const k8sRequest = https.get(options, (k8sResponse ) => { // as you can see I renamed request and res to k8sRequest and k8sResponse, to avoid loosing the scope on req and res express middleware variables
let responseBody = ""
res.setEncoding("UTF-8")
k8sResponse.on("data", (chunk) => { // here use k8sResponse to collect chunks
console.log("---chunk", chunk.length);
responseBody += chunk;
});
k8sResponse.on("end", () => { // here use k8sResponse again
let json = JSON.parse(responseBody)
// console.log(responseBody)
console.log("Response finished");
res.json({ status: "complete", data: responseBody}) // here use the express res variable, to reply to the client.
});
});
k8sRequest.end() // here use the k8sRequest variable to make the https call to the k8s cluster
// here I deleted the res.json instruction
})
The above code should just works. Anyway, I suggest you using axios also with your backend service. You are already using it with React, so you know how to use it. The syntax is minimal and easier and you can use the async/await approach.
Axios solution:
import axios from "axios"
app.get("/paas", bodyParser.json(), async (req, res) => {
try {
const url = 'https://k8.fqdn.com/k8s/clusters/c-wwfc/v1/pods/mynamespace'
const k8sResponse = await axios.get(url, headers: {
Authorization: "Bearer token:12345"
})
res.json({ status: "complete", data: k8sResponse.data })
} catch (e) {
res.json({status: "error", data: e.response.data})
}
})
You should wrap your axios call inside a try/catch block to properly handle errors like you are doing with your React implementation. Error handling should be also implemented if you still want you the native node.js https module
I have an Angular Universal app. I am trying to access an external API, but doing it directly through the HttpClient generates a Cors error. In development, I successfully used a proxy to make the call. I am trying to implement a proxy in production by creating a route on my express server that will swap in the appropriate external API route. I am having trouble seeing anything online that can help with this particular situation. I seem to have set up the route ok. I'm getting a 200 ok error but no data is being sent. Can anyone help?
server.ts
app.route('/api/book').get((req, res) => {
https.get('https://api2.isbndb.com/book/' + req, (resp) => {
let data = '';
// A chunk of data has been recieved.
resp.on('data', (chunk) => {
data += chunk;
});
// The whole response has been received. Print out the result.
resp.on('end', () => {
res.send(res.json(data)
);
});
}).on("error", (err) => {
console.log("Error: " + err.message);
});
});
You can simply enable cors from your server side like this.
var express = require('express')
var cors = require('cors')
var app = express()
app.use(cors())
For better understanding or to configure cors() url through.
can see here.
As by default it will call the options method to check the permission for the user to access that end points.
or you can use below example from client side api call,
let data = { name: 'Peter Parker', age: 34 };
const results = await fetch(
'http://localhost:3000/api/v1/results',
{
method: "post",
mode: "cors",
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*"
},
body: JSON.stringify(data)
}
)
.then(res => res.json())
.then(res => {
return res;
})
.catch(error => {
error.response = {
status: 0,
statusText:
"Cannot connect. Please make sure you are connected to internet."
};
throw error;
});
I am creating an app with login and registration functionality with React and Express. I am using Formik to handle the form data as well as to post it:
> const initialValues={{username:"", email:"", password:""}}
onSubmit ={ async (values, { setSubmitting }) => {
const value = values.username+'/'+values.email+'/'+values.password;
const res = await fetch(`http://localhost:5000/newuser/${value}`, {
method: 'GET',
mode: 'cors',
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
}}).then(response => response.json());
console.log(res);
values = initialValues;
setSubmitting(false);
}
This is then sent to the express application to the following route:
> app.get('/newuser/:username/:email/:password', (req, res) => {
const username = req.params.username;
const email = req.params.email;
const password = req.params.password;
let sql = `Insert into users (username, useremail, userpass) values ('${username}', '${email}', '${password}')`;
query = db.query(sql, (err, results) => {
if(err){throw err;}
res.send("New user added you can login now");
});
});
I am able to save these users to the database however I have the following 2 questions about this code, which I was able to piece together from various different videos, tutorials, questions and docs:
With regards to this line:
app.get('/newuser/:username/:email/:password', (req, res)
This is the only way I can get the form data into express, if I do not include the semi-colons and call these values using req.params, I get a "404 not found error" because the 3 values are empty. If I try and access them via req.body they still appear to be empty. I have tried to JSON.stringify them and I am using body-parser in the express app. My question is how can I access these 3 values(username, email, password) with req.body? Also is there a specific way I should format them if I want access this route from my browser, for example http://localhost:5000/users?username&email&password
How can I send a response back to the react app to tell it for example that the user exists and the password is correct? I have already made the mysql query that checks this and updates a variable in express I just need to then send the response, perhaps the value of that variable that will then tell react to go to the index page. However res.send(variable) does not seem to be sending the variable to react and the login form stays stagnant after it is submitted.
To access the body use method:"POST" rather than GET.
let response = await fetch(`http://localhost:5000/newUser`, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(values),
})
if (response.errors) {
console.error(response.errors)
}
let responseJson = await response.json()
if (responseJson['message']) {
console.log(responseJson['message'])
}
Server side use something like this:
import cors from 'cors'
...
let app = express()
.use(cors())
.post('/newUser', (req, res) => {
let {username, email, password} = req.body
...
// If all ok
res.status(200).send({message: "User created"})
// If there's an issue
res.status(500).send({message: "oups"})
})
...
I recently implemented a schema and some resolvers for my Express server. I tested them successfully through /graphql and now I would like to call the queries I implemented when accessing from a REST API, like so:
//[...]
//schema and root correctly implemented and working
app.use('/graphql', graphqlHTTP({
schema: schema,
rootValue: root,
graphiql: true,
}));
//I start the server
app.listen(port, () => {
console.log('We are live on ' + port);
});
//one of many GET handlers
app.get("/mdc/all/:param", function(req, res) {
//call one of the (parametrized) queries here
//respond with the JSON result
});
How can I call the queries I defined with GraphQL inside my GET handlers? How do I pass parameters to them?
Thank you!
Basically you can just use http post method to fetch the data from a GraphQL API, but here very nice solution using node-fetch , to install it:
npm install node-fetch --save
and the code to use it is:
const fetch = require('node-fetch');
const accessToken = 'your_access_token_from_github';
const query = `
query {
repository(owner:"isaacs", name:"github") {
issues(states:CLOSED) {
totalCount
}
}
}`;
fetch('https://api.github.com/graphql', {
method: 'POST',
body: JSON.stringify({query}),
headers: {
'Authorization': `Bearer ${accessToken}`,
},
}).then(res => res.text())
.then(body => console.log(body)) // {"data":{"repository":{"issues":{"totalCount":247}}}}
.catch(error => console.error(error));
this solution was taken from here
You can use graphql-request.
import { request, GraphQLClient } from 'graphql-request'
// Run GraphQL queries/mutations using a static function
request(endpoint, query, variables).then((data) => console.log(data))
// ... or create a GraphQL client instance to send requests
const client = new GraphQLClient(endpoint, { headers: {} })
client.request(query, variables).then((data) => console.log(data))
I've got an existing working test that is testing a route in an Express app (trimmed code):
const AWS = require('aws-sdk-mock');
const AWS_SDK = require('aws-sdk');
AWS.setSDKInstance(AWS_SDK);
...
before(() => {
sendEmailMock = sinon.stub().callsArgWith(1, null, 'All is well');
AWS.mock('SES', 'sendEmail', sendEmailMock);
server = rewire('../../../..');
...
describe('POST:/feedback', () => {
it('Returns 200 with a fully formed request', (done) => {
request(app)
.post('/gethelp/api/v1/feedback')
.send({
thumbsUp: 'true',
title: 'Abcdef ghi',
url: 'http://google.com',
comments: 'lkajsdj lkajsdkjf aslkjdfa asjdflasjd lkfj',
})
.expect(200, () => {
const args = sendEmailMock.args[0][0];
... etc
This is a working test. But I need to refactor it to not use the full server (because it's doing some integration stuff on startup). So I'm bringing in node-mocks-http:
const httpMocks = require('node-mocks-http');
const feedbackRouteHandler = require('./feedback');
...
before(() => {
sendEmailMock = sinon.stub().callsArgWith(1, null, 'All is well');
AWS.mock('SES', 'sendEmail', sendEmailMock);
});
...
const mockRequest = httpMocks.createRequest({
method: 'POST',
url: '/gethelp/api/v1/feedback',
body: {
thumbsUp: 'true',
title: 'Abcdef ghi',
url: 'http://google.com',
comments: 'lkajsdj lkajsdkjf aslkjdfa asjdflasjd lkfj',
},
});
const mockResponse = httpMocks.createResponse();
feedbackRouteHandler(mockRequest, mockResponse);
expect(mockResponse.statusCode).to.equal(200);
expect(sendEmailMock.args).to.exist;
The problem is that adding in node-mocks-http appears to have broken the mocking of the AWS SDK. When sendEmail is hit it's hitting the actual AWS SDK, not the mocked version. It was hitting the mocked version in the previous version of the test.
How can I use node-mocks-http with aws-sdk-mock?