Related
Intro
I am developing an login application using Nextjs on frontend and springboot on backend.
Problem
I am able to login from the frontend which calls the loginAPI named /authenticate developed in springboot and it is successfully returning the authToken.After login I got redirects to home (/allcoupons) page.
In login , I am passing the value of token as response.data like this
const handleSubmit = async (e) => {
// e.preventDefault();
let requestbody = {
username: credentials.username,
password: credentials.password,
};
try {
const response = await axios({
method: "post",
headers: {},
url: "http://localhost:8081/authenticate",
data: requestbody,
});
//console.log("credentials for login = ", credentials);
//console.log("response from api = ", response);
if (response.status === 200) {
router.push(
{
pathname: "/allcoupons",
query: { auth: JSON.stringify(response.data) },
},
undefined,
{
shallow: true
}
);
} else alert("invalid credentials");
} catch (error) {
setTimeout(() => {
setShowAlert(true);
}, 2000);
setShowAlert(false);
}
};
Then I redirects to /allcoupons component
In this component I am using getServerSideProps(). I am able to access the authtoken value from context.query.auth but now I am unable to send this authtoken value as bearer token with another API /allcoupons in the headers.
home.js
import React, { Fragment, useState, useEffect } from "react";
import { useRouter } from "next/router";
import Footer from "./components/footer";
import { Alert } from "flowbite-react";
import axios from "axios";
const Allcoupons = ({ datafromAPI }) => {
const router = useRouter();
//console.log("datafromAPI in components = ", datafromAPI.coupons)
//let data = datafromAPI.coupons;
const val = router.query.auth ? JSON.parse(router.query.auth) : {};
console.log("authtoken form login = ", val);
const [showModal, setShowModal] = useState(false);
.
.
return (
<>
.
.
.
</>
);
};
export async function getServerSideProps(context) {
//Fetch data from get API
//console.log("context = ", context.query.auth);
const token = context.query.auth;
console.log("token = ",context.query.auth)
const res = await axios.get(
`http://localhost:8081/couponstore/v1.0/coupons`,
//using like this
{ headers: { Authorization: `Bearer ${token}` } }
);
const datafromAPI = res.data;
console.log("data from API server = ",datafromAPI);
return { props: { datafromAPI } };
}
Observation
But as soon as I redirects to this page , it endpoint change from /allcoupons to /allcoupons?auth={authtokenvalue} .
Logs/StackTrace
Also this log comes in the terminal
token = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhcnVuYWJoIiwiZXhwIjoxNjY0NTQwODYwLCJpYXQiOjE2NjQ1MzM2NjB9.Ib3X-6TMyQ3YfoGz-PuS4hehzuHq-N6XHwzLF6cXD2U"
error - [AxiosError: Request failed with status code 403] {
code: 'ERR_BAD_REQUEST',
config: {
transitional: {
silentJSONParsing: true,
forcedJSONParsing: true,
clarifyTimeoutError: false
},
adapter: [Function: httpAdapter],
transformRequest: [ [Function: transformRequest] ],
transformResponse: [ [Function: transformResponse] ],
timeout: 0,
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
maxContentLength: -1,
maxBodyLength: -1,
env: { FormData: [Function] },
validateStatus: [Function: validateStatus],
headers: {
Accept: 'application/json, text/plain, */*',
Authorization: 'Bearer "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhcnVuYWJoIiwiZXhwIjoxNjY0NTQwODYwLCJpYXQiOjE2NjQ1MzM2NjB9.Ib3X-6TMyQ3YfoGz-PuS4hehzuHq-N6XHwzLF6cXD2U"',
'User-Agent': 'axios/0.27.2'
},
method: 'get',
url: 'http://localhost:8081/couponstore/v1.0/coupons',
data: undefined
},
request: <ref *1> ClientRequest {
_events: [Object: null prototype] {
abort: [Function (anonymous)],
aborted: [Function (anonymous)],
connect: [Function (anonymous)],
error: [Function (anonymous)],
socket: [Function (anonymous)],
timeout: [Function (anonymous)],
prefinish: [Function: requestOnPrefinish]
},
_eventsCount: 7,
_maxListeners: undefined,
outputData: [],
outputSize: 0,
writable: true,
destroyed: false,
_last: true,
chunkedEncoding: false,
shouldKeepAlive: false,
maxRequestsOnConnectionReached: false,
_defaultKeepAlive: true,
useChunkedEncodingByDefault: false,
sendDate: false,
_removedConnection: false,
_removedContLen: false,
_removedTE: false,
_contentLength: 0,
_hasBody: true,
_trailer: '',
finished: true,
_headerSent: true,
_closed: false,
socket: Socket {
connecting: false,
_hadError: false,
_parent: null,
_host: 'localhost',
_readableState: [ReadableState],
_events: [Object: null prototype],
_eventsCount: 7,
_maxListeners: undefined,
_writableState: [WritableState],
allowHalfOpen: false,
_sockname: null,
_pendingData: null,
_pendingEncoding: '',
server: null,
_server: null,
parser: null,
_httpMessage: [Circular *1],
write: [Function: writeAfterFIN],
[Symbol(async_id_symbol)]: 285969,
[Symbol(kHandle)]: [TCP],
[Symbol(lastWriteQueueSize)]: 0,
[Symbol(timeout)]: null,
[Symbol(kBuffer)]: null,
[Symbol(kBufferCb)]: null,
[Symbol(kBufferGen)]: null,
[Symbol(kCapture)]: false,
[Symbol(kSetNoDelay)]: false,
[Symbol(kSetKeepAlive)]: true,
[Symbol(kSetKeepAliveInitialDelay)]: 60,
[Symbol(kBytesRead)]: 0,
[Symbol(kBytesWritten)]: 0,
[Symbol(RequestTimeout)]: undefined
},
_header: 'GET /couponstore/v1.0/coupons HTTP/1.1\r\n' +
'Accept: application/json, text/plain, */*\r\n' +
'Authorization: Bearer "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhcnVuYWJoIiwiZXhwIjoxNjY0NTQwODYwLCJpYXQiOjE2NjQ1MzM2NjB9.Ib3X-6TMyQ3YfoGz-PuS4hehzuHq-N6XHwzLF6cXD2U"\r\n' +
'User-Agent: axios/0.27.2\r\n' +
'Host: localhost:8081\r\n' +
'Connection: close\r\n' +
'\r\n',
_keepAliveTimeout: 0,
_onPendingData: [Function: nop],
agent: Agent {
_events: [Object: null prototype],
_eventsCount: 2,
_maxListeners: undefined,
defaultPort: 80,
protocol: 'http:',
options: [Object: null prototype],
requests: [Object: null prototype] {},
sockets: [Object: null prototype],
freeSockets: [Object: null prototype] {},
keepAliveMsecs: 1000,
keepAlive: false,
maxSockets: Infinity,
maxFreeSockets: 256,
scheduling: 'lifo',
maxTotalSockets: Infinity,
totalSocketCount: 1,
[Symbol(kCapture)]: false
},
socketPath: undefined,
method: 'GET',
maxHeaderSize: undefined,
insecureHTTPParser: undefined,
path: '/couponstore/v1.0/coupons',
_ended: true,
res: IncomingMessage {
_readableState: [ReadableState],
_events: [Object: null prototype],
_eventsCount: 4,
_maxListeners: undefined,
socket: [Socket],
httpVersionMajor: 1,
httpVersionMinor: 1,
httpVersion: '1.1',
complete: true,
rawHeaders: [Array],
rawTrailers: [],
aborted: false,
upgrade: false,
url: '',
method: null,
statusCode: 403,
statusMessage: '',
client: [Socket],
_consuming: false,
_dumped: false,
req: [Circular *1],
responseUrl: 'http://localhost:8081/couponstore/v1.0/coupons',
redirects: [],
[Symbol(kCapture)]: false,
[Symbol(kHeaders)]: [Object],
[Symbol(kHeadersCount)]: 18,
[Symbol(kTrailers)]: null,
[Symbol(kTrailersCount)]: 0,
[Symbol(RequestTimeout)]: undefined
},
aborted: false,
timeoutCb: null,
upgradeOrConnect: false,
parser: null,
maxHeadersCount: null,
reusedSocket: false,
host: 'localhost',
protocol: 'http:',
_redirectable: Writable {
_writableState: [WritableState],
_events: [Object: null prototype],
_eventsCount: 3,
_maxListeners: undefined,
_options: [Object],
_ended: true,
_ending: true,
_redirectCount: 0,
_redirects: [],
_requestBodyLength: 0,
_requestBodyBuffers: [],
_onNativeResponse: [Function (anonymous)],
_currentRequest: [Circular *1],
_currentUrl: 'http://localhost:8081/couponstore/v1.0/coupons',
[Symbol(kCapture)]: false
},
[Symbol(kCapture)]: false,
[Symbol(kNeedDrain)]: false,
[Symbol(corked)]: 0,
[Symbol(kOutHeaders)]: [Object: null prototype] {
accept: [Array],
authorization: [Array],
'user-agent': [Array],
host: [Array]
},
[Symbol(kUniqueHeaders)]: null
},
response: {
status: 403,
statusText: '',
headers: {
'x-content-type-options': 'nosniff',
'x-xss-protection': '1; mode=block',
'cache-control': 'no-cache, no-store, max-age=0, must-revalidate',
pragma: 'no-cache',
expires: '0',
'x-frame-options': 'DENY',
'content-length': '0',
date: 'Fri, 30 Sep 2022 10:27:40 GMT',
connection: 'close'
},
config: {
transitional: [Object],
adapter: [Function: httpAdapter],
transformRequest: [Array],
transformResponse: [Array],
timeout: 0,
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
maxContentLength: -1,
maxBodyLength: -1,
env: [Object],
validateStatus: [Function: validateStatus],
headers: [Object],
method: 'get',
url: 'http://localhost:8081/couponstore/v1.0/coupons',
data: undefined
},
request: <ref *1> ClientRequest {
_events: [Object: null prototype],
_eventsCount: 7,
_maxListeners: undefined,
outputData: [],
outputSize: 0,
writable: true,
destroyed: false,
_last: true,
chunkedEncoding: false,
shouldKeepAlive: false,
maxRequestsOnConnectionReached: false,
_defaultKeepAlive: true,
useChunkedEncodingByDefault: false,
sendDate: false,
_removedConnection: false,
_removedContLen: false,
_removedTE: false,
_contentLength: 0,
_hasBody: true,
_trailer: '',
finished: true,
_headerSent: true,
_closed: false,
socket: [Socket],
_header: 'GET /couponstore/v1.0/coupons HTTP/1.1\r\n' +
'Accept: application/json, text/plain, */*\r\n' +
'Authorization: Bearer "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhcnVuYWJoIiwiZXhwIjoxNjY0NTQwODYwLCJpYXQiOjE2NjQ1MzM2NjB9.Ib3X-6TMyQ3YfoGz-PuS4hehzuHq-N6XHwzLF6cXD2U"\r\n' +
'User-Agent: axios/0.27.2\r\n' +
'Host: localhost:8081\r\n' +
'Connection: close\r\n' +
'\r\n',
_keepAliveTimeout: 0,
_onPendingData: [Function: nop],
agent: [Agent],
socketPath: undefined,
method: 'GET',
maxHeaderSize: undefined,
insecureHTTPParser: undefined,
path: '/couponstore/v1.0/coupons',
_ended: true,
res: [IncomingMessage],
aborted: false,
timeoutCb: null,
upgradeOrConnect: false,
parser: null,
maxHeadersCount: null,
reusedSocket: false,
host: 'localhost',
protocol: 'http:',
_redirectable: [Writable],
[Symbol(kCapture)]: false,
[Symbol(kNeedDrain)]: false,
[Symbol(corked)]: 0,
[Symbol(kOutHeaders)]: [Object: null prototype],
[Symbol(kUniqueHeaders)]: null
},
data: ''
},
page: '/allcoupons'
}
Whats the mistake here??
This how do usually when I create react apps
I create a global context
import { createContext } from "react";
import { GlobalContextType } from "../types";
const defaultValue: GlobalContextType = {
dispatch: () => {},
state: {
user: { authToken: "", username: "" }
},
};
export const GlobalContext = createContext(defaultValue);
create a hook for my global context
import { useContext } from "react";
import { GlobalContext } from "../contexts";
export function useGlobalContext () {
const context = useContext(GlobalContext)
if (!context) throw new Error("Missing Context - Global context");
return context;
}
Create state reducer hook
import { Dispatch, useMemo, useReducer } from "react";
import {
GlobalContextActions,
GlobalContextState,
} from "../types";
export function globalContextReducer(
state: GlobalContextState,
action: ReducerAction<GlobalContextActions>
): GlobalContextState {
switch (action.type) {
case GlobalContextActions.setUser:
return {
...state,
user: action.payload
};
default:
return state;
}
}
export function useGlobalContextReducer(reducer = globalContextReducer) {
const [state, dispatch] = useReducer(reducer, {
user : {authToken: "", username: ""}
});
return useMemo(() => {
return {
dispatch,
state,
};
}, [d, state]);
}
Wrapped the whole App with my global context
import { GlobalContext } from "../src/contexts";
import { useGlobalContextReducer } from "../src/hooks/use-global-context-reducer";
export default function MyApp(props: MyAppProps) {
const { Component pageProps } = props;
const globalContextReducer = useGlobalContextReducer();
return (
<GlobalContext.Provider value={globalContextReducer}>
<Component {...pageProps} />
</GlobalContext.Provider>
);
}
this just my setup
then in my login page
import {GlobalContextActions, useGlobalContext} from "../../context"
import {Routes} from "../routes"
function Login() {
const { dispatch} = useGlobalContext();
const router = useRouter();
const [form, updateForm] = useState({
email: "",
password: "",
});
const onFieldChange = (event: ChangeEvent<HTMLInputElement>) => {
const { target } = event;
const { id, value } = target;
updateForm((current) => ({ ...current, [id]: value }));
};
const isLoginDisabled = !validateEmail(form.email) || !form.password;
const onLogin = async () => {
const dataService = container.resolve(DataService);
const result = await dataService.getLoginData(form.email, form.password);
if (result.error) {
return dispatchError(result?.errorMessage as string);
}
useGlobalContextReducer({action:GlobalContextActions.setUser, payload: result.data});
router.push(Routes.home);
};
return (
<Box>
<form action="" onSubmit={(event) => event?.preventDefault()}>
<TextField
id="email"
label={"email"}
variant="standard"
required
value={form.email}
onChange={onFieldChange}
type="email"
fullWidth
data-testid="email"
/>
<TextField
id="password"
label={"password"}
variant="standard"
type="password"
value={form.password}
required
fullWidth
onChange={onFieldChange}
data-testid="password"
/>
<Button type="submit" variant="contained" disabled={isLoginDisabled} onClick={onLogin}>
Login
</Button>
</form>
</Box>
);
}
export default Login;
and this how I use the global state
function MyPage() {
const {state} = useGlobalContext
return (<div>{JSON.stringinfy(state)}</div>)
}
First of all I do not recommend returning authtoken in response of successful login. You should use httpOnly cookies to set authtoken. It is more secure and you can set it from backend like this.
Second axios provide a way to set Authorization token in request. I mean you can alter default headers like below:
axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
Read more in doc
Trying to send an image through GupShup. I'm using their sandbox. My backend is node.js with feathersjs.
But it's returning me this error:
Response {
size: 0,
timeout: 0,
[Symbol(Body internals)]: {
body: PassThrough {
_readableState: [ReadableState],
readable: true,
_events: [Object: null prototype],
_eventsCount: 2,
_maxListeners: undefined,
_writableState: [WritableState],
writable: false,
allowHalfOpen: true,
_transformState: [Object],
[Symbol(kCapture)]: false
},
disturbed: false,
error: null
},
[Symbol(Response internals)]: {
url: 'https://api.gupshup.io/sm/api/v1/msg',
status: 400,
statusText: 'Bad Request',
headers: Headers { [Symbol(map)]: [Object: null prototype] },
counter: 0
}
}
This is the code to send the image
const form = new URLSearchParams();
form.append('channel', 'whatsapp');
form.append('destination', destination);
form.append('source', app.get('GUPSHUP_NUMBER'));
form.append('message.payload', JSON.stringify(message));
form.append('src.name', 'OneAccess');
console.log(form);
try {
const res = await fetch('https://api.gupshup.io/sm/api/v1/msg', {
method: 'POST',
body: form,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
apikey: app.get('GUPSHUP_API'),
},
});
console.log('result message', res);
} catch (err) {
console.log('errro sending msg', err);
}
This is the message that I'm trying to send
message: {
type: 'image',
originalUrl:
'https://images.pexels.com/photos/248797/pexels-photo-248797.jpeg',
previewUrl:
'https://images.pexels.com/photos/248797/pexels-photo-248797.jpeg',
caption: 'Sample image',
},
Can anyone help me?
Change message.payload to message. You can check the correct signature at https://www.gupshup.io/developer/docs/bot-platform/guide/whatsapp-api-documentation#SendImage
MySQL runs fine with simple callbacks, but I want to run multiple mysql queries asynchronously in express node.js, for that I am using async await with promise.all. I also tried using promise.allSettled, but it still gives the same error.
Here is the complete code.
dbConn.js
var config = require('../config');
var conn = (module.exports = require("mysql").createConnection({
host: config.dbHost,
user: config.dbUser,
port: config.dbPort,
password: config.dbPassword,
database: config.dbName,
}));
conn.connect(err => {
if (err) {
return console.log(err.stack);
} else {
return console.log("Connected!");
}
});
Route File.
var conn = require('../DB/dbConn');
router.get('/search',async function(req, res, next) {
try {
const CourseContent = await conn.query( "SELECT cd.*,s.*,u.* from coursesdetails cd,subjects s,universities u where cd.subjectId = s.subjectId and u.universityId = cd.universityId and s.subjectNameEn like '%Art%';" );
const Allsubjects = await conn.query("select * from subjects;");
const AllCountries = await conn.query("SELECT distinct Country from worldcities;");
const AllDisciplines = await conn.query("select * from discipline;");
const promises = [CourseContent,Allsubjects,AllCountries,AllDisciplines];
Promise.all(promises).then((results) => {
console.log(results);
res.render('search', { results: results,layout: 'layouts/index-layout' });
}).catch((error)=> {console.log(error);})
} catch (error) {
console.error(error);
}
});
response From Promise.all results
[
Query {
_events: [Object: null prototype] {
error: [Function],
packet: [Function],
timeout: [Function],
end: [Function]
},
_eventsCount: 4,
_maxListeners: undefined,
_callback: undefined,
_callSite: Error
at Protocol._enqueue (C:\Users\myste\Documents\Office Work\FindCoursesNode.js\node_modules\mysql\lib\protocol\Protocol.js:144:48)
at Connection.query (C:\Users\myste\Documents\Office Work\FindCoursesNode.js\node_modules\mysql\lib\Connection.js:198:25)
at C:\Users\myste\Documents\Office Work\FindCoursesNode.js\routes\course.js:58:38
at Layer.handle [as handle_request] (C:\Users\myste\Documents\Office Work\FindCoursesNode.js\node_modules\express\lib\router\layer.js:95:5)
at next (C:\Users\myste\Documents\Office Work\FindCoursesNode.js\node_modules\express\lib\router\route.js:137:13)
at Route.dispatch (C:\Users\myste\Documents\Office Work\FindCoursesNode.js\node_modules\express\lib\router\route.js:112:3)
at Layer.handle [as handle_request] (C:\Users\myste\Documents\Office Work\FindCoursesNode.js\node_modules\express\lib\router\layer.js:95:5)
at C:\Users\myste\Documents\Office Work\FindCoursesNode.js\node_modules\express\lib\router\index.js:281:22
at Function.process_params (C:\Users\myste\Documents\Office Work\FindCoursesNode.js\node_modules\express\lib\router\index.js:335:12)
at next (C:\Users\myste\Documents\Office Work\FindCoursesNode.js\node_modules\express\lib\router\index.js:275:10),
_ended: false,
_timeout: undefined,
_timer: Timer { _object: [Circular], _timeout: null },
sql: "SELECT cd.*,s.*,u.* from coursesdetails cd,subjects s,universities u where cd.subjectId = s.subjectId and u.universityId = cd.universityId and s.subjectNameEn like '%Art%';",
values: undefined,
typeCast: true,
nestTables: false,
_resultSet: null,
_results: [],
_fields: [],
_index: 0,
_loadError: null,
_connection: Connection {
_events: [Object: null prototype] {},
_eventsCount: 0,
_maxListeners: undefined,
config: [ConnectionConfig],
_socket: [Socket],
_protocol: [Protocol],
_connectCalled: true,
state: 'authenticated',
threadId: 25,
[Symbol(kCapture)]: false
},
[Symbol(kCapture)]: false
},
Query {
_events: [Object: null prototype] {
error: [Function],
packet: [Function],
timeout: [Function],
end: [Function]
},
_eventsCount: 4,
_maxListeners: undefined,
_callback: undefined,
_callSite: Error
at Protocol._enqueue (C:\Users\myste\Documents\Office Work\FindCoursesNode.js\node_modules\mysql\lib\protocol\Protocol.js:144:48)
at Connection.query (C:\Users\myste\Documents\Office Work\FindCoursesNode.js\node_modules\mysql\lib\Connection.js:198:25)
at C:\Users\myste\Documents\Office Work\FindCoursesNode.js\routes\course.js:59:36
at processTicksAndRejections (internal/process/task_queues.js:97:5),
_ended: false,
_timeout: undefined,
_timer: Timer { _object: [Circular], _timeout: null },
sql: 'select * from subjects;',
values: undefined,
typeCast: true,
nestTables: false,
_resultSet: null,
_results: [],
_fields: [],
_index: 0,
_loadError: null,
_connection: Connection {
_events: [Object: null prototype] {},
_eventsCount: 0,
_maxListeners: undefined,
config: [ConnectionConfig],
_socket: [Socket],
_protocol: [Protocol],
_connectCalled: true,
state: 'authenticated',
threadId: 25,
[Symbol(kCapture)]: false
},
[Symbol(kCapture)]: false
},
Query {
_events: [Object: null prototype] {
error: [Function],
packet: [Function],
timeout: [Function],
end: [Function]
},
_eventsCount: 4,
_maxListeners: undefined,
_callback: undefined,
_callSite: Error
at Protocol._enqueue (C:\Users\myste\Documents\Office Work\FindCoursesNode.js\node_modules\mysql\lib\protocol\Protocol.js:144:48)
at Connection.query (C:\Users\myste\Documents\Office Work\FindCoursesNode.js\node_modules\mysql\lib\Connection.js:198:25)
at C:\Users\myste\Documents\Office Work\FindCoursesNode.js\routes\course.js:60:37
at processTicksAndRejections (internal/process/task_queues.js:97:5),
_ended: false,
_timeout: undefined,
_timer: Timer { _object: [Circular], _timeout: null },
sql: 'SELECT distinct Country from worldcities;',
values: undefined,
typeCast: true,
nestTables: false,
_resultSet: null,
_results: [],
_fields: [],
_index: 0,
_loadError: null,
_connection: Connection {
_events: [Object: null prototype] {},
_eventsCount: 0,
_maxListeners: undefined,
config: [ConnectionConfig],
_socket: [Socket],
_protocol: [Protocol],
_connectCalled: true,
state: 'authenticated',
threadId: 25,
[Symbol(kCapture)]: false
},
[Symbol(kCapture)]: false
}...
Node.js version 12.18.1
The mysql module does not support the Promise API, so you cannot use async/await with it. If you want to use async/await then you should take a look at the mysql2 module. Here is a small example of working with this module:
const mysql = require('mysql2');
(async function main(param) {
try {
const nativePool = mysql.createPool({
host: 'localhost',
user: 'root',
database: 'newsdb',
connectionLimit: 10,
});
const pool = nativePool.promise();
const query1 = pool.query('SELECT * FROM users');
const query2 = pool.query('SELECT * FROM users');
const query3 = pool.query('SELECT * FROM users');
const results = await Promise.all([query1, query2, query3]);
results.forEach(([rows, fields]) => console.log(rows));
} catch (error) {
console.error(error);
}
})();
Also, in your sample code, you do not need to use await before requests if you want to execute them in parallel in Promise.all. Because, using await, you will wait for each request to complete.
You could make it work with Promises as you want just importing the util module that already comes in node
the code would be something like this
const util = require('util')
conn.query = util.promisify(conn.query)
then after it you export the conn
But I would recommend you to use Pool instead of conn for mysql , the method I showed works also with Pool
I'm trying to do a sql transaction. for this I need to start a session which a possible only with a mongo dB connection instance.
In my app, I can reach only the DB instance. and I need to be able to get from it the mongodb connection instance. As I understand, getMongo() function should do exactly that.
The problem is the getMongo() is not acting as expected.
when i run this following code:
const db = await this.dbClient;
console.log(db,"db");
console.log(db.getMongo(),"getMongo");
const session = db.getMongo().startSession();
I get this following console.log and errors:
Db {
_events: [Object: null prototype] {},
_eventsCount: 0,
_maxListeners: undefined,
s: {
dbCache: {},
children: [],
topology: NativeTopology {
_events: [Object: null prototype],
_eventsCount: 35,
_maxListeners: Infinity,
s: [Object],
[Symbol(kCapture)]: false,
[Symbol(waitQueue)]: [Denque]
},
options: {
retryWrites: true,
readPreference: [ReadPreference],
promiseLibrary: [Function: Promise]
},
logger: Logger { className: 'Db' },
bson: BSON {},
readPreference: ReadPreference { mode: 'primary', tags: undefined },
bufferMaxEntries: -1,
parentDb: null,
pkFactory: undefined,
nativeParser: undefined,
promiseLibrary: [Function: Promise],
noListener: false,
readConcern: undefined,
writeConcern: undefined,
namespace: MongoDBNamespace { db: 'MyDB', collection: undefined }
},
serverConfig: [Getter],
bufferMaxEntries: [Getter],
databaseName: [Getter],
[Symbol(kCapture)]: false
} db
{"Error msg: TypeError: db.getMongo is not a
function\n...","level":"error"}
{"session is not defined....","level":"error"}
Anybody knows what it the problem?
My mongo version is 4.2.6.
Many thanks
I'm having an issue with some EPS conversions using ImageMagick in Firebase Cloud Functions. The ones that does work, work every time - and the ones that don't, always fails, and I don't understand why..
I'm getting this error in the logs:
{ ChildProcessError: `convert -colorspace sRGB -density 300 input.eps -resize 400x400 output.png` failed with code 1
at ChildProcess.<anonymous> (/user_code/node_modules/child-process-promise/lib/index.js:132:23)
at emitTwo (events.js:106:13)
at ChildProcess.emit (events.js:191:7)
at maybeClose (internal/child_process.js:920:16)
at Socket.<anonymous> (internal/child_process.js:351:11)
at emitOne (events.js:96:13)
at Socket.emit (events.js:188:7)
at Pipe._handle.close [as _onclose] (net.js:509:12)
name: 'ChildProcessError',
code: 1,
childProcess:
ChildProcess {
domain: null,
_events: { error: [Function: t], close: [Function] },
_eventsCount: 2,
_maxListeners: undefined,
_closesNeeded: 3,
_closesGot: 3,
connected: false,
signalCode: null,
exitCode: 1,
killed: false,
spawnfile: 'convert',
_handle: null,
spawnargs:
[ 'convert',
'-colorspace',
'sRGB',
'-density',
'300',
'input.eps',
'-resize',
'400x400',
'output.png' ],
pid: 12,
stdin:
Socket {
connecting: false,
_hadError: false,
_handle: null,
_parent: null,
_host: null,
_readableState: [Object],
readable: false,
domain: null,
_events: [Object],
_eventsCount: 2,
_maxListeners: undefined,
_writableState: [Object],
writable: false,
allowHalfOpen: false,
destroyed: true,
_bytesDispatched: 0,
_sockname: null,
_pendingData: null,
_pendingEncoding: '',
server: null,
_server: null,
write: [Function: writeAfterFIN],
_idleNext: null,
_idlePrev: null,
_idleTimeout: -1 },
stdout:
Socket {
connecting: false,
_hadError: false,
_handle: null,
_parent: null,
_host: null,
_readableState: [Object],
readable: false,
domain: null,
_events: [Object],
_eventsCount: 3,
_maxListeners: undefined,
_writableState: [Object],
writable: false,
allowHalfOpen: false,
destroyed: true,
_bytesDispatched: 0,
_sockname: null,
_pendingData: null,
_pendingEncoding: '',
server: null,
_server: null,
_idleNext: null,
_idlePrev: null,
_idleTimeout: -1,
write: [Function: writeAfterFIN] },
stderr:
Socket {
connecting: false,
_hadError: false,
_handle: null,
_parent: null,
_host: null,
_readableState: [Object],
readable: false,
domain: null,
_events: [Object],
_eventsCount: 3,
_maxListeners: undefined,
_writableState: [Object],
writable: false,
allowHalfOpen: false,
destroyed: true,
_bytesDispatched: 0,
_sockname: null,
_pendingData: null,
_pendingEncoding: '',
server: null,
_server: null,
write: [Function: writeAfterFIN],
read: [Function],
_consuming: true,
_idleNext: null,
_idlePrev: null,
_idleTimeout: -1 },
stdio: [ [Object], [Object], [Object] ] },
stdout: undefined,
stderr: undefined }
My cloud function looks like this:
/**
* When an image is uploaded in the Storage bucket We generate a thumbnail automatically using
* ImageMagick.
* After the thumbnail has been generated and uploaded to Cloud Storage,
* we write the public URL to Firestore.
*/
exports.generateThumbnail = functions.storage.object().onFinalize((object) => {
// File and directory paths.
const filePath = object.name;
const contentType = object.contentType; // This is the image MIME type
const fileDir = path.dirname(filePath);
const fileName = path.basename(filePath);
const thumbFilePath = path.normalize(path.join(fileDir, `${THUMB_PREFIX}${fileName}.png`));
const tempLocalFile = path.join(os.tmpdir(), filePath);
const tempLocalDir = path.dirname(tempLocalFile);
const tempLocalThumbFile = path.join(os.tmpdir(), thumbFilePath);
// Don't run when deleting files
if (object.resourceState === 'not_exists') {
console.log('Deleted file');
return null;
}
// Check if it's a eps, ps or ai file before proceeding
if (contentType != "application/postscript") {
console.log("We don't need to transform this file");
return null;
}
// Exit if the image is already a thumbnail.
if (fileName.startsWith(THUMB_PREFIX)) {
console.log('Already a Thumbnail.');
return null;
}
// Cloud Storage files.
const bucket = gcs.bucket(object.bucket);
const file = bucket.file(filePath);
const thumbFile = bucket.file(thumbFilePath);
const metadata = {
contentType: 'image/png',
// To enable Client-side caching you can set the Cache-Control headers here. Uncomment below.
// 'Cache-Control': 'public,max-age=3600',
};
// Create the temp directory where the storage file will be downloaded.
return mkdirp(tempLocalDir).then(() => {
// Download file from bucket.
return file.download({ destination: tempLocalFile });
}).then(() => {
console.log("The file has been downloaded to", tempLocalFile);
// Generate a thumbnail using ImageMagick.
return spawn('convert', ['-colorspace', 'sRGB', '-density', '300', tempLocalFile, '-resize', '400x400', tempLocalThumbFile]);
}).then(() => {
console.log('Thumbnail created at', tempLocalThumbFile);
// Uploading the Thumbnail.
return bucket.upload(tempLocalThumbFile, { destination: thumbFilePath, metadata: metadata });
}).then(() => {
console.log('Thumbnail uploaded to Storage at', thumbFilePath);
// Once the image has been uploaded delete the local files to free up disk space.
fs.unlinkSync(tempLocalFile);
fs.unlinkSync(tempLocalThumbFile);
// Get the Signed URLs for the thumbnail and original image.
const config = {
action: 'read',
expires: '03-01-2500',
};
return Promise.all([
thumbFile.getSignedUrl(config)
]);
}).then((results) => {
const thumbResult = results[0];
const thumbFileUrl = thumbResult[0];
console.log('Got Signed URLs: ' + results);
console.log('Thumb result:' + thumbResult);
console.log('Thumb file URL: ' + thumbFileUrl);
// Add the URLs to the Database
return admin.firestore().doc(fileDir).update({ thumb_src: thumbFileUrl, processed: true }).then(() => {
// write is complete here
console.log("Thumbnail URLs saved to database.");
});
}).catch((error) => {
console.error(error);
});
});
Let me know if I need to provide more information, but like I said - the code works for some EPS files. First I thought that the problem could be the file size of the input files, and that the conversion didn't wait for the download to finish - But I'm not sure if that's the case or not.