'How to force something to run serverside in NextJS

I'm trying to build a website and have a API to handle requests using my private keys (so they aren't publicly accasible). However I also sign data send to this API, each user got their own key pair and for logged out user I have a genaral keypair. However I am now trying to handle a captcha request but it tries to run my function clientside, thus not having access to my API key which is stored in a environment variable. How do I force my function to run server-side. Error:

Unhandled Runtime Error
TypeError: Cannot read properties of undefined (reading 'length')

Source
pages\contact.js (69:21) @ _callee$

  67 | const data = { "token":token };
  68 | const publicKey = 'website';
> 69 | const hmac = crypto.createHmac('sha256', process.env.PUBLIC);
     |             ^
  70 | const signature = Buffer.from('sha256=' + hmac.update(JSON.stringify(data)).digest('hex'), 'utf8');
  71 | axios.post('https://api.com/' + 'grecaptcha', data, {headers: {'Signature-256': signature, key: publicKey}}).then(resp => {
  72 |     if ( resp.status === 200 ){

Function:

function Form(props) {
    let [form, setForm] = useState({});
    const { executeRecaptcha } = useGoogleReCaptcha();

    const handleChange = (event) => {
        const name = event.target.name
        const value = event.target.value
        setForm(values => ({...values, [name]: value}))
    }

    const handleReCaptchaVerify = useCallback(async () => {
        if (!executeRecaptcha) {
            props.setErrorText(['Please try again later.'])
            props.setIsError(true)
            return;
        } else if (!(form.name && form.email && form.subject && form.message )) {
            props.setErrorText(['All fields are required.'])
            props.setIsError(true)
            return
        }
        const token = await executeRecaptcha();
        const data = { "token":token };
        const publicKey = 'website';
        const hmac = crypto.createHmac('sha256', process.env.PUBLIC);
        const signature = Buffer.from('sha256=' + hmac.update(JSON.stringify(data)).digest('hex'), 'utf8');
        axios.post('https://api.com/' + 'grecaptcha', data, {headers: {'Signature-256': signature, key: publicKey}}).then(resp => {
            if ( resp.status === 200 ){
                const data = form;
                const publicKey = 'website';
                const hmac = crypto.createHmac('sha256', process.env.PUBLIC);
                const signature = Buffer.from('sha256=' + hmac.update(JSON.stringify(data)).digest('hex'), 'utf8');
                axios.post('https://api.com/' + 'contact', data, {headers: {'Signature-256': signature, key: publicKey}}).then(res => {
                    if ( res.status === 200 ) {
                        props.setIsSuccess(true)
                    } else {
                        props.setErrorText(['Please try again.'])
                        props.setIsError(true)
                    }
                })
            } else {
                props.setErrorText(['reCAPTCHA not valid.'])
                props.setIsError(true)
            }
        })
    }, [form, executeRecaptcha, props])

    return (
        <div className={props.isSuccess ? 'text-center filter blur' : props.isError ? 'text-center filter blur' : 'text-center'} >
            <Header text="If you'd like to contact me please fill out the form below"/>
            <div className="contact-outer-div">
                <div className="contact-inner-div">
                    <TextForm text="Name" name="name" placeholder="Name" onChange={handleChange} value={form.name || ""} />
                    <TextForm text="Email address" name="email" placeholder="[email protected]" onChange={handleChange} value={form.email || ""} />
                    <TextForm text="Subject" name="subject" placeholder="Subject" onChange={handleChange} value={form.subject || ""} />
                    <Message onChange={handleChange} value={form.message || ""} />
                    <Submit onClick={handleReCaptchaVerify} />
                </div>
            </div>
        </div>
    )
}

I get the error, it can't read the length of undefined, so how do I force this function to run server-side so it can access environment variables without exposing them.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source