Passing JSON data in Express Middleware - node.js

I have the following route in my express app:
app.post("/users/me/trackers/court_cases", caseValidator, DriversController.court_cases);
I would like to be able to pass information from my second middleware, caseValidator, to the third set of middleware. The second middleware currently fetches JSON data from a RESTful API, that I would like to pass along to the final route before sending it to the user.
Here's my current case validator function:
caseValidator = function(req, res, next){
var case_id = req.body.case_id;
var authOptions = {
method: 'GET',
url: `https://www.courtlistener.com/api/rest/v3/dockets/${case_id}/`,
headers: {
'Authorization' : "myauth"
},
json: true
};
var url = `https://www.courtlistener.com/api/rest/v3/dockets/${case_id}/`
axios(authOptions)
.then((response) => {
console.log("success!")
next();
//// Pass in the JSON data to the next middleware?
})
.catch((error) => {
res.status(400)
.send(error)
});
};

you can use req.someVar.
axios(authOptions)
.then(response => {
console.log("success!");
req.someVar = response.data;
next();
})
then in next middleware you have access to that data.

Related

React NextJs: how to render a page after fetching data to the server-side?

Usually, I send the data in react to the server-side like this:
e.preventDefault();
await fetch(process.env.NEXT_PUBLIC_DR_HOST, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: body,
}).then(res =>
{
window.location = res.url;
})
And if there is an error within the sent data, a 400 error is thrown and the request is sent to the error middleware:
server.use((err, req, res, next) =>
{
const error = new ServerError(err.message, err.status)
res.status(error.status)
res.redirect("/create") //this could be anything
})
As you might guess the code above works fine. But what if I want to render something instead of redirect to another url?
server.use((err, req, res, next) =>
{
const error = new ServerError(err.message, err.status)
res.status(error.status)
app.render(req, res, "/error", { error }) //replaced readirect with app.render
})
Rendering a page leads to no response .then(res =>{ window.location = res.url }) and the page remains untouched. How can I create something similar to the redirect method but with app.render instead?

How do I call a different REST API within a express route?

I have an express.js REST API that I have created with a variety of routes. I'd like to create a route to call another REST API and then return the result. Ideally, it should look something like the following:
router.post('/CreateTicket', cors(corsOptions), function(req, res, next) {
//make a call to another rest api and then res.send the result
}
The REST API route that I am calling is a POST request and will take in a JSON body with the information for the ticket. It then will return a JSON response containing the ticket information and ticket link.
Essentially, I just want to pass req.body as the body of the API call and then res.send() the response of the API call. I was trying to figure out some way to use fetch or requests, but was just getting confused.
Thank you so much for any help that anyone can offer!
I would suggest to use axios if you want to call the third-party API. The simple way of doing is to create an options(config) pass it to the axios object.
npm i axios --save
Axios config
const options = {
'method': 'POST',
'url': 'https://URL',
'headers': {
'Content-Type': 'application/json'
},
data: {
firstName: 'Fred',
lastName: 'Flintstone'
}
};
try {
const result = await axios(options);
console.log(result);
} catch (e) {
console.log(e);
}
In your route file:
const axios = require('axios');
const getData = async (body) => {
const options = {
'method': 'POST',
'url': 'https://URL',
'headers': {
'Content-Type': 'application/json'
},
data: {
body
}
};
try {
const result = await axios(options);
console.log(result);
return result;
} catch (e) {
console.log(e);
}
}
router.post('/CreateTicket', cors(corsOptions), async function(req, res, next) {
//make a call to another rest api and then res.send the result
try {
const response = await getData(req.body);
res.send(response);
} catch (e) {
//wrap your error object and send it
}
}
Note: if you want to pass the data to your own created route you can use res.redirect and it will send the response back. You can check the axios details in the link above.
You would have to use something like axios or http (code originates from link):
const https = require('https')
const options = {
hostname: 'example.com',
port: 443,
path: '/todos',
method: 'GET'
}
const req = https.request(options, res => {
console.log(`statusCode: ${res.statusCode}`)
res.on('data', d => {
return d
})
}

Reactjs axios post response is not returning anything

I'm using axios.post() to edit a mysql database on the back end of my Reactjs app. The data gets through the post request to the back end fine. But I need to know when the post request finished and return some data from it to know if what the back end code ran worked correctly. I've tried the following where newEdit is an object with the information that's need in the back end
axios
.post('http://ip:3001/edit_table', newEdit)
.then((response) => {
console.log("response: ",response);
}, (error) =>{
console.log("error: ",error)
});
Neither of the console log statements get ran. Once again, the object does get to the routed nodejs file fine, I am just unable to get any kind of response. Anyone know what's happening? thanks.
if your backend code is OK and return response then you can following below example that works perfectly.
const updateData = async () => {
try {
const response = await axios.put(`https://jsonplaceholder.typicode.com/posts/${id}`, {
method: 'PUT',
body: JSON.stringify({
id: id,
title: post.title,
body: post.body,
userId: 1
}),
headers: {
"Content-type": "application/json; charset=UTF-8"
}
})
.then(response => response.json())
.then(json => console.log(json));
console.warn(response.data);
} catch (error) {
console.warn(error);
}
};
Make sure that your backend is returning a response to the client.
You can either use res.send or res.json. res.send([body]) is used to send HTTP response to the client while res.json(body) is used to send JSON response.
res.send([body])
res.send(new Buffer('whoop'));
res.send({ some: 'json' });
res.send('<p>some html</p>');
Example:
var express = require('express')
var app = express()
app.get('/', function (req, res) {
res.send('hello world')
})
app.listen(3000)
res.json([body])
res.json(null)
res.json({ user: 'tobi' })
res.status(500).json({ error: 'message' })
Example:
var express = require('express')
var app = express()
app.get('/', function (req, res) {
res.json({ success: true })
})
app.listen(3000)
References:
Express API reference
Node.js response object methods res.send and res.json

Indexing user query with Appbaseio and ReactiveSearch

I'm attempting to index a user's query using ReactiveSearch's DataSearch component and appbase-js.
So I've made my Node/Express app for appbase-js interaction with appbaseio.
in app.js:
...
const search = require('./routes/search');
...
app.use('/api/search', search);
Then here is my search.js
const express = require('express');
const Appbase = require('appbase-js');
// create an appbase.io app's instance
const appbaseRef = new Appbase({
url: "https://scalr.api.appbase.io",
app: "index-query",
credentials: "####-####"
});
const router = express.Router();
/* GET search. */
router.get('/test', (req, res, next) => {
res.send('This is the SEARCH route - and it WORKS!');
});
router.post('/query', (req, res, next) => {
appbaseRef.index({
type: "autocomplete",
body: value
}).then('data', response => {
console.log("#index success: ", response);
}),('error', error => {
console.log("#index error: ", error);
});
});
module.exports = router;
Then here is my DataSearch component:
<DataSearch
componentId="SearchSensor"
dataField={["suggestions"]}
className="search-bar"
iconPosition="right"
innerclassName={{
list: "text-item"
}}
onValueSelected{
(value) => {
????
}
}
/>
I was advised in another question not do this:
onValueSelected={(value) => {
fetch('YOUR_SERVER_URL' or 'Elasticsearch URL', { method: 'POST', body: {...} })
}
So as not to expose sensitive information on the client
I'm not sure how to get value (the user's query) from my React front end to my Node/Express backend so that it can be indexed to ES app on Appbaseio?
Say your server is hosted at 'SERVER_URL', the key is to send the data from the frontend to the server via a fetch request:
<DataSearch
...
onValueSelected={(value) => {
fetch('SERVER_URL/api/search/query', {
method: 'POST',
body: JSON.stringify({ value })
}).then(() => handle response client side))
}}
/>
Then you can add the body-parser middleware in express.
app.use(bodyParser.json())
In your route you can use the value from body and index it to elasticsearch. You can use the index method from appbase-js which you're using here.
router.post('/query', (req, res, next) => {
appbaseRef.index({
type: "autocomplete",
body: { value: req.body.value }
}).then('data', response => {
console.log("#index success: ", response);
}),('error', error => {
console.log("#index error: ", error);
});
});

POST request to restify with Fetch API not working

I'm having some major problems understanding why the Fetch API won't let me send a POST request to my restify server.
I have a basic restify server with a route that receives POST requests on /login.
This route works perfectly as intended if I test with Postman or HTTPRequester, but when I then test it on a browser application with the fetch API, I get the following error (in Chrome):
OPTIONS http://localhost:1337/login 405 (Method Not Allowed)
Fetch API cannot load http://localhost:1337/login. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. The response had HTTP status code 405. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
Two issues
I specifically use the POSt method in my request, so why suddenly OPTIONS?
I've already set Access-Control-Allow-Origin: * on my server.
EDIT: I use restify v5.2.0
My server app:
const restify = require('restify');
const app = restify.createServer({
'name': 'API Token Test',
'version': '1.0.0'
});
app.use(restify.plugins.acceptParser(app.acceptable));
app.use(restify.plugins.bodyParser());
app.use(restify.plugins.jsonp());
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', 'X-Requested-With');
return next();
});
app.post('/login', (req, res) => {
db.execute('SELECT idusers, password FROM users WHERE username = ?', [req.body.username], (selError, rows) => {
if (passwordHash.verify(req.body.password, rows[0].password)) {
crypto.randomBytes(256, (err, buf) => {
if (err) return res.status(500).end();
else {
const token = buf.toString('hex');
db.execute('INSERT INTO accesstokens SET userid = ?, token = ?', [rows[0].idusers, token], (insError) => {
if (insError) return res.status(500).end();
else return res.send({ "AccessToken": token });
});
}
});
} else {
res.status(401).end();
}
});
});
app.listen(1337);
(I've left out mysql stuffs and crypto/password-hash -requires, which are irrelevant to the problem)
And my clientside script:
(() => {
document.addEventListener('DOMContentLoaded', () => {
const form = document.querySelector('.loginForm');
form.onsubmit = () => {
const data = JSON.stringify({
'username': form.username.value,
'password': form.password.value
});
let headers = new Headers();
headers.set('Accept', 'application/json');
headers.set('Content-Type', 'application/json');
headers.set('Content-Length', data.length);
fetch('http://localhost:1337/login', {
'method': 'POST',
'headers': headers,
'mode': 'cors',
'cache': 'default',
'body': data
})
.then((result) => result.json())
.then((data) => {
console.log(data);
localStorage.setItem('token', data);
})
.catch((err) => {
console.log(err);
});
return false;
};
});
})();
Appears all CORS support has been moved to this module since restify v5.x.
Installing restify-cors-middleware and adding the following to my app worked:
const corsMiddleware = require('restify-cors-middleware');
const cors = corsMiddleware({
'origins': ['*']
});
app.pre(cors.preflight);
app.use(cors.actual);

Resources