[Feature?]: patch `fetch` on the server to allow calling api endpoints
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
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.
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:
- migrating an old backend
- 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.
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());
try this:
import { isServer } from 'solid-js/web'
export const apiPrefix: string = isServer ? import.meta.env.VITE_API_PREFIX : '/api'
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
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"],
},
});