TypeError: Cannot read property 'language' of undefined
The demographics model was working few months ago when I used it as 'Clarifai.DEMOGRAPHICS_MODEL' but now it gives a 404 error for the same. I think now I am supposed to use it as 'Clarifai.Demographics' but it gives the error shown in picture.
Am I doing something wrong or is it some Clarifai issue? I am relatively new to react programming and just noticed the app that I had made before using 'Clarifai.DEMOGRAPHICS_MODEL' started showing errors suddenly.
For now, I am just trying to make this work
const onSubmit = () => {
app.models.predict(Clarifai.Demographics, "https://static.independent.co.uk/s3fs-public/thumbnails/image/2015/06/06/15/Chris-Pratt.jpg")
.then(res => console.log(res))
}
NEW EDIT :
Finally, now I can retrieve data from clarifai and send it to frontend. Keeping the backend code here for reference if anyone needs.
--------server.js---------
const express = require('express')
const cors = require('cors')
const posts = require('./demographics.js')
const app = express()
app.use(cors())
app.use(express.json())
const PORT = process.env.PORT || 5000
app.post('/data', posts.demographics)
app.listen(PORT, ()=> {
console.log('Working at port ',PORT)
})
--------demographics.js---------
const {ClarifaiStub, grpc} = require("clarifai-nodejs-grpc");
const stringify = require('json-stringify-safe');
const demographics = (req,res) => {
const stub = ClarifaiStub.grpc()
const metadata = new grpc.Metadata();
metadata.set("authorization", "Key {My_Key}");
stub.PostWorkflowResults(
{
workflow_id: "Demographics",
inputs: [
{data: {image: {url: req.body.input}}}
]
},
metadata,
(err, response) => {
if(response){
const data = stringify(response.results[0].outputs[4].data.regions, null, 2)
res.send(data)
}
else {
console.log(err)
res.status(400)
}
}
)
}
You have to call the request either from the front end or from the backend.
And the demographics now only support requests from the backend.
const {ClarifaiStub} = require("clarifai-nodejs-grpc");
const grpc = require("#grpc/grpc-js");
const metadata = new grpc.Metadata();
metadata.set("authorization", "{My key}");
const stub = ClarifaiStub.json()
stub.PostWorkflowResults(
{
workflow_id: "Demographics",
inputs: [
{data: {image: {url: "https://static.independent.co.uk/s3fs-public/thumbnails/image/2015/06/06/15/Chris-Pratt.jpg"}}}
]
},
metadata,
(err, response) => {
if(response){
console.log(response.results[0].outputs[2].data.regions[0].data.concepts
)
}else {
console.log(err)
}
use this for returning results
// response.results[0].outputs[2].data.regions[0].data.concepts, muliticulture,
// response.results[0].outputs[3].data.regions[0].data.concepts, gender,
//response.results[0].outputs[4].data.regions[0].data.concepts, age,
The Clarifai JS Rest client is now depreciated, the model IDs are not updated and this specific Demographics model is also on the course of depreciation. You can replace it with the new gRPC NodeJS API: https://docs.clarifai.com/api-guide/api-overview/api-clients
You can then get a demographics prediction by calling the new Demographics workflow: https://docs.clarifai.com/api-guide/workflows/workflow-predict (replace 'YOUR_WORKFLOW_ID' by 'Demographics')
Related
I am using aws-sdk/clients/chimesdkmessaging to make requests to get/delete/send channel messages.
But the issue is that the temporary credentials are expired after 1 hour and I cannot use the services without renewing the credentials. I am able to renew them, but couldn't set them in the API Request header.
I tried to set the request header as :
request.httpRequest.headers["x-amz-security-token"] = NEW_TOKEN
But it didn't work. Also, I couldn't find anything on adding a middleware to these API's.
Here's my code
const ChimeMessaging = require("aws-sdk/clients/chimesdkmessaging");
const chimeMessaging = new ChimeMessaging();
async function sendChannelMessage(
channelArn,
messageContent,
persistence,
type,
member,
options = null
) {
const chimeBearerArn = createMemberArn(member.userId);
const params = {
ChimeBearer: chimeBearerArn,
ChannelArn: channelArn,
Content: messageContent,
Persistence: persistence, // Allowed types are PERSISTENT and NON_PERSISTENT
Type: type,
};
const request = (await chimeMessagingClient()).sendChannelMessage(params)
request.on("complete", function (err, data) {
request.httpRequest.headers["x-amz-security-token"] = NEW_TOKEN
});
const response = await request.promise();
const sentMessage = {
response: response,
CreatedTimestamp: new Date(),
Sender: { Arn: createMemberArn(member.userId), Name: member.username },
};
return sentMessage;
}
I am using aws-sdk/clients/chimesdkmessaging to make requests to get/delete/send channel messages.
But the issue is that the temporary credentials are expired after 1 hour and I cannot use the services without renewing the credentials. I am able to renew them, but couldn't set them in the API Request header.
I tried to set the request header as :
request.httpRequest.headers["x-amz-security-token"] = NEW_TOKEN
But it didn't work. Also, I couldn't find anything on adding a middleware to these API's.
Here's my code
const ChimeMessaging = require("aws-sdk/clients/chimesdkmessaging");
const chimeMessaging = new ChimeMessaging();
async function sendChannelMessage(
channelArn,
messageContent,
persistence,
type,
member,
options = null
) {
const chimeBearerArn = createMemberArn(member.userId);
const params = {
ChimeBearer: chimeBearerArn,
ChannelArn: channelArn,
Content: messageContent,
Persistence: persistence, // Allowed types are PERSISTENT and NON_PERSISTENT
Type: type,
};
const request = (await chimeMessagingClient()).sendChannelMessage(params)
request.on("complete", function (err, data) {
request.httpRequest.headers["x-amz-security-token"] = NEW_TOKEN
});
const response = await request.promise();
const sentMessage = {
response: response,
CreatedTimestamp: new Date(),
Sender: { Arn: createMemberArn(member.userId), Name: member.username },
};
return sentMessage;
}
I am currently working on social media mern stack react app. I am using node js and express as my backend services , also using mongoose to store my data and axios and redux thunk which connect the backend to the front end. Till now I had no issue recieving and sending data to the server. Right now I am trying to create search post get request ,base on a keyword the user entered. The issue with it, that when I am sending the keyword to the server instead of recieving the string it gets undefined value, like redux thunk not sending anything. I will be very thankful if someone could help me with that. I am watching the code over and over again and can't find out the reason for that.
My post controller class(I copied only the relevant function):
import express from "express";
const app = express();
import Post from "../model/PostModel.js";
import ErrorHandlng from "../utilities/ErrorHandling.js";
import bodyParser from "body-parser";
import catchAsync from "../utilities/CatchAsync.js";
import User from "../model/UserModel.js";
app.use(express.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
export const getPosts = catchAsync(async (req, res, next) => {
const data = req.body.keyword;
const page = parseInt(req.query.page || "0");
const PAGE_SIZE = 20;
const query = new RegExp(data, "i");
const total = await Post.countDocuments({});
const posts = await Post.find({ $or: [{ title: query }, { content: query }] })
.limit(PAGE_SIZE)
.skip(PAGE_SIZE * page);
if (!posts) {
return next(new ErrorHandlng("No posts were found", 400));
}
res.status(200).json({
status: "success",
data: {
totalPages: Math.ceil(total / PAGE_SIZE),
posts,
},
});
});
My api class(front end,copied only the calling for that specific get request):
import axios from "axios";
const baseURL = "http://localhost:8000";
axios.defaults.withCredentials = true;
const API = axios.create({
baseURL,
credentials: "include",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
});
export const getPostsByKeyword = (keyword, page) =>
API.get(`/post/getPostsByKey?page=${page}`, keyword);
Post slice class:
export const fetchPostsByKeyWord = createAsyncThunk(
"post/getKeyword",
async ({ keyword, page }, { fulfillWithValue, rejectWithValue }) => {
try {
const response = await api.getPostsByKeyword(keyword, page);
if (response.statusCode === "400") {
throw new Error("There are no available posts");
}
const fetchData = await response.data.data.posts;
const totalPages = await response.data.data.totalPages;
return fulfillWithValue({ fetchData, totalPages });
} catch (err) {
console.log(err.response.message);
}
}
);
const initialState = { status: "undefined" };
const PostSlice = createSlice({
name: "post",
initialState,
reducers: {},
extraReducers: {},
});
export const postActions = PostSlice.actions;
export default PostSlice;
Calling the backend:
dispatch(fetchPostsByKeyWord({ keyword, page }))
.unwrap()
.then((originalPromiseResults) => {
console.log("thte " + " " + originalPromiseResults.totalPages);
console.log("The data is" + originalPromiseResults.fetchData);
setTotalPages(originalPromiseResults.totalPages);
})
.catch((err) => {
console.log(err.message);
});
As you can see I have not copied the whole code, I copied only the parts that are relevants for the question.
Browsers cannot currently send GET requests with a request body. XMLHttpRequest (which Axios uses) will ignore it and fetch() will trigger an error.
See also HTTP GET with request body for extra discussion on why trying this might be a bad idea.
You should instead pass everything required in the query string, preferably via the params option so it is correctly encoded...
export const getPostsByKeyword = (keyword, page) =>
API.get("/post/getPostsByKey", { params: { page, keyword } });
and grab the data via req.query server-side.
const { page, keyword } = req.query;
With vanilla JS, you can use URLSearchParams to construct the query string...
const params = new URLSearchParams({ page, keyword });
// XHR
const xhr = new XMLHttpRequest();
xhr.open("GET", `/post/getPostsByKey?${params}`);
// Fetch
fetch(`/post/getPostsByKey?${params}`); // GET is the default method
Your Axios instance creation could also be a lot simpler...
Axios is usually quite good at setting the correct content-type header, you don't have to
Your Express app isn't doing any content-negotiation so you don't need to set the accept header
Unless you're actually using cookies (which it doesn't look like), you don't need credential support
const API = axios.create({ baseURL });
///component
function Home() {
const [show, setShow]= useState([{name:'', info:'', airingDate:'', poster:''}])
useEffect(()=>{
fetch("/home")
//.then(res=> res.json())
.then(res => res.text())
.then(text => console.log(text))
})
return (
<div>
{show.map(a=>
<div>
<h2>{a.title}</h2>
</div>
)}
</div>
)
/////index.js
const TvShows = require("./models/TvShows");
const express = require("express");
const app = express();
const mongoose= require("mongoose")
const dotenv= require("dotenv");
const authRoute = require("./routes/auth");
const { application } = require("express");
const userRoute = require("./routes/users");
const commentRoute = require("./routes/comments");
const tvshowsRoute = require("./routes/tvshows");
const cors = require("cors");
app.use(cors());
console.log(".");
dotenv.config();
app.use(express.json());
mongoose.connect(process.env.MONGO_URL,{
useCreateIndex: true,
useNewUrlParser: true,
useUnifiedTopology: true,
}).then(console.log("connected to mongoDB"));
app.use("/auth", authRoute);
app.use("/users", userRoute);
app.use("/comments", commentRoute);
app.post("/api/home", tvshowsRoute);
app.use("/api/home", tvshowsRoute);
/*
app.get('/api/home', (req,res)=>{
TvShows.find().then((result)=>{
res.send(result);
})
})
*/
/*
app.use("/",(req,res)=>{
console.log("main url")
})*/
app.listen("3001",()=>{
console.log("backend running");
})
//////route
const router = require("express").Router();
const TvShows = require("../models/TvShows");
router.post("/api/home", async (req, res) => {
console.log("here")
try{
const newTvShow = new TvShows({
title: req.body.title,
poster: req.body.poster,
info: req.body.info
});
const savedTvShows = await newTvShow.save();
res.status(200).json(savedTvShows);
}catch (err) {
res.status(500).json(err);
}
}
);
router.route("/api/home").get((req, res)=>{
TvShows.find()
.then(foundShows=> res.json(foundShows))
})
module.exports = router;
when I change res.json with res.text I see my index.html page on console not the data I want to fetch from mongodb. This error is probably because I didn't use /api/ on root url but I couldn't figure it out where I should write it. I tried but didn't work. It would be so good if someone could've helped. Thank you so much.
Indeed, you are fetching the /home page of your front-end app.
Assuming the api is on a different server, you would need to call the address of that server.
If you have a set up locally with a nodejs server and a react app running separately, you should have them run on two different ports.
If you have react app on http://localhost:3000 (default), then change your api to listen on 3001, then in your react code above, you can use the full uri
http://localhost:3001/api/home
in your fetch call.
I'm making a lot of assumptions about how you have this set up, based on my own experience of local development for similar problems.
I see there are a lot of posts on this subject already, so I apologize if this is a repeat.
What is strange and possibly unique (I don't know) is that the server seems to be functioning and executing the API call properly.
I have a react front end with an express backend being hosted on an AWS EC2 instance. As said above, when my front end makes a axios.post request, the server does everything it is supposed to, but I'm am returned two errors. One is
OPTIONS http://us-west-1.compute.amazonaws.com:3000 net::ERR_CONNECTION_REFUSED
The other is
Error: Network Error
at createError (createError.js:17)
at XMLHttpRequest.handleError (xhr.js:87)
react code is:
import React from "react";
import PaypalExpressBtn from "react-paypal-express-checkout";
import axios from "axios";
export default class Pay extends React.Component {
constructor(props) {
super(props);
this.state = {
items: {}
};
}
render() {
const onSuccess = payment => {
axios
.post("http://compute.amazonaws.com:3000/", {
value: this.props.value,
fileName: this.props.fileName,
hash: this.props.hash
})
.then(response => console.log(response.data))
.catch(function(error) {
console.log(error);
});
console.log(payment);
};
let env = "sandbox"; // you can set here to 'production' for production
let currency = "USD"; // or you can set this value from your props or state
let total = 3.33; // same as above, this is the total amount (based on
const client = {
sandbox:
"...key...",
production: "YOUR-PRODUCTION-APP-ID"
};
return (
<div>
<PaypalExpressBtn
onSuccess={onSuccess}
/>
</div>
);
}
}
express code is:
const express = require("express");
const app = express();
const Tx = require("ethereumjs-tx");
var cors = require('cors')
const Web3 = require("web3");
const web3 = new Web3(
"https://ropsten.infura.io/v3/d55489f8ea264a1484c293b05ed7eb85"
);
app.use(cors());
const abi = [...]
const contractAddress = "0x15E1ff7d97CB0D7C054D19bCF579e3147FC9009b";
const myAccount = "0x59f568176e21EF86017EfED3660625F4397A2ecE";
const privateKey1 = new Buffer(
"...privateKey...",
"hex"
);
app.post("/", function(req, res, next) {
var hashValue = req.body.hash,
fileName = req.body.fileName,
value = req.body.value;
const contract = new web3.eth.Contract(abi, contractAddress, {
from: myAccount
// gas: '50000'
});
web3.eth.getTransactionCount(myAccount, (err, txCount) => {
//Smart contract data
const data = contract.methods
.setHashValue(value + " " + fileName + " " + hashValue)
.encodeABI();
// Build the transaction
const txObject = {
nonce: web3.utils.toHex(txCount),
gasLimit: web3.utils.toHex(1000000),
gasPrice: 20000000000,
data: data,
from: myAccount,
to: contractAddress
};
// Sign the transaction
const tx = new Tx(txObject);
const serializedTx = tx.serialize();
// const raw = '0x' + serializedTx.toString('hex')
// Broadcast the transaction
web3.eth
.sendSignedTransaction("0x" + serializedTx.toString("hex"))
.on("receipt", console.log);
next();
});
});
app.listen(3000, () => console.log("listening on 3000"));
I would reiterate that the server is broadcasting the Ethereum transaction as intended. The reason that I am asking is because I do not want errors, and am checking to see if this is part of a larger issue I'm having with a json return call.
Any help is appreciated. Thanks!
I resolved this by adding a res.json()
web3.eth
.sendSignedTransaction("0x" + serializedTx.toString("hex"))
.on("receipt", console.log, res.json);