solid-start icon indicating copy to clipboard operation
solid-start copied to clipboard

[Feature?]: patch `fetch` on the server to allow calling api endpoints

Open huseeiin opened this issue 11 months ago • 5 comments

Duplicates

  • [x] I have searched the existing issues

Latest version

  • [x] I have tested the latest version

Summary 💡

this doesn't work on the server currently:

import { createAsync, query } from "@solidjs/router";
import { Suspense } from "solid-js";

const getData = query(async () => {
  "use server";

  const res = await fetch("/api");

  return res.json();
}, "data");

export default function Home() {
  const data = createAsync(() => getData());

  return (
    <Suspense fallback={<p>Loading...</p>}>{JSON.stringify(data())}</Suspense>
  );
}

Examples 🌈

i'm getting this error: Failed to parse URL from /api

Motivation 🔦

this is implemented in sveltekit among other frameworks

huseeiin avatar Jan 31 '25 11:01 huseeiin

I believe accepting relative paths aren't a good enough reason to patch prototype or introducing a compile-time change.

const fetchData = query(async () => {
  "use server";
  const r = await fetch("http://localhost:3001/api", { method: "GET" });
  const re = await r.json();

  console.log(re);
  return re.body;
}, "fetchData");

This would work just fine and is in-tune with every spec implementation of the Fetch API.

Our premise in Solid is to keep a light abstraction on top of the platform (as little compilation as possible) and protect security best-practices.


Additionally, I'd possibly question the necessity of making an actual fetch request from one server function to another, not really sure I understood the use-case here.

atilafassina avatar Feb 01 '25 18:02 atilafassina

I believe accepting relative paths aren't a good enough reason to patch prototype or introducing a compile-time change.

"http://localhost:3001/api" is not good because that is a network call.

and about your other point, reasons why you may want to call fetch() in a server function:

  1. migrating an old backend
  2. exposing a unified api that your frontend and other frontends can use

and this doesn't need compilation, it is a runtime patch. and solidstart already has nitro's $fetch btw, but its broken in dev mode.

huseeiin avatar Feb 01 '25 18:02 huseeiin

this works in production only (it will work in dev once we get nitro in dev support in solidstart):

await getRequestEvent()
  ?.nativeEvent.fetch("/api-endpoint")
  .then((res) => res.json());

huseeiin avatar Jun 13 '25 14:06 huseeiin

try this:

import { isServer } from 'solid-js/web'

export const apiPrefix: string = isServer ? import.meta.env.VITE_API_PREFIX : '/api'

Eliot00 avatar Jun 26 '25 13:06 Eliot00

try this:

import { isServer } from 'solid-js/web'

export const apiPrefix: string = isServer ? import.meta.env.VITE_API_PREFIX : '/api'

that doesn't have anything to do with this issue

huseeiin avatar Jun 26 '25 13:06 huseeiin

i found a way!

create fetch-plugin.ts

import type { NitroApp } from "nitropack";

export default (e: NitroApp) => {
  globalThis.fetch = e.localFetch;
};

then in your config:

import { defineConfig } from "@solidjs/start/config";

export default defineConfig({
  server: {
    preset: "node-server",
    plugins: ["./fetch-plugin.ts"],
  },
});

huseeiin avatar Aug 08 '25 17:08 huseeiin