Why is Plasmic overriding my http request with https

Hi!

It seems that Plasmic Studio overrides my request when I try to fetch an http address.
http://localhost:3000/api/create-checkout-session

Here is my code with the hardcoded adress

import { loadStripe } from '@stripe/stripe-js';
import React from 'react';

// Load Stripe with your publishable key
const stripePromise = loadStripe(process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY);

const CheckoutButton = ({ label }) => {
    const handleCheckout = async () => {
        console.log("Checkout button clicked");
        console.log("NEXT_PUBLIC_DOMAIN:", process.env.NEXT_PUBLIC_DOMAIN);
      
        const stripe = await stripePromise;
      
        const response = await fetch('http://localhost:3000/api/create-checkout-session', {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
            'Upgrade-Insecure-Requests': '0', // Explicitly prevent HTTPS upgrade
          },
        });
      
        if (!response.ok) {
          console.error('Failed to create checkout session:', response.statusText);
          return;
        }
      
        const session = await response.json();
      
        console.log("Checkout session created: ", session);
      
        const result = await stripe.redirectToCheckout({
          sessionId: session.id,
        });
      
        if (result.error) {
          console.error(result.error.message);
        }
      };

    return (
        <button onClick={handleCheckout}>
            {label || 'Subscribe Now'}
        </button>
    );
};

export default CheckoutButton;

And yet, when I click the button in the preview in Plasmic Studio, nothing happens and in the console I get the error telling me that I can’t open https://localhost… even tho it should only be trying to open http://localhost

It seems that there is an overiding done in the Plasmic Studio, because I tried this component in a simple page without Plasmic, and the Post works fine! There is a clean redirection to Stripe.

Any idea how I can circumvent that? Am I missing something?

Here is my project id: 4WayTwhC5fXHbkHxbvoXQQ

Hello @quentin_zakoian, I couldn’t reproduce this issue with a minimal example.

  1. I have a server running on localhost
  2. I configure custom app host on a Studio project.
  3. I create a code component that makes a GET request to the localhost server.
  4. I use the code component in the Studio. The GET request works all right.

Please let me know how your scenario differs from the abovementioned example.

Hi, thank you for the response.

I believe the issue may be tied specifically to how POST requests are handled in Plasmic Studio Preview Mode, as my scenario involves a POST request to http://localhost for creating a Stripe checkout session.

Key differences from the minimal example:

  1. I’m making a POST request to http://localhost:3000/api/create-checkout-session, not a GET request.
  2. In Plasmic Studio’s Preview Mode, the POST request is being forcibly redirected to https://localhost, resulting in an ERR_SSL_PROTOCOL_ERROR even though the URL is hardcoded as http://localhost.
  3. This exact setup works perfectly fine in a regular Next.js page when I bypass Plasmic Studio.

Could this be due to security policies in Plasmic Studio that treat POST requests differently, especially since it’s related to Stripe (a payment system)? Is there a way to disable this SSL enforcement for local development in Plasmic Studio?

Thank you!

I was still not able to reproduce the issue with a minimal POST request. Could you share a minimal sample project / POST request handler (without Stripe) that can help us reproduce this issue?

Hi Sarah, thank you so much for your reply!

I’ve created a minimal example that reproduces the issue without Stripe.

  1. I created a simple POST request to http://localhost:3000/api/echo that echoes back the request body.
  2. In Plasmic Studio Preview Mode, the POST request is still being forced to https://localhost, resulting in the ERR_SSL_PROTOCOL_ERROR.

You can see this issue in the minimal project:

  • POST endpoint: /api/echo
  • Project ID: 4WayTwhC5fXHbkHxbvoXQQ

Here is my file pages/api/echo.js

export default function handler(req, res) {
    if (req.method === 'POST') {
      // Echo back the request body as a response
      return res.status(200).json({ received: req.body });
    }
  
    return res.status(405).json({ message: 'Only POST requests allowed' });
  }
  

Here is my file components/CheckoutButton.jsx

import React from 'react';

const CheckoutButton = ({ label }) => {
    const handleCheckout = async () => {
        console.log("Checkout button clicked");

        const response = await fetch('http://localhost:3000/api/echo', {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
            'Upgrade-Insecure-Requests': '0',
          },
          body: JSON.stringify({ message: 'Test POST request' }),
        });

        if (!response.ok) {
          console.error('Failed to send POST request:', response.statusText);
          return;
        }

        const data = await response.json();
        console.log("Response from /api/echo:", data);
      };

    return (
        <button onClick={handleCheckout}>
            {label || 'Send POST Request'}
        </button>
    );
};

export default CheckoutButton;

Here is my file pages/plasmic-host.jsx

import * as React from 'react';
import { PlasmicCanvasHost, registerComponent } from '@plasmicapp/react-web/lib/host';
import CSVUploadComponent from '../components/CSVUploadComponent.jsx';
import MappingComponent from '../components/MappingComponent.jsx';
import CSVFlowComponent from '../components/CSVFlowComponent.jsx';
import supabase from '../supabaseClient.jsx'; // Import the Supabase client
import CSVFlowComponentProducts from '../components/CSVFlowComponentProducts.jsx';
import MappingComponentProducts from '../components/MappingComponentProducts.jsx';
import { useEffect, useState } from 'react';
import CheckoutButton from '../components/CheckoutButton.jsx';




// You can register any code components that you want to use here; see
// https://docs.plasmic.app/learn/code-components-ref/
// And configure your Plasmic project to use the host url pointing at
// the /plasmic-host page of your nextjs app (for example,
// http://localhost:3000/plasmic-host).  See
// https://docs.plasmic.app/learn/app-hosting/#set-a-plasmic-project-to-use-your-app-host

// registerComponent(...)



registerComponent(CSVUploadComponent, {
  name: 'CSVUploadComponent',
  importPath: './components/CSVUploadComponent',
  props: {
    onParsedData: {
      type: 'eventHandler',
      argTypes: [
        {
          name: 'data',
          type: 'array',
        },
      ],
      description: 'Callback when CSV data is parsed',
    },
  },
});



registerComponent(MappingComponent, {
  name: 'MappingComponent',
  importPath: './components/MappingComponent',
  props: {
    csvData: {
      type: 'array',
      defaultValue: [],
      description: 'Parsed CSV data for mapping',
    },
    onMappingComplete: {
      type: 'eventHandler',
      argTypes: [
        {
          name: 'mapping',
          type: 'object',
        },
      ],
      description: 'Callback when mapping is completed',
    },
  },
});


registerComponent(MappingComponentProducts, {
  name: 'MappingComponentProducts',
  importPath: './components/MappingComponentProducts',
  props: {
    csvData: {
      type: 'array',
      defaultValue: [],
      description: 'Parsed CSV data for mapping',
    },
    onMappingComplete: {
      type: 'eventHandler',
      argTypes: [
        {
          name: 'mapping',
          type: 'object',
        },
      ],
      description: 'Callback when mapping is completed',
    },
  },
});


registerComponent(CSVFlowComponent, {
  name: "CSVFlowComponent",
  importPath: './components/CSVFlowComponent',
  importName: "CSVFlowComponent",
  isDefaultExport: true,
  props: {
    shopId: {
      type: 'string',
      defaultValue: '',
      description: 'Shop ID to be assigned to each customer',
    },
  },
});

// Register Product Flow Components
registerComponent(CSVFlowComponentProducts, {
  name: "CSVFlowComponentProducts",
  importPath: './components/CSVFlowComponentProducts',
  importName: "CSVFlowComponentProducts",
  isDefaultExport: true,
  props: {
    shopId: {
      type: 'string',
      defaultValue: '',
      description: 'Shop ID to be assigned to each product',
    },
  },
});

registerComponent(CheckoutButton, {
  name: 'CheckoutButton',
  importPath: '../components/CheckoutButton.jsx',
  props: {
    label: {
      type: 'string',
      defaultValue: 'Subscribe Now',
      description: 'The label text for the checkout button',
    },
  },
});




const PlasmicHost = () => {
  return <PlasmicCanvasHost />;
}



export default PlasmicHost;

And here is the error I get when I click the Custom CheckoutButton in the preview mode in Plasmic (the grey button):

This seems to be caused by nextjs redirecting …/api/echo to …/api/echo/

For some reason the HTTPS is added in this redirect.

Can you use …/api/echo/ (with the trailing /) and see if that fixes it for you?

1 Like

Thank you so much!