I want to use a third-party api: Latin WordNet API, but I meet some problems.
The api document shows how to get result by url in browser, but I don't know how to get result by other way.
I try to use axios through HTML script element to get the result, like:
const btn = document.querySelector('#searchBtn')
btn.addEventListener('click', function () {
const options = {
method: 'GET',
url: 'https://latinwordnet.exeter.ac.uk/api/lemmas/virtus/n/'
}
axios(options).then(data => console.log(data))
})
But I get error about CORS. If I use proxy like ngrok, it still doesn't work.
3. I want to try it like normal route, like:
const express = require('express')
const router = express.Router()
router.get('/api/lemmas/virtus/n/', (req, res) => {
console.log(res)
})
I don't know where the result will come from, and I'm also not sure this way is right or false.
Hope anyone may give some tips.
try with GET request:
const options = {
method: 'GET',
url: 'https://latinwordnet.exeter.ac.uk/api/lemmas/virtus/n/'
};
axios(options)
.then(response => console.log(response.data.results))
.catch(err=>console.log(err.response.data));
I found a way to deal with it:
const express = require('express')
const axios = require('axios')
const router = express.Router()
router.get('/search', (req, res) => {
axios.get(`https://latinwordnet.exeter.ac.uk/api/lemmas/${req.query.word}/n/`)
.then(response => {
return res.json(response.data.results)
})
})
combine route and axios
Related
I am trying to pass data to my Node.js backend in order to use it in a get request to an API.
For example:
Server.js
const PORT = 8000
const axios = require('axios').default
const express = require('express')
const app = express()
const cors = require('cors')
app.use(cors())
require('dotenv').config()
app.use(express.json())
app.get('/convertedAmount', (req, res) => {
const contentBody = req.body
const options = {
method: 'GET',
url: 'https://currency-converter5.p.rapidapi.com/currency/convert',
params: {format: 'json', from: contentBody.primaryCurrency, to:
contentBody.secondaryCurrency, amount: contentBody.primaryCurrencyAmount},
headers: {
'x-rapidapi-host': process.env.RAPIDAPI_HOST,
'x-rapidapi-key': process.env.RAPIDAPI_KEY,
},
}
axios
.request(options)
.then((response) => {
res.json(response.data)
})
.catch((error) => {
console.error(error)
})
})
app.listen(PORT, () => console.log(`server running on PORT ${PORT}`))
The issue is, I don't know how to pass data to the backend from the frontend, without making it a POST request. But that doesn't work if I make a POST request to the rapidAPI url. So the backend needs to stay the same.
My question is, how would I write the frontend part for this?
Using a POST request in the frontend sends the data with the req.body, but I cant get the data to display in my browser on localhost:8000/convertedAmount.
Thank you
My attempt is:
Frontend.js
...
axios.post('/convertedAmount', {
primaryCurrency: 'USD',
secondaryCurrency: 'GBP',
primaryCurrencyAmount: 1
})
.then((response) => {
console.log(response);
}, (error) => {
console.log(error);
})
...
You shouldn't be trying to send data in the body (such as in req.body) through a GET request. That is what a POST request is for.
With a GET request, you should pass data (such as a user id) as a parameter. Basically, in the url string.
FRONTEND
axios.get("/convertedAmount/USD/GBP/1")
BACKEND
app.get("/convertedAmount/:primaryCurrency/:secondaryCurrency/:primaryCurrencyAmount", (req, res)=>{
console.log(req.params.primaryCurrency);
console.log(req.params.secondaryCurrency);
console.log(req.params.primaryCurrencyAmount);
});
Alternatively, you could use query strings, which would look like this:
FRONTEND
axios.get("/convertedAmount?primaryCurrency=USD&secondaryCurrency=GBP&primaryCurrencyAmount=1")
BACKEND
app.get("/convertedAmount*", (req, res)=>{
console.log(req.query.primaryCurrency);
console.log(req.query.secondaryCurrency);
console.log(req.query.primaryCurrencyAmount);
});
I'm learning node.js currently and I'm stuck with this problem. I was able to successfully create my node.js server and it works when I run it on the terminal. I even console.log the data I am trying to GET and it shows in the terminal but when I try to load it on Postman, it doesn't show anything.
I use localhost:9001/api but it doesn't load. I don't even get any errors.
Here's my code:
const express = require('express');
const app = express();
const fetch = require('node-fetch');
require('dotenv').config();
const api_key = XXXXXXXXXXX
app.use(express.static('public'));
app.listen(9001, () => console.log('listneing at 9001'));
app.get("/api", async (req,res)=> {
console.log("getting data")
const url = `website.com/vi/api/?alt=json&key=${api_key}`
const options={
"method" : "GET"
};
const response = await fetch(url, options)
.then(response => response.json())
.catch(e => {
console.errror({
"message": "oh no",
error : e,
});
});
console.log(response)
});
Not sure how to solve it can anyone please help a new learner? 🙏
Postman needs a response from your side to show Responses.
The console.log() prints the output on your screen but in order to get response in Postman, You have to return a response like
return res.status(response.code).json(response);
This is my way of returning response. You can make your own variable and add values to them.
I'm trying to send data to my Nodejs server (hosted on Firebase), from Reactjs to retrieve data from an API call.
It worked when the API url was hard coded, so the issue should be in sending the data from React to Node. I'm currently trying to have it only return one request, but once I'm able to do that, I will be trying to fetch multiple requests.
The result is to populate the stocks state with the response.
My React code looks like this:
class Table extends Component {
constructor (props)
{
super(props);
this.state = {
favorites: ['APPL'],
stocks: []
};
}
componentDidMount() {
// http is adjusted for stackoverflow
fetch('http://localhost:5001/', {
// new part:
method: 'post',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
favorites: this.state.favorites})
// old part - worked before i tried to send data to the backend:
})
.then((response) => response.json())
.then(stockList => {
this.setState({ stocks: stockList });
console.log(stockList);
});
}
Node code:
const functions = require("firebase-functions");
const express = require("express");
const fetch = require("node-fetch");
const cors = require("cors");
const app = express();
app.use(cors({origin: true}));
app.get('/', async (request, response) => {
// new line that was ment to catch the data from frontend.
const favorites = request.body.favorites
// web and key is the rest of the API call.
const url = web+favorites+key;
const fetchResponse = await fetch(url);
const symbol = await fetchResponse.json();
response.json(symbol);
});
In order to get the data from the frontend you will need to make a post endpoint instead in your Node server and send a GET request inside that method.
const functions = require("firebase-functions");
const express = require("express");
const fetch = require("node-fetch");
const cors = require("cors");
const app = express();
app.use(cors({origin: true}));
app.post('/', (req, res) => {
// here is how you get the POST data from the body
console.log(req.body.favorites)
// send the data from the POST request to the API through a GET request here
})
Now you need to make a GET request where I put the comment, you can use the simpler https node.js library for that.
In my question, I'm trying to use Firebase functions to handle the link to an external API and use the data from that API in my frontend.
After some though and help from Stackoverflow, I have found that it might not be an ideal way to do it. I was basically trying to add a layer between the frontend and the API, but that is not necessary, as it is possible to reach the API directly in React. This will remove the function from Firebase, meaning less steps, less code and less fees.
So for every instance in the state.favorites, the correlated data is pulled from the API and stored in the state.stocks.
This piece of code did the trick:
class Table extends Component {
constructor (props)
{
super(props);
this.state = {
favorites: ['aapl', 'arvl'],
stocks: []
};
}
componentDidMount() {
this.state.favorites.map((favorites, index) => {
fetch(`API_website${favorites}/(API_token`)
.then((response) => response.json())
.then(stockList => {
this.setState({ stocks: stockList });
console.log(stockList);
});
})
}
I am trying to load a JSON file from a url in google cloud. I am using the node-fetch package and it works fine for a couple of hours. The problem is that google changes the redirected url frequently. How can I make a get request to the url I will be forwarded to? Or at least know what url I will be forwarded to? I see there is also a package called request, but its deprecated.
This is the code
var express = require('express');
var router = express.Router();
var fetch = require('node-fetch');
router.get('/', async (req, res) => {
const url = 'https://storage.cloud.google.com/blablabla/config.json';
fetch(url)
.then((res) => {
if (res.ok) {
return res.json();
}
})
.then((data) => res.send({ data }))
.catch((err) => res.send(err));
});
module.exports = router;
You can look up the final URL in the response headers. In your case res.headers.get('location') should do the trick.
The Response object has an undocumented url property. So, let's say you call
const response = await fetch(url, {
redirect: 'follow',
follow: 10,
});
response.url will be the URL of the last redirect that was followed.
I keep getting the following error on my graphql queries and not sure why:
POST body missing. Did you forget use body-parser middleware?
Am I doing something weird here? I have tried different recommendations with body-parser online, but still can't seem to fix it.
Server:
require('babel-polyfill')
const express = require('express')
const router = require('./middleware')
const expressStaticGzip = require('express-static-gzip')
const app = express()
const port = process.env.EXPRESS_PORT || 4000
const bodyParser = require('body-parser')
app.use(/\/((?!graphql).)*/, bodyParser.urlencoded({ extended: true }))
app.use(/\/((?!graphql).)*/, bodyParser.json())
app.use('/search/data', expressStaticGzip('public'))
app.use('/', router)
app.listen(port, () => {
console.log(`Server is running on port ${port}`)
})
Router
const router = express.Router()
const server = new ApolloServer({
typeDefs,
resolvers,
context: ({ req }) => {
const { authorization = '' } = req.headers
const universalFetch = (url, opts = {}) => {
return fetch(url, {
...opts,
headers: {
...opts.headers,
authorization,
},
})
}
const request = createRpcClient(universalFetch)
const methods = {}
const catalog = Object.keys(methods).reduce((catalog, method) => {
catalog[method] = params => request(methods[method], params)
return catalog
}, {})
return { catalog, fetch: universalFetch }
},
})
router.use(bodyParser.json())
router.use(bodyParser.text({ type: 'application/graphql' }))
router.use('*', renderer)
server.applyMiddleware({ app: router })
In my particular case the client just missed "Content-type" header with 'application/json' value. After adding that the error message has dissapeared.
applyMiddleware already adds body-parser for the GraphQL endpoint -- there's no need to apply it again and doing so may be causing your issue.
Additionally, I would expect applyMiddleware to be called before router.use('*', renderer) -- otherwise, I would think the wildcard route would be used for /graphql as well?
I forgot the header content-type: application/json
This error also caused by incorrect json in the body or some other problems in the body, such as unnecessary wrong invisible chars. So check generated json for errors and what is actually presents in the request body.
This error can also be raised because the body is too large.
I got it with apollo-server-micro inside a custom api route of NextJs.
It can be fixed by calling the json function coming from micro before apollo gets the request :
import { json } from 'micro'
import { ApolloServer } from 'apollo-server-micro'
const server = new ApolloServer({/*config*/})
const raiseBodyLimit: (handler: NextApiHandler) => NextApiHandler = (
handler
) => async (req, res) => {
if (req.headers['content-type'] !== 'application/json') {
return handler(req, res)
}
await json(req, { limit: '1gb' }) // This is the trick to raise body limit
return handler(req, res)
}
export default raiseBodyLimit(
server.createHandler({
path: '/api/graphql',
})
)
I saw this in this apollo-server's github issue.
Here are some information to build an apollo server endpoint with next.js
if your api upload anything you need to add the
{
uploads:true
}
in middleware while using graphql