I am trying to implement a simple email confirmation on signup flow using Angular 4, nodejs, mailgun-js and mailgun. The problem is the mailgun send:
mailgun.messages().send(data, function(error, body) {
console.log(body);
});
is timing out with the following error on the front-end:
POST http://localhost:3000/users/sendMail net::ERR_EMPTY_RESPONSE
core.js:1448 ERROR
HttpErrorResponse {headers: HttpHeaders, status: 0, statusText: "Unknown Error", url: null, ok: false, …}
error
:
ProgressEvent {isTrusted: true, lengthComputable: false, loaded: 0, total: 0, type: "error", …}
headers
:
HttpHeaders {normalizedNames: Map(0), lazyUpdate: null, headers: Map(0)}
message
:
"Http failure response for (unknown url): 0 Unknown Error"
name
:
"HttpErrorResponse"
ok
:
false
status
:
0
statusText
:
"Unknown Error"
url
:
null
__proto__
:
HttpResponseBase
The back-end show now errors but the return value (body) is undefined and the email is not sent. This is my complete back-end sendMail module:
const api_key = '<key-f40360259dea7c667ca06d4aee956421>';
const DOMAIN = '<sandbox836cdf3cfe9c467b916fe5bb0d73e7e7.mailgun.org>';
const mailgun = require('mailgun-js')({ apiKey: api_key, domain: DOMAIN });
// ---------------- sendMail variables -----
router.post('/sendMail', (req, res, next) => {
console.log("Email message data: " + JSON.stringify(req.body));
const data = {
from: 'xxxxdev#gmail.com',
to: [req.body.email, 'xxxxxxx#gmail.com'],
name: req.body.firstName,
code: req.body.workshopCode,
subject: req.body.workshopTitle,
text: req.body.messageBody
};
mailgun.messages().send(data, function(error, body) {
console.log(body);
});
});
Both From and To email are valid email address and the req.body displayed in the console.log is the correct data passed from the Front-End.
This the Front-end sendmail module:
sendEmailConfirmation(message) {
const headers = new HttpHeaders();
headers.append('Content-Type', 'application/x-www-form-urlencoded');
this.http.post('http://localhost:3000/users/sendMail', message).subscribe((data) => {
console.log('Mail return data: ' + data); >>>THIS LINE IS NEVER EXECUTED<<<<<<
},
);
}
What am I missing here??.....
I noticed the absence of a res.send so I added the following:
if (error) throw error;
else {
res.send('Email sent');
}
Now I get a forbidden error on the back-end:
(node:10780) UnhandledPromiseRejectionWarning: Error: Forbidden
at IncomingMessage.res.on (C:\connect2Server\node_modules\mailgun-js\lib\request.js:301:17)
at IncomingMessage.emit (events.js:165:20)
at endReadableNT (_stream_readable.js:1101:12)
at process._tickCallback (internal/process/next_tick.js:152:19)
(node:10780) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a ca
tch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 2)
Please make sure that if you are sending from Europe to also include the host like this:
const mg = mailgun({apiKey: MAILGUN_PRIVATE_API_KEY, domain: MAILGUN_DOMAIN_NAME, host:MAILGUN_HOST});
For Europe, host is api.eu.mailgun.net and for America it's api.mailgun.net from what I know.
Problem solved.....caused by typo in mailgun credentials. The '<' '>' brackets where copied over .....the clue was the Forbidden error.
Related
I used nested request by using axios. Initially requesting POST request for the token with key/secrets and then trying to get results in following GET request by using previous request's token.
var config = {
method: 'post',
url: gsecConfig.tokenUrl,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
data: data
};
axios(config)
.then(function (response) {
if (response.data.access_token) {
const config = {
headers: { Accept: 'application/json', Authorization: `Bearer ${response.data.access_token}` }
};
axios.get(gsecConfig.gsecUrl + gsecid, config)
.then(function (response) {
let supplierData = response.data;
res.status(200).json({
"data": supplierData
});
}).catch(function (error) {
res.status(error.response.status || error.response).json({
"errors": [error.response.data]
});
});
}
})
.catch(function (error) {
res.status(error.response.status || error.response).json({
"errors": [error.response.data]
});
});
while running the application getting below errors.
(node:32) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'status' of undefined
at /whitelist-v1/nodejs/routes/gsec.js:47:39
at process._tickCallback (internal/process/next_tick.js:68:7)
(node:32) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 2)
(node:32) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
It's highly likely your error doesn't have a .response member, making error.response.status failing. Errors may be decorated with .response only if they originate from the network - the standard Error object doesn't declare it.
So both catches should probably be more like:
res.status(error.response && error.response.status || 500).json({
"errors": [error.response && error.response.data || error.message]
});
If it's not error.response that yields an undefined, then your res is undefined, which should be more obvious to catch.
I just want to implement Joi in Hapi API.
server.route([
{
method: 'POST',
path: '/login',
config: {
tags: ['login', 'auth'],
auth: false,
validate: {
payload: payloadValidator,
failAction: (req, h, source, error) => {
console.log("Error ::: ", source.details[0].message);
return h.response({ code: 0, message: source.details[0].message });
}
}
},
handler: async (request, h) => {
console.log(request.payload.email);
console.log(request.payload.password);
...
}
}
]);
Hear I call payloadValidator.
const payloadValidator = Joi.object({
email: Joi.string().required(),
password: Joi.string().required()
}).options({ allowUnknown: true });
Actually I'm new with hapi and I'm missing something in my code. Can anyone help me to fix this issue?
Required output
If I do not pass email then the app must throw an error of Email is required and it should be the same with the password field also.
Error:
Error ::: "email" is required
Debug: internal, implementation, error
Error: Lifecycle methods called before the handler can only return an error, a takeover response, or a continue signal
at Request._lifecycle (/var/www/html/hapi/node_modules/#hapi/hapi/lib/request.js:326:33)
at process._tickCallback (internal/process/next_tick.js:68:7)
As an error suggests Lifecycle methods called before the handler can only return an error, a takeover response, or a continue signal you have to return takeover response.
return h.response({ code: 0, message: source.details[0].message }).takeover();
For more information you can visit this link : reference link
Sadly this question is not relevant anymore, since Microsoft decided to retire the api Read the details here
I am trying to implement skype interview api, when I provide payload to it, it throws JSON parsing error. If I provide an empty payload it works fine. When i provide any other payload mentioned here, it works. But as soon as I provide position code as mentioned in the above link it fails. Here is the code I am using -
exports.getLink = (req, res) => {
let payload = {
"code": "RENE2010"
}
, stringifyPayload = JSON.stringify(payload)
let token = generateToken(stringifyPayload)
fetch(config.skype.url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + token
},
body: stringifyPayload
})
.then(result => result.json())
.then(jsonResult => {
utils.sendResponse(res, jsonResult)
}, err => {
utils.sendResponse(res, null, 400, 'ERROR', err)
}).catch(ex => {
utils.sendResponse(res, null, 400, 'Exception', ex)
})
}
And here is the generateToken Method -
let generateToken = (content) => {
let token = jwt.sign({
jti: Guid.raw(),
iat: new Date().getTime(),
iss: config.skype.api_key,
sub: sha256(content),
exp: Math.floor(Date.now() / 1000) + 10
}, config.skype.app_secret)
return token
}
And here is the error which I am getting -
UnhandledPromiseRejectionWarning: FetchError: invalid json response body at https://interviews.skype.com/api/interviews reason: Unexpected token I in JSON at position 0
at /Users/xxx/node_modules/node-fetch/lib/index.js:272:32
at process._tickCallback (internal/process/next_tick.js:68:7)
(node:9550) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 2)
(node:9550) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
if I try to print the result without parsing into json this is the error I get -
{
size: 0,
timeout: 0,
[Symbol(Body internals)]:
{ body:
PassThrough {
_readableState: [ReadableState],
readable: true,
domain: null,
_events: [Object],
_eventsCount: 2,
_maxListeners: undefined,
_writableState: [WritableState],
writable: false,
allowHalfOpen: true,
_transformState: [Object] },
disturbed: false,
error: null },
[Symbol(Response internals)]:
{ url: 'https://interviews.skype.com/api/interviews',
status: 400,
statusText: 'Bad Request',
headers: Headers { [Symbol(map)]: [Object] },
counter: 0 } }
{ FetchError: invalid json response body at https://interviews.skype.com/api/interviews reason: Unexpected token I in JSON at position 0
at /Users/xxx/node_modules/node-fetch/lib/index.js:272:32
at process._tickCallback (internal/process/next_tick.js:68:7)
message:
'invalid json response body at https://interviews.skype.com/api/interviews reason: Unexpected token I in JSON at position 0',
type: 'invalid-json' }
The onError function from apollo-link-error has a populated graphQLErrors Object, but when ApolloClient throws an error object, the graphQLErrors property contains an empty array. Further inspection reveals the graphql error message in error.networkError.result.errors.
How can one properly configure Apollo Client to return a populated graphQLErrors object?
Apollo Client Setup:
const {ApolloClient} = require('apollo-client')
const { ApolloLink } = require('apollo-link')
const {HttpLink} = require('apollo-link-http')
const {onError} = require('apollo-link-error')
const {InMemoryCache} = require('apollo-cache-inmemory')
const errorLink = onError(({ graphQLErrors, networkError }) => {
if (graphQLErrors) {
graphQLErrors.map(({ message, locations, path }) =>
console.log(
`[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`,
),
)
}
if (networkError) console.log(`[Network error]: ${networkError}`)
})
const middleware = (req, ignored_res, next) => {
const client = new ApolloClient({
link: ApolloLink.from([errorLink, new HttpLink({ uri:'http://somegraphqlserver.com', fetch: require('node-fetch') })]),
cache: new InMemoryCache(),
})
req.GQLClient = client
return next()
}
module.exports = middleware
Calling apollo-server-express:
req.GQLClient
.query({
query: SOME_MALFORMED_QUERY,
})
.then((data) => {...})
.catch((error) => {
console.log('rawError', error)
console.log('error.networkError.result.errors', error.networkError.result.errors)
return next(error)
})
Console Results:
[GraphQL error]: Message: Cannot query field "blah" on type "CustomerList"., Location: [object Object], Path: undefined
[Network error]: Error: Response not successful: Received status code 400
rawError { Error: Network error: Response not successful: Received status code 400
at new ApolloError (/.../node_modules/apollo-client/bundle.umd.js:121:28)
at /.../node_modules/apollo-client/bundle.umd.js:1187:41
at /.../node_modules/apollo-client/bundle.umd.js:1620:17
at Array.forEach (<anonymous>)
at /.../node_modules/apollo-client/bundle.umd.js:1619:18
at Map.forEach (<anonymous>)
at QueryManager.broadcastQueries (/.../node_modules/apollo-client/bundle.umd.js:1614:22)
at /.../node_modules/apollo-client/bundle.umd.js:1114:31
at process._tickCallback (internal/process/next_tick.js:178:7)
graphQLErrors: [],
networkError:
{ Error: Response not successful: Received status code 400
at throwServerError (/.../node_modules/apollo-link-http-common/lib/bundle.umd.js:33:21)
at /.../node_modules/apollo-link-http-common/lib/bundle.umd.js:58:17
at process._tickCallback (internal/process/next_tick.js:178:7)
response:
Response {
size: 0,
timeout: 0,
[Symbol(Body internals)]: [Object],
[Symbol(Response internals)]: [Object] },
statusCode: 400,
result: { errors: [Array] } },
message: 'Network error: Response not successful: Received status code 400',
extraInfo: undefined }
error.networkError.result.errors [ { message: 'Cannot query field "blah" on type "CustomerList".',
locations: [ [Object] ] } ]
library versions:
Server:
"apollo-server-express": "^1.3.2"
Client:
"apollo-cache-inmemory": "^1.1.12"
"apollo-client": "^2.2.8"
"apollo-link-error": "^1.0.9"
"apollo-link-http": "^1.5.4"
This is by design. From the docs:
graphQLErrors: An array of errors from the GraphQL endpoint
networkError: Any error during the link execution or server response,
that wasn't delivered as part of the errors field in the GraphQL result
In other words, if your query is malformed, you request a field that isn't valid (like in your example), or hit any other issue that results in status other than 200, the error will appear as part of the networkError property. On the other hand, if the request returns a 200, but the errors array inside the response is populated, those same errors will be returned as part of graphQLErrors.
If you want to see an example of graphQLErrors being populated, format your query correctly but have one of your resolvers throw an error as soon as it's called. As long as the query doesn't hit any other issues, you should see the same error pop up inside graphQLErrors.
When I try to update a user using a web form, it runs a app.post on express. The object user is correct, but sometimes it throws a error in node console
app.post('/register/update', jsonParser, (request, response) => {
let user = request.body.user;
let users = mongoUtil.users();
console.log(user);
users.update({email: user.email}, user, (err, res) => {
if(err) {
response.sendStatus(400);
}
response.sendStatus(201);
});
});
In node console:
{ _id: '578246ec9eb0587a5d67b8c9',
email: 'test#test.com',
zipcode: '1231-123',
companyName: 'test',
tradeName: 'test',
contactName: 'Test',
tel: '(14) 1232-1231',
password: 'test',
passwordConfirm: 'test',
adress: 'test',
adressComplement: 'test',
adressNumber: '123' }
/home/ec2-user/ ... /mongodb/lib/utils.js:98
process.nextTick(function() { throw err; });
^
Error: Can't set headers after they are sent.
at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:346:11)
at ServerResponse.header (/home/ec2-user/ ... /node_modules/express/lib/response.js:719:10)
at ServerResponse.contentType (/home/ec2-user/ ... /node_modules/express/lib/response.js:552:15)
at ServerResponse.sendStatus (/home/ec2-user/ .. /node_modules/express/lib/response.js:340:8)
at users.update (/home/ec2-user/menuWebApp/server/app.js:94:14)
at handleCallback (/home/ec2-user/ ... /node_modules/mongodb/lib/utils.js:96:12)
at /home/ec2-user/ ... /node_modules/mongodb/lib/collection.js:1008:42
at commandCallback (/home/ec2-user/ ... /node_modules/mongodb/node_modules/mongodb-core/lib/topologies/server.js:1194:9)
at Callbacks.emit (/home/ec2-user/ ... /node_modules/mongodb/node_modules/mongodb-core/lib/topologies/server.js:119:3)
at Connection.messageHandler (/home/ec2-user/ ... /node_modules/mongodb/node_modules/mongodb-core/lib/topologies/server.js:358:23)
I'm probably dealing with a callback problem, but I don't have idea how to solve it D:
The error is not coming from the update statement itself its coming from your callback function.
Specifically these lines of code.
if(err) {
response.sendStatus(400);
}
response.sendStatus(201);
What you are doing is if there is an error send the status 400, then send the status 201. The problem is once you send a response with your headers to the requestor you can't try and set the headers again.
So your code should change to:
if(err) {
response.sendStatus(400);
}else{
response.sendStatus(201);
}
So if an error is generated you will send a 400 response otherwise you will send a 201 response instead of trying to send a 400 response and then a 201 response immediately after.