简体   繁体   中英

nextjs POSt API not working in live environment, but working perfect on local

I have recently started learning now to build web apps using Nextjs, so I decided to build a simple app to play around with and learn. I was developing locally and everything was working perfectly. However, when I deploy to vercel the POST function doesn't work.

The app is very simple, it displays some data on the home page, and there is a page to enter new data - using prisma SQLite.

Pulling data from the DB working fine on the home page, but when I try to insert data, it fails with the error message below;

Failed to load resource: the server responded with a status of 500 ()

as well as

adddata:1 Uncaught (in promise) SyntaxError: Unexpected end of JSON input

It isn't have anything to do with ENV variables because I didn't set any on this app. And everything works perfectly on my localhost. Please see below for the code on the adddata page

import Head from 'next/head'
import { useState } from 'react';

import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient();

export default function AddData(props) {

    const [formData, setFormData] = useState({})

    const [responseMessage, setResponseMessage] = useState()

    const [lastEntryMiles, setLastEntryMiles] = useState()
    
    const addLastMillage = () => {
        setLastEntryMiles(props.lastEntry.miles);
        document.getElementById('lastEntry').focus();
    }

    async function saveItem(e) {

        e.preventDefault()

        const response = await fetch('/api/addfuelitem/', {
            method: 'POST',
            body: JSON.stringify(formData),
        })
        
        if(!response.ok){
            // throw new Error(response.statusText);
            setResponseMessage(response.statusText);
        }
        if(response.ok){

            setResponseMessage("Sucess!!");
            window.setTimeout(function(){
                window.location.href = "/";        
            }, 2000);
        }

        return await response.json()

    }

    return (
        <>
            <Head>
                <title>Add Data Fuel Tracker</title>
                <meta name="description" content="Custom Fuel Tracker" />
            </Head>
            <section>
                <div className="container p-5">
                    <div className="text-center"><h2>Add Fuel Data</h2></div>

                    <form onSubmit={saveItem}>
                        <div className="mb-3">
                            <label htmlFor="miles" className="form-label">Enter the current millage</label>
                            <input type="number" className="form-control" id="miles" name="miles" onChange={e => setFormData({ ...formData, miles: +e.target.value })} />
                        </div>
                        <div className="mb-3">
                            <label htmlFor="volume" className="form-label">Enter the volume of fuel</label>
                            <input type="number"step="0.01" className="form-control" id="volume" name="volume" onChange={e => setFormData({ ...formData, volume: +e.target.value })} />
                        </div>
                        <div className="mb-3">
                            <label htmlFor="cost" className="form-label">Enter the total cost of the fuel</label>
                            <input type="number"step="0.01" className="form-control" id="cost" name="cost" onChange={e => setFormData({ ...formData, cost: +e.target.value })} />
                        </div>
                        <div className="mb-3">
                            <a className="btn btn-primary" onClick={addLastMillage}>Add Last Millage</a>
                        </div>
                        <div className="mb-3">
                            <label htmlFor="lastEntry" className="form-label">Last Millage</label>
                            <input type="number" className="form-control" id="lastEntry" name="lastEntry" defaultValue={props.lastEntry.miles} onChange={e => setFormData({ ...formData, lastEntry: +e.target.value })} />
                        </div>
                        <div className="mb-3">
                            <label htmlFor="station" className="form-label">Enter the name of the petrol station (optional)</label>
                            <input type="text" className="form-control" id="station" placeholder="Enter the name of the petrol station (optional)" name="station" onChange={e => setFormData({ ...formData, station: e.target.value })} />
                        </div>
                        <div className="col-12">
                            <button className="btn btn-primary" type="submit" >Submit form</button>
                        </div>
                        <div className="col-12 responseMessage">{ responseMessage }</div>
                    </form>
                </div>
            </section>

        </>
    )
}

export async function getStaticProps(){

    const getLastEntry = await prisma.fuelitem.findFirst({
        orderBy: {
          id: 'asc',
        },
        take: -1, // Reverse the list
    })
  
    return {
      props:{
        lastEntry:JSON.parse(JSON.stringify(getLastEntry))
      }
    }
  
}

And then below this is the api page

import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient();

export default async function handler(req, res) {

  const data = JSON.parse(req.body)

  const costLitre = data.cost / data.volume
  const gallons = data.volume * 0.219
  const milesTrip = data.miles - data.lastEntry
  const mpg = milesTrip / gallons

  const savedfuelitem = await prisma.fuelitem.create({
    data:{
      miles: data.miles,
      volume: data.volume,
      cost: data.cost,
      station: data.station,
      costLitre: costLitre,
      milesTrip: milesTrip,
      mpg: mpg
    }
  })

  res.json(savedfuelitem)
  
}

EDIT for more information

the server logs are

[POST] /api/addfuelitem
00:20:39:30
info  - Loaded env from /var/task/.env
2021-10-21T23:20:40.899Z    2e81b793-c28e-4ead-9448-411a4e8c11b7    ERROR   PrismaClientInitializationError: Error querying the database: unable to open database file: /var/task/node_modules/.prisma/client/./data.db
    at cb (/var/task/node_modules/@prisma/client/runtime/index.js:38543:17)
    at async handler (/var/task/.next/server/pages/api/addfuelitem.js:26:25)
    at async Object.apiResolver (/var/task/node_modules/next/dist/server/api-utils.js:101:9)
    at async Server.handleApiRequest (/var/task/node_modules/next/dist/server/next-server.js:770:9)
    at async Object.fn (/var/task/node_modules/next/dist/server/next-server.js:661:37)
    at async Router.execute (/var/task/node_modules/next/dist/server/router.js:205:32)
    at async Server.run (/var/task/node_modules/next/dist/server/next-server.js:841:29)
    at async Server.handleRequest (/var/task/node_modules/next/dist/server/next-server.js:292:20)
    at async Server.<anonymous> (/var/task/___next_launcher.js:32:9) {
  clientVersion: '3.3.0',
  errorCode: undefined
}
2021-10-21T23:20:40.899Z    2e81b793-c28e-4ead-9448-411a4e8c11b7    ERROR   PrismaClientInitializationError: Error querying the database: unable to open database file: /var/task/node_modules/.prisma/client/./data.db
    at cb (/var/task/node_modules/@prisma/client/runtime/index.js:38543:17)
    at async handler (/var/task/.next/server/pages/api/addfuelitem.js:26:25)
    at async Object.apiResolver (/var/task/node_modules/next/dist/server/api-utils.js:101:9)
    at async Server.handleApiRequest (/var/task/node_modules/next/dist/server/next-server.js:770:9)
    at async Object.fn (/var/task/node_modules/next/dist/server/next-server.js:661:37)
    at async Router.execute (/var/task/node_modules/next/dist/server/router.js:205:32)
    at async Server.run (/var/task/node_modules/next/dist/server/next-server.js:841:29)
    at async Server.handleRequest (/var/task/node_modules/next/dist/server/next-server.js:292:20)
    at async Server.<anonymous> (/var/task/___next_launcher.js:32:9) {
  clientVersion: '3.3.0',
  errorCode: undefined
}
RequestId: 2e81b793-c28e-4ead-9448-411a4e8c11b7 Error: Runtime exited with error: exit status 1
Runtime.ExitError

But there is not any response body, only the response headers which is

cache-control: s-maxage=0
content-disposition: inline; filename="500"
content-type: text/html; charset=utf-8
date: Thu, 21 Oct 2021 23:20:41 GMT
server: Vercel
strict-transport-security: max-age=63072000; includeSubDomains; preload
x-matched-path: /500
x-vercel-cache: MISS
x-vercel-id: lhr1::964nh-1634858438937-e662abbca7b4

You're trying to connect to a sqlite database/file inside your Vercel server. This isn't possible because

  1. You likely haven't initialized the sqlite database.
  2. Vercel functions run inside lambdas, so they are non persistent (which you don't want for your database).

I would suggest switching to a hosted database solution (PostgreSQL, MySQL or SQL Server). You can find more information about deploying to Vercel in the Prisma docs .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM