-
Notifications
You must be signed in to change notification settings - Fork 2.6k
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
Error: Expected a Response to be returned from queryRoute #4741
Comments
@alfonsocartes Are you able to provide a minimal reproduction or code sample of what your loader looks like and how you're getting the image from S3? That would help us dig into the root cause here. Thanks! |
Sure, the loader fetches from an external API through a resource route. It's based on this example: https://github.com/remix-run/examples/tree/main/file-and-s3-upload export async function loader({ request, params }: LoaderArgs) {
try {
// extract all the parameters from the url
const { key, width, height, fit, format } = extractParams(params, request);
if (
(width && !ALLOWED_IMAGE_SIZES.includes(width)) ||
(height && !ALLOWED_IMAGE_SIZES.includes(height))
) {
throw new Error(`Image size not allowed`);
}
return downloadImage(key, width, height, fit, format);
} catch (error: unknown) {
// if the image is not found, or we get any other errors we return different response types
return handleError(error);
}
} The downloadImage function calls an external API: return fetch(
`${process.env.API_URL}/images/${imageKey}?width=${width}&height=${height}&fit=${fit}&format=${format}`
); And the external API streams the image: router.get("/:imageKey", async (req, res) => {
try {
const { imageKey } = req.params;
const { width, height, fit, format } = req.query;
const w =
(typeof width === "string" && Number.parseInt(width)) || undefined;
const h =
(typeof height === "string" && Number.parseInt(height)) || undefined;
const f = fit != "undefined" ? (fit as keyof sharp.FitEnum) : undefined;
const type =
format != "undefined" ? (format as keyof sharp.FormatEnum) : undefined;
if (
w &&
typeof w === "string" &&
!ALLOWED_IMAGE_SIZES.includes(Number.parseInt(w))
) {
return res.status(400).send("Invalid width size");
}
if (
h &&
typeof h === "string" &&
!ALLOWED_IMAGE_SIZES.includes(Number.parseInt(h))
) {
return res.status(400).send("Invalid height size");
}
// Download image from S3
const readStream = await downloadFileFromS3(imageKey);
if (!readStream) {
return res.status(404).send("Image not found");
}
// Resize image accourding to query params
const resizedStream = streamingResize(readStream, w, h, f, type);
// Send the image to the client with the correct content type and cache control
const resHeaders = {
"Content-Type": `image/${type ?? "jpeg"}`,
"Cache-Control": "public, max-age=31536000, inmutable",
};
res.writeHead(200, resHeaders);
// This sends the stream straight to the client.
resizedStream.pipe(res);
} catch (error) {
console.error("POST /images/", error);
const resHeaders = {
"Content-Type": "text/plain",
"Cache-Control": "no-cache, no-store, must-revalidate",
};
res.set(resHeaders);
// error needs to be typed
const errorT = error as Error & { code: string };
// if the read stream fails, it will have the error.code ENOENT
if (errorT.code === "ENOENT") {
return res.status(404).json({ message: "Could not download image" });
}
// if there is an error processing the image, we return a 500 error
return res.status(500).json({ message: errorT.message });
}
}); export async function downloadFileFromS3(Key: string) {
const s3Client = new S3Client({
credentials: {
accessKeyId: AWS_ACCESS_KEY!,
secretAccessKey: AWS_SECRET!,
},
region: STORAGE_REGION,
});
const downloadParams = {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
Bucket: STORAGE_NAME!,
Key,
};
// return s3Client.getObject(downloadParams).createReadStream();
const s3Item = await s3Client.send(new GetObjectCommand(downloadParams));
console.info(
"Successfully downloaded " +
downloadParams.Key +
" from " +
downloadParams.Bucket +
"/" +
downloadParams.Key
);
if (s3Item.Body) {
const stream = s3Item.Body as Readable;
return stream;
} else {
throw new Error("No body");
}
} Thank you @brophdawg11 |
Have same problem with oracle. |
|
Thank you! This simple reproduction will be a big help. My initial hunch is that it's something with our |
Heya, I just bumped into this. I can confirm that it's response instances that are the problem. I added this console.log to console.log({
globalResponse: Response,
remixResponse: webFetch.Response,
responseIsGlobal: response instanceof Response,
responseIsRemix: response instanceof webFetch.Response,
responsesAreSame: Response === webFetch.Response,
}); Here's what I got:
Any |
Oh, and in my case I'm simply returning So it appears that somehow the global Node Response isn't getting overridden by the Remix Response for |
Yeah this boils down to the CJS |
All good! It works now. |
We're still seeing this error after updating to
We're calling Google Maps API and getting a 200 back, then get the above error. Sample snippet below:
|
@johnhayde Any chance you could look at whats returned from your loader there? Does it satisfy the check we're using for function isResponse(value: any): value is Response {
return (
value != null &&
typeof value.status === "number" &&
typeof value.statusText === "string" &&
typeof value.headers === "object" &&
typeof value.body !== "undefined"
);
} |
@brophdawg11 Here's the response object we're getting from our loader:
|
@brophdawg11 downgrading to 1.7.6 was not working for us either. We changed calls from |
@brophdawg11 1.8.2-pre.0 works! it fixed the issue. Thanks Matt. |
@johnhayde Huh - interesting. Glad it's working for you, but definitely curious why |
@brophdawg11 was also seeing this behavior returning from As in const response = await fetch("someurl");
console.log(response instanceof Response); // false |
This is released in @benbrandt That |
FYI, this update works for me 👍 Thanks! |
What version of Remix are you using?
1.8.0
Steps to Reproduce
I'm downloading an image from S3 with a resource route and I get Error: Expected a Response to be returned from queryRoute.
This doesn't happen in 1.7.6.
Expected Behavior
Get image
Actual Behavior
The text was updated successfully, but these errors were encountered: