-
Notifications
You must be signed in to change notification settings - Fork 27k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Failed to parse URL when fetching localhost using Server Components #48344
Comments
If you run the That is to say that you need an absolute URL. The browser, per spec IIRC, assumes paths relative to the document base URL/origin or something like that. It is a fun read 😅 |
Got it. Besides that, I think throwing a more guiding error will help. Something like "Failed to parse URL. Pass an absolute URL when using server components" |
Yeah, but that's a fetch, a native API to node, that's crashing. Not sure it's a good idea to hijack that. Another framework, Nuxt, uses $fetch, made by them to allow for the request to call into the API route from the server. https://nuxt.com/docs/guide/concepts/server-engine#direct-api-calls Without such helpers, the problem is that you'd be making yet another request round trip, when you are already at the server side. So you should just invoke the data you want directly, that's one of the reasons we are writing the components on the server. That means connecting to your database or data endpoints from the server component without having to involve API routes at all. |
I see, it's true that the request is really redundant when I can just import the function directly, and it's even typesafe because I don't need to cast the response after fetching. Thanks :) |
Because server components run on the server, they essentially act like a node server. That's why requesting '/path' won't resolve (same behavior as a regular server). You need to specify absolute paths for the URL to be parsed (e.g 'http://localhost/path') |
I found this solution and it works fine:
|
Similar use case here, I try to fetch an asset in the My understanding is that it would require to write server-specific code (if server, use server fetch, else on the client, use client fetch), although we are fetching the same resource on the same path in both cases. Isn't it against the spirit of simplifying the SSR to make it just work, by running the same code on client and server? I didn't want to write the domain in the config for that use case, so I used the Thanks! |
Confirm: Within a page aka server component fetching a local api endpoint returns a: Error [TypeError]: Failed to parse URL... |
Is it a valid way to fix this by using the import { headers } from "next/headers";
const fetchData = async (host: string) => {
const res = await fetch(`http://${host}/api/quizzes`);
return res.json();
};
export default async function Dashboard() {
const host = headers().get("host");
const data = await fetchData(host!);
return <div>{JSON.stringify(data)}</div>;
} |
The problem is still that you trigger a new round trip, out to the internet and back to the server itself. Just fetch the data from the root source in the Server Component. |
How do you pass query params in this case? |
any update about it? I have found the same solution but methods needs request and param but they are sended by url
|
Sorry, not an issue. Just make sure the localhost you are calling is either public or there is a correct secret passed via headers |
This is even happening in client components, is that expected? What is the correct way to "opt out" of code running on the server? Docs (https://nextjs.org/docs/app/building-your-application/rendering/static-and-dynamic-rendering) seem to suggest that using the |
I used the following technique and we can pass query params by adding question mark after the 'api/test?id=123'. the url itself doesn't matter as we know which api function we are calling and only require query params. import { NextRequest } from 'next/server' import TestListClient from './list'; |
Any update for this? |
Following |
Update? |
async function getAllPosts(){
const host = headers().get("host");
const protocal = process?.env.NODE_ENV==="development"?"http":"https"
let res = await fetch(`${protocal}://${host}/api`, { cache: "no-store" });
let posts = res.json();
return posts;
} guys try this. |
What if you're not using Server Components and still getting the |
if you are not using a server component you can directly call with a relative URL fetch('/api'); |
I think it may help those who are looking for this error on pages marked as 'use client'. In my case I have this folder structure:
I was unable to fetch from /weather/page.js vs /weather/api/cities until I switched from:
to
|
I had the same problem you just need to create a util function export function getBaseUrl() {
if (typeof window !== 'undefined') return '';
const vc = process.env.VERCEL_URL;
if (vc) return `https://${vc}`;
return 'http://localhost:8081';
} |
This closed issue has been automatically locked because it had no new activity for 2 weeks. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you. |
Verify canary release
Provide environment information
Operating System: Platform: linux Arch: x64 Version: #22 SMP Tue Jan 10 18:39:00 UTC 2023 Binaries: Node: 16.17.0 npm: 8.15.0 Yarn: 1.22.19 pnpm: 7.1.0 Relevant packages: next: 13.3.1-canary.6 eslint-config-next: 13.3.0 react: 18.2.0 react-dom: 18.2.0
Which area(s) of Next.js are affected? (leave empty if unsure)
App directory (appDir: true)
Link to the code that reproduces this issue
https://codesandbox.io/p/github/Amirko28/next13-test/draft/intelligent-cherry?file=%2Fapp%2Fcomponents%2Fpost-list%2Findex.tsx&selection=%5B%7B%22endColumn%22%3A51%2C%22endLineNumber%22%3A2%2C%22startColumn%22%3A30%2C%22startLineNumber%22%3A2%7D%5D&workspace=%257B%2522activeFilepath%2522%253A%2522%252Fapp%252Fcomponents%252Fpost-list%252Findex.tsx%2522%252C%2522openFiles%2522%253A%255B%2522%252FREADME.md%2522%252C%2522%252Fapp%252Fapi%252Fposts%252FgetAll.ts%2522%252C%2522%252Fapp%252Fapi%252Fposts%252Fcreate.ts%2522%252C%2522%252Fapp%252Fcomponents%252Fpost-list%252Findex.tsx%2522%252C%2522%252Fapp%252Fcomponents%252Fadd-post%252Findex.tsx%2522%255D%252C%2522sidebarPanel%2522%253A%2522EXPLORER%2522%252C%2522gitSidebarPanel%2522%253A%2522COMMIT%2522%252C%2522spaces%2522%253A%257B%2522clgf51ety000x356ilg8ae35d%2522%253A%257B%2522key%2522%253A%2522clgf51ety000x356ilg8ae35d%2522%252C%2522name%2522%253A%2522Default%2522%252C%2522devtools%2522%253A%255B%257B%2522type%2522%253A%2522UNASSIGNED_PORT%2522%252C%2522port%2522%253A3000%252C%2522url%2522%253A%2522jiwe3j-3000.csb.app%2522%252C%2522key%2522%253A%2522clgf57pcp02n0356igg3gw2oz%2522%252C%2522isMinimized%2522%253Afalse%257D%252C%257B%2522type%2522%253A%2522TERMINAL%2522%252C%2522shellId%2522%253A%2522clgf53qdd0010g0i3cey03oke%2522%252C%2522key%2522%253A%2522clgf52ztc008e356ixn6ferp2%2522%252C%2522isMinimized%2522%253Afalse%257D%255D%257D%257D%252C%2522currentSpace%2522%253A%2522clgf51ety000x356ilg8ae35d%2522%252C%2522spacesOrder%2522%253A%255B%2522clgf51ety000x356ilg8ae35d%2522%255D%252C%2522hideCodeEditor%2522%253Afalse%257D
To Reproduce
run
pnpm dev
and go to port 3000 for it to crash in runtimeDescribe the Bug
Calling
fetch
within a server component in order to get data from the same host fails:fetch('/api/posts')
throws an error:TypeError: Failed to parse URL from /api/posts
.However, fetching the same URL within a client component works fine.
Trying to access the resource with
fetch('http://localhost:3000/api/posts')
does work.In the attached CodeSandbox repo:
Fetch in a server component -> app/components/post-list/index.tsx - line 3
Fetch in a client component -> app/components/add-post/index.tsx - line 15
Expected Behavior
Calling
fetch('/api/posts')
should work inside server componentsWhich browser are you using? (if relevant)
Chrome 111.0.5563.147
How are you deploying your application? (if relevant)
No response
The text was updated successfully, but these errors were encountered: