Nextjs API folder call - 500 error in production - api

I have an api folder in my next.js app for some server side endpoints:
import { NextApiRequest, NextApiResponse } from 'next'
import Cors from 'cors'
// Initializing the cors middleware
const cors = Cors({
methods: ['GET', 'HEAD', 'POST'],
origin: '*',
optionsSuccessStatus: 200,
})
// Helper method to wait for a middleware to execute before continuing
// And to throw an error when an error happens in a middleware
function runMiddleware(req, res, fn) {
return new Promise((resolve, reject) => {
fn(req, res, (result) => {
if (result instanceof Error) {
return reject(result)
}
return resolve(result)
})
})
}
export default async (req, res) => {
await runMiddleware(req, res, cors)
const POSKEY = process.env.POSKEY
const PAYEE = process.env.PAYEE
const { currency, url, locale, price } = req.body
const currentUrl = url
const apiResult = await fetch(
'https://api.test.barion.com/v2/Payment/Start',
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': 3495,
},
body: JSON.stringify({
PosKey: POSKEY,
PaymentType: 'Immediate',
GuestCheckout: true,
FundingSources: ['All'],
Currency: currency,
RedirectUrl: currentUrl,
CallbackUrl: currentUrl,
Locale: locale,
Transactions: [
{
Payee: PAYEE,
Total: price,
Items: [
{
Name: 'Teszt',
Description: 'Test item comment',
Quantity: 1,
Unit: 'pc',
UnitPrice: 1,
ItemTotal: 1,
SKU: 'SM-01',
},
],
},
],
}),
}
)
.then((result) => {
return result.json()
})
.catch((error) => {
console.error(error)
})
res.status(200).json({ url: apiResult.GatewayUrl })
}
When I call the endpoint, in development it works perfectly:
But in production I got 500 error. (deployed to vercel)
Error in the console on vercel:
[POST] /apigateway/ 23:30:28:53
2022-06-27T21:30:28.595Z e8c57750-4647-4e7a-b62e-6221abc141ac ERROR Error: Cannot find module '/var/task/node_modules/next/dist/server/next.js'.
Please verify that the package.json has a valid "main" entry
at tryPackage (internal/modules/cjs/loader.js:321:19)
at Function.Module._findPath (internal/modules/cjs/loader.js:534:18)
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:888:27)
at Function.Module._load (internal/modules/cjs/loader.js:746:27)
at Module.require (internal/modules/cjs/loader.js:974:19)
at require (internal/modules/cjs/helpers.js:101:18)
at Object.5199 (/var/task/.next/server/pages/api/gateway.js:20:39)
at webpack_require (/var/task/.next/server/webpack-api-runtime.js:25:42)
at webpack_exec (/var/task/.next/server/pages/api/gateway.js:109:39)
at /var/task/.next/server/pages/api/gateway.js:110:28 { code: 'MODULE_NOT_FOUND', path:
'/var/task/node_modules/next/package.json', requestPath: 'next' }
RequestId: e8c57750-4647-4e7a-b62e-6221abc141ac Error: Runtime exited
with error: exit status 1 Runtime.ExitError
What other configuration should I add to my next.config file to make it work, I am beginner with this api.
UPDATE:
This solved my problem... https://github.com/vercel/next.js/issues/34844

The problem was with the .js file wrong import:
Same issue here: https://github.com/vercel/next.js/issues/34844#issuecomment-1055628706
TLDR:
Remove the import { NextApiRequest, NextApiResponse } from "next";

Related

AWS SDK for JavaScript v3 PutObjectCommand error 'A header you provided implies functionality that is not implemented'

I'm trying to upload a file with node.js from my client app (electron) to an S3 bucket in this manner:
const { S3Client, PutObjectCommand } = require('#aws-sdk/client-s3');
const s3Client = new S3Client({
region: 'eu-central-1',
credentials: {
accessKeyId: 'access',
secretAccessKey: 'secret',
},
});
const uploadFileToS3 = async (f) => {
const bucketParams = {
ACL: 'private',
Bucket: 'bucket',
Key: f.name,
Body: f.data,
ServerSideEncryption: 'AES256',
ContentType: 'image/png',
};
try {
return await s3Client
.send(new PutObjectCommand(bucketParams))
.then((result) => {
return process.send({
type: 'success',
fileName: f.name,
result,
});
});
} catch (erro) {
process.send({
type: 'error',
fileName: f.name,
error: erro,
});
}
};
process.on('message', (file) => {
uploadFileToS3(file);
});
I get the following error, that I'm unable to understand:
error: {
name: 'NotImplemented',
'$fault': 'client',
'$metadata': {
httpStatusCode: 501,
requestId: 'PXEBV6H4MX3',
extendedRequestId: 'yyyyyy',
attempts: 1,
totalRetryDelay: 0
},
Code: 'NotImplemented',
Header: 'Transfer-Encoding',
RequestId: 'PXEBV6H4MX3',
HostId: 'yyyyyy',
message: 'A header you provided implies functionality that is not implemented'
}
The file is a buffer generated with:
fs.readFileSync(pth)
Any idea of what could caused this error ?
Seems like the buffer created with
fs.readFileSync(pth)
was rejected and I could only use a stream:
const readableStream = await createReadStream(Buffer.from(f));
Maybe I'm wrong but it is possible that the actual SDK version is unable to accept a buffer yet, this could be the reason for that "missing functionality" message.

react native iOS Apollo - TypeError: Network request failed - URI accessible from outside the app

I've got a graphql URI that I need to query from my react-native App. This URI is public and I've got access to its schema/structure when I simply type the URI in my browser.
As soon as I try to query it from my code, I get the [TypeError: Network request failed] error (logs are created in the function that builds my ApolloClient).
I've checked the URI a million time, it's the same as the one I put in my browser, and the one I've used in the past to successfully query the DB.
This is the client-building function:
export function initServices({
uri,
authToken,
mockMeanDelay = 400,
mock = false,
mockScenarios = [],
}: Options): Services {
let mockRemoteController = null;
let linkToOutsideWorld: ApolloLink;
const messageBus = createMessageBus();
const terminatingLink = createUploadLink({
uri: CORRECT_URI_HERE,
})
const authLink = setContext(async (_, { headers }) => {
const token = await authToken();
return {
headers: {
...headers,
authorization: token ? `Bearer ${token}` : '',
},
};
});
linkToOutsideWorld = from([authLink, withCustomScalars(), terminatingLink]);
const errorReportingLink = onError(({ graphQLErrors, networkError }) => {
if (graphQLErrors)
graphQLErrors.forEach(({ message, locations, path }) =>
// eslint-disable-next-line no-console
console.error(
`[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`,
),
);
// eslint-disable-next-line no-console
if (networkError) console.error(`[Network error]: ${networkError}`);
});
const link = ApolloLink.from([errorReportingLink, linkToOutsideWorld]);
const fragmentMatcher = new IntrospectionFragmentMatcher({
// #ts-ignore
introspectionQueryResultData: introspectionResult,
});
const apolloClient = new ApolloClient({
link,
defaultOptions: {
watchQuery: {
// We prefer using a `cache-and-network` policy so that screens
// are always in sync with backend
// Otherwise, the default policy would not fetch the server
// data from server if the result of query is already in cache
fetchPolicy: 'cache-and-network',
},
},
cache: new InMemoryCache({
cacheRedirects: {
Query: {
// #ts-ignore issue in typing of cacheRedirects
userById: (_, { userId }: QueryUserByIdArgs, { getCacheKey }) =>
getCacheKey({ __typename: 'User', id: userId }),
// #ts-ignore issue in typing of cacheRedirects
gatheringSpaceById: (
_,
{ gatheringSpaceId }: QueryGatheringSpaceByIdArgs,
{ getCacheKey },
) =>
getCacheKey({
__typename: 'GatheringSpace',
id: gatheringSpaceId,
}),
// #ts-ignore issue in typing of cacheRedirects
gatheringInstanceById: (
_,
{ gatheringInstanceId }: QueryGatheringInstanceByIdArgs,
{ getCacheKey },
) =>
getCacheKey({
__typename: 'GatheringInstance',
id: gatheringInstanceId,
}),
},
},
fragmentMatcher,
}),
});
return { apolloClient, messageBus, mockRemoteController };
}
When I replace the URI with another publicly available one, it seems to work so my guess is that there's an issue with the back-end side. But how is it possible that I have full access to the schema and queries with my browser?
Any tips to help debugging are welcome too!
Thanks for your help!

POST request freezes after add body-parser

I'm build vue app, and for mine app need api request to server from client, also necessary proxy any request.
It's mine vue.config.js
const producer = require('./src/kafka/producer');
const bodyParser = require('body-parser')
module.exports = {
devServer: {
setup: function (app, server) {
app.use(bodyParser.json())
app.post('/send-message', function (req, res) {
producer.send(req.body)
.then(() => {
res.json({result: true, error: null});
})
.catch((e) => {
res.status(500).json({result: false, error: e});
})
});
},
proxy: {
'/v2/order/by-number': {
target: 'http://address-here'
}
}
}
};
As you can see so i'm use body-parser app.use(bodyParser.json())
After I added it, proxying stopped working for me. Request to /send-message freezes after show me error
Proxy error: Could not proxy request path-here from localhost:8080
to http://address-here
Internet searches have not led to a solution.
For a long time, i find a solution:
Add second param jsonParser to app.post()
See full example
const producer = require('./src/kafka/producer');
const bodyParser = require('body-parser')
const jsonParser = bodyParser.json({limit: '1mb'});
module.exports = {
devServer: {
setup: function (app, server) {
app.post('/send-message', jsonParser, function (req, res) {
producer.send(req.body)
.then(() => {
res.json({result: true, error: null});
})
.catch((e) => {
res.status(500).json({result: false, error: e});
})
});
},
proxy: {
'path': {
target: 'http://address-here'
}
}
}
};

Two custom methods/endpoints using loopBack, one works, the other gives a 401

I created two custom endpoints with Loopback.
Account.deleteAllHearingTests = function (req, callback) {
console.log('here comes the req to delete all hearing tests', req);
Account.findById(req.accessToken.userId)
.then(account => {
if (!account) {
throw new Error('cannot find user');
}
return app.models.HearingTest.updateAll({ accountId: account.id }, { isDeleted: new Date() });
})
.then(() => {
callback(null);
})
.catch(error => {
callback(error);
})
}
Account.remoteMethod(
'deleteAllHearingTests', {
http: {
path: '/clearHearingTests',
verb: 'post'
},
accepts: [
{ arg: 'req', type: 'object', http: { source: 'req' } }
],
returns: {}
}
);
the second one looks like this.
Account.deleteSingleHearingTest = function (req, callback) {
// console.log('accounts.js: deleteSingleHearingTest: are we being reached????', req)
Account.findById(req.accessToken.userId)
.then(account => {
if (!account) {
throw new Error('Cannot find user');
}
console.log('account.js: deleteSingleHearingTest: req.body.hearingTestId N: ', req.body.hearingTestId);
return app.models.HearingTest.updateAll({ accountId: account.id, id: req.body.hearingTestId }, { isDeleted: new Date() });
})
.then(() => {
callback(null);
})
.catch(error => {
callback(error);
});
}
Account.remoteMethod(
'deleteSingleHearingTest', {
http: {
path: '/deleteSingleHearingTest',
verb: 'post'
},
accepts: [
{ arg: 'req', type: 'object', description: 'removes a single hearing test', http: { source: 'req' } }
],
description: 'this is the end point for a single delete',
returns: {}
}
);
};
The first custom method returns a 401 status response when I make the initial fetch. The second returns a 200.
Inside my actions file the first method is called with something that looks like this:
export function deleteAllHearingTests() {
return (dispatch, getState) => {
let state = getState();
if (!state.user || !state.user.accessToken || !state.user.accessToken.id || !state.user.accessToken.userId) {
console.debug('deleteAllHearingTests', state.user);
// TODO: ERROR
return;
}
fetch(SERVERCONFIG.BASEURL + '/api/Accounts/clearHearingTests?access_token=' + state.user.accessToken.id, {
method: 'POST',
headers: SERVERCONFIG.HEADERS
})
.then(response => {
console.log('here is your response', response);
if (response.status !== 200) {
throw new Error('Something is wrong');
}
return response.json()
})
the second method is called with
export const deleteSingleHearingTest = (hearingTestNumber) => {
return (dispatch, getState) => {
let state = getState();
if (!state.user || !state.user.accessToken || !state.user.accessToken.id || !state.user.accessToken.userId) {
console.debug('writeTestResult', state.user);
// TODO: ERROR
return;
}
console.log('single delete ', SERVERCONFIG.BASEURL + '/api/Accounts/deleteSingleHearingTest?access_token=' + state.user.accessToken.id)
fetch(SERVERCONFIG.BASEURL + '/api/Accounts/deleteSingleHearingTest?access_token=' + state.user.accessToken.id, {
method: 'POST',
headers: SERVERCONFIG.HEADERS,
body: JSON.stringify({ "hearingTestId": hearingTestNumber })
})
.then(response => {
console.log('getting response from initial fetch inside deleteSingleReqport', response);
They are nearly identical, however, one works..the other fails. What are some possible causes for the 401?
Did you try to call those methods with external tool like a postman, so you would exactly know if you don't miss access_token or something else? Also, when you compare code from one function and another, you can see that you are colling the updateAll with different arguments. It's hard to say without original code, but maybe the issue is there? Compare below:
return app.models.HearingTest.updateAll(
{ accountId: account.id },
{ isDeleted: new Date() });
return app.models.HearingTest.updateAll(
{ accountId: account.id, id: req.body.hearingTestId },
{ isDeleted: new Date() });
Additionally, in fetch method they are also diffferences, you are missing in one case the below:
body: JSON.stringify({ "hearingTestId": hearingTestNumber })
What you could also do to debug and to provide more data is to run server in debug mode by calling:
export DEBUG=*; npm start

Catch error server response with #nuxtjs/auth

I'm trying to catch the error response for #nuxtjs/auth but it doesn't seem to return anything but undefined.
It refuses to login if I include the user so I want to know why it's returning undefined.
CONFIG:
auth: {
strategies: {
local: {
endpoints: {
login: {
url: 'http://127.0.0.1:80/api/login',
method: 'post',
propertyName: 'token'
},
logout: false,
user: {
url: 'http://127.0.0.1:80/api/me',
method: 'get',
propertyName: undefined
}
},
tokenRequired: true,
tokenType: 'bearer',
}
},
plugins: [
'#/plugins/auth.js'
]
},
PLUGIN:
export default function ({ app }) {
app.$auth.onError((error, name, endpoint) => {
console.error(name, error)
});
}
VIEW FUNCTION:
- both handleSuccess and handleFailure returns undefined.
login() {
this.toggleProcessing(0);
let payload = {
username: 'admin',
password: 'admin123'
}
let handleSuccess = response => {
console.log(response);
this.toggleProcessing(0);
}
let handleFailure = error => {
console.log(error);
this.toggleProcessing(0);
}
this.$auth.loginWith('local', { data: payload }).then(handleSuccess).catch(handleFailure);
},
You can use e.response
async login() {
try {
const login = {
username: this.username,
password: this.password
}
let response = await this.$auth.loginWith('local', { data: login })
console.log('response', response)
} catch (e) {
console.log('Error Response', e.response)
}
}
I fell into the same problem and after spending some time i found out a very good way to catch the response. The solution is to use the axios interceptor. Just replace your plugin file code with the following
export default function ({$axios, $auth}){
$axios.interceptors.response.use(function (response) {
// Do something with response data
return response;
}, function (error) {
// Do something with response error
return Promise.reject(error);
});
}
I'm not sure initially what might be wrong here because I can't see the complete nuxt.config.js and your full component but here are a few things to check:
#nuxtjs/axios is installed
Both axios and auth modules are registered in the modules section of nuxt.config.js:
modules: [
'#nuxtjs/axios',
'#nuxtjs/auth'
]
Also, ensure the middleware property for auth is set in the component/page component.
Ensure you're following the documentation on this page: https://auth.nuxtjs.org/getting-starterd/setup
Ive been using try -> this.$auth.loginWith to catch error server response with #nuxtjs/auth.
login() {
const data = { form };
try {
this.$auth
.loginWith("local", { data: data })
.then(api => {
// response
this.response.success = "Succes";
})
.catch(errors => {
this.response.error = "Wrong username/password";
});
} catch (e) {
this.response.error = e.message;
}
},
Specify the token field in the nuxt.config
strategies: {
local: {
endpoints: {
login: { // loginWith
url: "auth/login",
method: "post",
propertyName: "data.token" // token field
},
user: { // get user data
url: "auth/user",
method: "get",
propertyName: "data.user"
},
}
}
},
modules: ["#nuxtjs/axios", "#nuxtjs/auth"],