Note: I'm still working on a minimal reproduction, but you can check on the live site.
๐ bug
First, see this Twitter discussion with @jlengstorf.
I defined the following redirect in netlify.toml.
[[redirects]]
from = "/api/*"
to = "/.netlify/functions/:splat"
status = 200
Then in my application I have a serverless function located at /.netlify/functions/subscribe.
I hit it via a POST request using the browser's fetch API like this.
const options = {
method: "POST",
body: JSON.stringify(data),
headers: {"Content-Type": "application/json"},
}
const response = await fetch("/api/subscribe", options)
It returns an HTML document rather than the expected JSON output.
<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta http-equiv="x-ua-compatible" content="ie=edge"/><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/><meta name="note" content="environment=development"/><title data-react-helmet="true"></title><link href="https://fonts.googleapis.com/css?family=Inter|Roboto|Patua+One" rel="stylesheet"/><style type="text/css">
.anchor.before {
position: absolute;
top: 0;
left: 0;
transform: translateX(-100%);
padding-right: 4px;
}
.anchor.after {
display: inline-block;
padding-left: 4px;
}
h1 .anchor svg,
h2 .anchor svg,
h3 .anchor svg,
h4 .anchor svg,
h5 .anchor svg,
h6 .anchor svg {
visibility: hidden;
}
h1:hover .anchor svg,
h2:hover .anchor svg,
h3:hover .anchor svg,
h4:hover .anchor svg,
h5:hover .anchor svg,
h6:hover .anchor svg,
h1 .anchor:focus svg,
h2 .anchor:focus svg,
h3 .anchor:focus svg,
h4 .anchor:focus svg,
h5 .anchor:focus svg,
h6 .anchor:focus svg {
visibility: visible;
}
</style><script>
document.addEventListener("DOMContentLoaded", function(event) {
var hash = window.decodeURI(location.hash.replace('#', ''))
if (hash !== '') {
var element = document.getElementById(hash)
if (element) {
var scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop
var clientTop = document.documentElement.clientTop || document.body.clientTop || 0
var offset = element.getBoundingClientRect().top + scrollTop - clientTop
// Wait for the browser to finish rendering before scrolling.
setTimeout((function() {
window.scrollTo(0, offset - 0)
}), 0)
}
}
})
</script><link rel="preconnect" href="https://instagram.com"/><script src="/socket.io/socket.io.js"></script></head><body><div id="___gatsby"></div><script>
window.gatsbyLoadInstagram = function() {
var js = document.createElement('script');
var firstScript = document.getElementsByTagName('script')[0];
js.id = 'gatsby-plugin-instagram';
js.src = 'https://instagram.com/embed.js';
firstScript.parentNode.insertBefore(js, firstScript);
return true;
}
</script><script src="/commons.js"></script>
</body></html>
So it seems like the netlify dev command does not respect function redirects.
First get the project up and running.
git clone https://github.com/bradgarropy/dailytexascountry.com.git
cd dailytexascountry.com
npm install
netlify dev
Then go to the /store page and enter your email, which will kick off the API call to /api/subscribe.
Check the Network tab to see the unexpected HTML response.
The /api/subscribe endpoint should return a JSON object.
โโโโโโโโโโโโโโโโโโโโโ
Environment Info โ
โโโโโโโโโโโโโโโโโโโโโ
System:
OS: Windows 10 10.0.18363
CPU: (8) x64 Intel(R) Core(TM) i7-9700K CPU @ 3.60GHz
Binaries:
Node: 12.13.1 - D:\nodejs\node.EXE
Yarn: 1.22.4 - ~\AppData\Roaming\npm\yarn.CMD
npm: 6.14.5 - D:\nodejs\npm.CMD
Browsers:
Edge: 44.18362.449.0
netlify-cli/2.50.0 win32-x64 node-v12.13.1
@bradgarropy there was a Gatsby build error when I tried to run netlify dev. But running a static server with netlify dev --dir static, I was able to invoke the function correctly at http://localhost:8888/api/subscribe.
After running netlify dev locally, can you please try curl -vvv -d '{"something": true}' http://localhost:8888/api/subscribe and share the output!
@RaeesBhatti yea, the build requires some environment variables to be successful during data sourcing.
Here is the result of the curl command. It's the same HTML as returned from the deployed site.
Additionally, I have a console.log("SUBSCRIBE") as the very first line of my handler, but I don't see that logged in the terminal.
$ curl -X POST http://localhost:8888/api/subscribe -d '{"email": "[email protected]"}'
<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta http-equiv="x-ua-compatible" content="ie=edge"/><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/><meta name="note" content="environment=development"/><title data-react-helmet="true"></title><link href="https://fonts.googleapis.com/css?family=Inter|Roboto|Patua+One" rel="stylesheet"/><style type="text/css">
.anchor.before {
position: absolute;
top: 0;
left: 0;
transform: translateX(-100%);
padding-right: 4px;
}
.anchor.after {
display: inline-block;
padding-left: 4px;
}
h1 .anchor svg,
h2 .anchor svg,
h3 .anchor svg,
h4 .anchor svg,
h5 .anchor svg,
h6 .anchor svg {
visibility: hidden;
}
h1:hover .anchor svg,
h2:hover .anchor svg,
h3:hover .anchor svg,
h4:hover .anchor svg,
h5:hover .anchor svg,
h6:hover .anchor svg,
h1 .anchor:focus svg,
h2 .anchor:focus svg,
h3 .anchor:focus svg,
h4 .anchor:focus svg,
h5 .anchor:focus svg,
h6 .anchor:focus svg {
visibility: visible;
}
</style><script>
document.addEventListener("DOMContentLoaded", function(event) {
var hash = window.decodeURI(location.hash.replace('#', ''))
if (hash !== '') {
var element = document.getElementById(hash)
if (element) {
var scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop
var clientTop = document.documentElement.clientTop || document.body.clientTop || 0
var offset = element.getBoundingClientRect().top + scrollTop - clientTop
// Wait for the browser to finish rendering before scrolling.
setTimeout((function() {
window.scrollTo(0, offset - 0)
}), 0)
}
}
})
</script><link rel="preconnect" href="https://instagram.com"/><script src="/socket.io/socket.io.js"></script></head><body><div id="___gatsby"></div><script>
window.gatsbyLoadInstagram = function() {
var js = document.createElement('script');
var firstScript = document.getElementsByTagName('script')[0];
js.id = 'gatsby-plugin-instagram';
js.src = 'https://instagram.com/embed.js';
firstScript.parentNode.insertBefore(js, firstScript);
return true;
}
</script><script src="/commons.js"></script></body></html>
However, when I hit the non-redirected URL, everything works as expected.
$ curl -X POST http://localhost:8888/.netlify/functions/subscribe -d '{"email": "bradgarropy
@gmail.com"}'
{"subscription":{"id":2260910931,"state":"active","created_at":"2020-05-09T13:15:09.000Z","source":"API::V3::SubscriptionsController (external)","referrer":null,"subscribable_id":1378571,"subscribable_type":"form","subscriber":{"id":839901467}}}
@bradgarropy While netlify dev is running, can you try changing netlify.toml (add a new line or something). Can you see the following in terminal where netlify dev is running?
โ Reloading redirect rules from [ 'netlify.toml' ]
@RaeesBhatti Yes, making any change to netlify.toml causes that log message.
Can you also make sure that no other instance of netlify dev is running. Just run pkill node and netlify dev and try the curl command again
Confirmed there is only version of node / netlify dev running. Same results with curl, redirect URL does not work, but /.netlify/functions/subscribe does.
$ ps -a
PID PPID PGID WINPID TTY UID STIME COMMAND
754 1 754 6324 cons0 197609 13:38:17 /usr/bin/bash
816 754 816 9476 cons0 197609 13:43:40 /usr/bin/sh
775 1 775 11340 cons1 197609 13:42:17 /usr/bin/bash
837 775 837 20288 cons1 197609 13:44:13 /usr/bin/ps
823 816 816 7208 cons0 197609 13:43:41 /d/nodejs/node
Just did some more testing, looks like HTTP POST requests are not redirecting properly, but HTTP GET requests are.
I just tried this again on Window as well, and request rewrites and function invocation seem to be working fine for both GET and POST requests on [email protected].
Please share a reproduceable example of this, so that, I can track it down.
@RaeesBhatti, after further testing, seems as though Netlify's redirects are not working when using Gatsby! They work fine if you are using plain ole' HTML.
Here is the example repo, and the deployed site.
You'll notice that it works once deployed, but not using ntl dev.
I can confirm this issue on [email protected]. I've tested https://github.com/netlify/cli/pull/885 and it can't be reproduced on that branch. Thank you for providing the example. Please hold on until that PR is merged and released.
I'm having this same issue. Holding on for the new PR to be merged!!
Thanks for your hard work on this @RaeesBhatti! Any idea on when you will cut the release with the fix?
Thank you all for you patience. [email protected] has just been released which contains a fix for this issue.
Just updated to v2.51.0 and tested, everything works!
Just did some more testing, looks like HTTP
POSTrequests are not redirecting properly, but HTTPGETrequests are.
I'm currently experiencing this problem and have a new version of netlify installed:
netlify-cli/2.59.0 darwin-x64 node-v10.22.0
GET requests work fine, but POST requests stall. The request gets to my api server, but my handler is never called. I've got my redirect defined in a _redirects file like so:
/api/* http://localhost:5000/:splat 200
Am I missing something?
I've tried to see if it's my api server that's the problem by spinning up a simple test express server. That results in the same problem. I've inspected the difference between a successful request directly to the server and one that goes through the redirect. They look pretty identical, except for the origin.
When testing with a simple express server, I did notice that the on data event is never called, so my guess is that the body is not being forwarded with the redirect. Maybe that's causing problems since POST should have a body?
UPDATE: This bug needs to be reopened. I've just verified that the above doesn't happen with netlify/cli v2.51. I rolled back to that version since @RaeesBhatti said that version worked for him.
Thanks @michaelGregoire for reporting.
While the original issue is about redirecting to functions, I was able to reproduce your issue here:
https://github.com/erezrokah/netlify-build-reproductions/tree/cli/issue_890#netlify-build-reproductions
I'll follow up with an update once I have more information.
Thanks @erezrokah. I wasn't sure if I should open a new ticket or not.