Indexing user query with Appbaseio and ReactiveSearch - node.js

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);
});
});

Related

How to make a request and return a response with Express in Node.js?

I trying to send a request to an api and return the response with express when someone curl my site.
app.post('/', async (req, res) => {
request.get('the_api')
.on('response', function(resp){
return res.status(200).send({
text: resp.body
})
})
})
For that requirement, in my projects I use axios, from the documentation:
Axio is a promise based HTTP client for the browser and node.js.
Here is a complete example:
const axios = require('axios');
// api openexchange
const oexchange = axios.create({
baseURL: 'https://openexchangerates.org/api/',
timeout: 60000
})
oexchange.interceptors.request.use((config) => {
config.params = config.params || {};
config.params.app_id = 'myapitoken'
return config;
});
app.get('/', async (req, res) => {
try {
//here it will request:
//https://openexchangerates.org/api/latest.json?app_id=myapitoken
req.oexchange = await oexchange.get('latest.json')
return res.status(200).json(req.oexchange.data)
} catch (e) {
res.status(500).json({ errors: [{ location: 'cotacao', msg: 'Houve um erro ao acessar a api do open exchange.', param: 'openexchangerates' }] })
}
})
In my example I am requesting an external exchange api.
Here is the documentation from axios.
Hope it helps.

Blob Objects sent through Axios are empty in Express

I'm sending a Blob Object created in VueJS to ExpressJS via Axios.post.
But if I send the BlobObject itself via Axiox, I can check it in req.body, but if I send it from ExpressJS to an object that wraps the Blob Object via Axios in order to get it in the form of const {blob} = req.body, ExpresJS BlobObject is empty.
How can I solve this?
Blob Object in Vue Component
Blob {size: 42003, type: ""}
size: 42003
type: ""
__proto__: Blob
Send Blob Object (Axios & Express) 1
// Vue Component
axios.post(`http://localhost:3000/blob`, this.blobObject)
.then(
(response) => {
console.log('Successfully Save API')
},
(err) => {
console.error(err)
}
)
// Express Router
router.post('/blob', (req, res, next) => {
...
console.log(req.body)
})
// req.body
{ "PK\u0003\u0004\n\u0000\u0000\u0000\b\u0000'\u0015\u001aO����%\u0003\u0000\u0000�\u0006\u0000\u0000\f\u0000\u0000\u0000project.json�TA��D\u0014�+�pٕR��3\u001e��\u0001�\u0015\u0005�\u00
16$vEAU%�3ϩ��Ɠ4�\u0012\t!\u000e��\u0004h/{�8U�\u0001�������a�R5T�K���{o�����8iG�:2|pB����\u0011���S\u0018�V6h�ul#f�V��\u0001sO�ǟ�9~�Z": 'x�����l���F�\b6I؏�~�:;\r��l��)\u0019Ї�\u0001���\u001fv�fa��J^��Q�K[��
�v�EM�E��tn�!Q���kܲ����\u0011��q�D\\ӄE�.�"�cʁ�J#g\\���:�쏟~\u000f"�4:���\u0017�a7\u001ba��N�6���f\u001d��IW��\u0010a���\fcN�G?"�(�ˇ\u0003ҙi��CϘ��,�\\\u0015�dE*X\\p�K(ʔ3�^A����:��r��r�zD�a.�(E �l','5\u001c��5�b�5��sC�ۣ���g?�\u001dk�\u0000���`��p�L\f\u0019\n4g�\u0006sle�M$ޚZ�a�\t��<*bZ�k���\u001cM\u0000ԣ��\u001dM{�Ӻ^\u000e��Xʺ�\u0012����\u0017�|q~�|u����_���\u0016��/�"�\u0012V':
'',
....
....
}
Send Blob Object (Axios & Express) 2
// Vue Component
axios.post(`http://localhost:3000/blob`, { "blob": this.blobObject })
.then(
(response) => {
console.log('Successfully Save API')
},
(err) => {
console.error(err)
}
)
// Express Router
router.post('/blob', (req, res, next) => {
...
console.log(req.body)
})
// req.body
"blob": {} // blobObject is Empty
add HTTP headers with Axios request
axios.post(`http://localhost:3000/blob`,
{ "blob": this.blobObject },
{
headers: {'Content-Type':'application/json'}
})
.then(
(response) => {
console.log('Successfully Save API')
},
(err) => {
console.error(err)
}
)
and make sure you have JSON parser middleware eg (if an app is your express app)
app.use(express.json());

React app on Heroku cannot make a POST request

I+m playing with the Chatkit API, and when running a React app in my local machine everything seems to work fine, but when I pushed it to Heroku, every time it tries to do a POST request through the server, it gives Failed to load resource: net::ERR_CONNECTION_REFUSED and index.js:1375 error TypeError: Failed to fetch
This is my server.js
const express = require('express')
const bodyParser = require('body-parser')
const cors = require('cors')
const Chatkit = require('#pusher/chatkit-server')
const app = express()
const chatkit = new Chatkit.default({
instanceLocator: I HAVE MY INSTANCE LOCATOR HERE,
key: I HAVE MY KEY HERE,
})
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
app.use(cors())
app.post('/users', (req, res) => {
const { username } = req.body
chatkit
.createUser({
id: username,
name: username
})
.then(() => res.sendStatus(201))
.catch(error => {
if (error.error === 'services/chatkit/user_already_exists') {
res.sendStatus(200)
} else {
res.status(error.status).json(error)
}
})
})
app.post('/authenticate', (req, res) => {
const authData = chatkit.authenticate({ userId: req.query.user_id })
res.status(authData.status).send(authData.body)
})
const PORT = 3001
app.listen(PORT, err => {
if (err) {
console.error(err)
} else {
console.log(`Running on port ${PORT}`)
}
})
And then this is my App.js
import React, { Component } from 'react'
import UsernameForm from './components/UsernameForm'
import ChatScreen from './ChatScreen'
class App extends Component {
constructor() {
super()
this.state = {
currentUsername: '',
currentScreen: 'WhatIsYourUsernameScreen'
}
this.onUsernameSubmitted = this.onUsernameSubmitted.bind(this)
}
onUsernameSubmitted(username) {
fetch('http://localhost:3001/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ username }),
})
.then(response => {
this.setState({
currentUsername: username,
currentScreen: 'ChatScreen'
})
})
.catch(error => console.error('error', error))
}
render() {
if (this.state.currentScreen === 'WhatIsYourUsernameScreen') {
return <UsernameForm onSubmit={this.onUsernameSubmitted} />
}
if (this.state.currentScreen === 'ChatScreen') {
return <ChatScreen currentUsername={this.state.currentUsername} />
}
}
}
export default App
I believe that it's at this time that it breaks
return <UsernameForm onSubmit={this.onUsernameSubmitted} />
When submitting it is expected to make a POST request to create a new user, and React to load the new component, but it just stays in the UsernameForm component, and in the console I can see these errors:
Failed to load resource: net::ERR_CONNECTION_REFUSED
index.js:1375 error TypeError: Failed to fetch
Probably the issue is the localhost in the endpoint at onUsernameSubmitted. We need more details about how your application is deployed and how the communication between server and spa is designed. If you have an Nginx you can set the redirect there.
I see three potential reasons of the error:
Database has to be well deployed and db:migrate triggered to define the db schema.
If 1) is fulfilled, then make sure whether your graphql path points to server url my-app.herokuapp.com not to localhost:<port>, The easiest way to check that is via browser/devtools/network query.
(optional) I use ApolloClient and my rule process?.env?.NODE_ENV ? 'prod_url' : 'dev_url' didn't work because of missing vars definitions in webpack:
new DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify(process.env.NODE_ENV),
},
}),```

React - Fetch request not sending content in body

I'm not getting data in body object from fetch request on my server side. I've tried other solutions on SO but nothing is working so far in my case. I'm using Node express on backend and React on frontend.
in component:
addCity = _ => {
const { city } = this.state;
fetch('http://localhost:3003/city_create', {
method: "POST",
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
create_name: city.name,
create_district: city.district,
create_population: city.population
})
})
.then(res => {
console.log(res);
this.getCities;
})
.catch(err => console.log(err))
}
server route:
router.post('/city_create', (req, res) => {
console.log("Trying to create new city...")
const { create_name, create_district, create_population } = req.body;
//debugger
const queryString = "INSERT INTO city (Name, District, Population, CountryCode) VALUES (?,?,?,'PAK')";
getConnection().query(queryString, [create_name, create_district, create_population], (err, rows, fields) => {
console.log(create_name, create_district, create_population);
if (err) {
console.log('A db error occurred:' + err);
res.sendStatus(500);
return;
//throw err;
}
console.log("Inserted a new City with Id: ", rows.insertId);
});
res.end();
});
tried using FormData and accept property in header as well but no luck.
You need to install body-parser module to extract the entire body portion of an incoming request stream and exposes it on req.body.
It was part of express earlier, now we need to install separately.
npm install body-parser --save
and use the middleware as :
app.use(bodyParser.json())

Passing JSON data in Express Middleware

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.

Resources