Open tmountjr opened 2 years ago
Hey Tom, You picked a very complex topic and there might be really a bug in it, so take everything I tell you with a grain of salt,
When creating your own FSXA-PWA, the FSXA-NUXT-MODULE creates an fsxa-api (explicitly a FSXARemoteApi). The RemoteApi is registered as server middleware. It contains the apikey for the backend, so we cannot use the RemoteApi to make requests on clientside. To use a FSXA-API on clientside we created the FSXAProxyApi. The ProxyApi than uses the server middleware for communication. We're also using SSR which makes it even more complex. maybe this is the reason you see the same request multiple times in the logs. Some requests are made by the SSR process, some requests are forwarded by the ProxyApi and some requests are logging from the RemoteApi (server middleware).
In general a serverless approach is possible. A former colleague of mine got a fsxa-pwa instance to work in Vercel and he said it worked ootb. I hope my answer could help you a little bit. :-)
That helps, thanks. So to summarize what you said in my own words, there are really two APIs - the FSXARemoteApi, which runs as server middleware, and the FSXAProxyApi, which is what actually dispatches the request to the CMS.
It sounds like the request path then is:
Request -> FSXARemoteApi -> FSXAProxyApi -> CMS
Is that accurate?
We first send the request to the proxy and after to the remote api, so the right path is:
Request -> FSXAProxyApi -> FSXARemoteApi -> CMS
Ah, ok, thanks. I think we need to identify where the request handoff is breaking down - I suspect it's between the Proxy
and Remote
stages but we'll need to confirm that for sure.
As a debug tip: Check the response you're actually getting via Rest client e.g. postman. Just Send a POST request to [SERVER]/api/fsxa/navigation with the payload from the log.
Looks like you get a html page as response (the "<" character), while json is expected.
@tmountjr Is this issue still relevant or could you solve it with the given information?
It's relevant, I just haven't had the time to dig into this in any detail. I plan on working on it today.
On Wed, Nov 2, 2022 at 4:17 AM henczi-espirit @.***> wrote:
@tmountjr https://github.com/tmountjr Is this issue still relevant or could you solve it with the given information?
— Reply to this email directly, view it on GitHub https://github.com/e-Spirit/fsxa-nuxt-module/issues/76#issuecomment-1299780533, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAJF3W4XE3YX6ADTSKUGQYLWGIPQXANCNFSM6AAAAAARPCMHSA . You are receiving this because you were mentioned.Message ID: @.***>
I turned up the logging all the way to 0
in the fsxa config and i'm getting some unexpected results. Locally, when I run a production build with just Nuxt (eg. nuxt build --standalone && nuxt start
, the debug output only references the Remote API:
ℹ INFO Express-Server | Received POST on route | /navigation
ℹ DEBUG Express-Server | POST request body | {"initialPath":"/","locale":"en_GB"}
ℹ DEBUG FSXARemoteApi | fetchNavigation | start | {"locale":"en_GB","initialPath":"/"}
ℹ DEBUG FSXARemoteApi | [buildNavigationServiceUrl] | {"locale":"en_GB","initialPath":"/"}
ℹ DEBUG FSXARemoteApi | [buildNavigationServiceUrl] | Using locale: en_GB
ℹ DEBUG FSXARemoteApi | fetchNavigation | url | https://redacted?depth=99&format=caas&language=en_GB
ℹ DEBUG FSXARemoteApi | fetchNavigation | response | 200
ℹ DEBUG FSXARemoteApi | fetchNavigation | response ok | true
But when I do a production build with our platform, I get additional debug output from the Proxy API and nothing from the Remote API:
DEBUG FSXAProxyApi | FSXAProxyApi created | {"baseUrl":"http://localhost:3001/api/fsxa"}
DEBUG FSXAApiSingleton | FSXA-Api initialized with api: | {"mode":"proxy","_baseUrl":"http://localhost:3001/api/fsxa","_method":"POST","_headers":{"Content-Type":"application/json"},"_enableEventStream":false,"_logger":{"_logLevel":"0","_name":"FSXAProxyApi"}}
Initializing app {
payload: { defaultLocale: 'de_DE', initialPath: '/api/fsxa/navigation' }
}
DEBUG FSXAProxyApi | fetchNavigation | start | {"locale":"de_DE","initialPath":"/api/fsxa/navigation"}
DEBUG FSXAProxyApi | fetchNavigation | body | {"body":{"initialPath":"/api/fsxa/navigation","locale":"de_DE"}}
DEBUG FSXAProxyApi | fetch | start | {"baseUrl":"http://localhost:3001/api/fsxa","url":"/navigation","options":{"method":"POST","headers":{"Content-Type":"application/json"},"body":"{\\"initialPath\\":\\"/api/fsxa/navigation\\",\\"locale\\":\\"de_DE\\"}"},"isServer":true,"isClient":false,"window":"undefined"}
It's at this stage that I enter that restart loop. It's worth noting that using our platform, skipping the production build and simply running things in dev mode shows the same debug output as I get when running nuxt
.
(I wonder if this is because the API is trying to ping localhost:3001
which, when we run our dev instance, essentially runs nuxt
on port 3001, and then runs our own server on port 3000, so port 3001 is still available and answering requests.)
It looks like (and I might be wrong) the FSXAProxyApi
doesn't come into play when the only thing running is nuxt itself. Is that accurate? Is there something that triggers the use of the proxy api in between the request and remote based on some condition?
Hey Tom, Sorry for the late answer.
When I do a production build with our platform, I get additional debug output from the Proxy API and nothing from the Remote API
This is pretty unusual. Could you turn off ssr and try that again? https://github.com/e-Spirit/fsxa-pwa/blob/master/nuxt.config.ts#L5 It seems that you're getting client logs and not the log messages from the server.
Also in the documentation https://github.com/e-Spirit/fsxa-pwa/blob/master/docs/modules/ROOT/pages/Introduction.adoc#running-the-application-in-a-production-environment we link to the Dockerfile.template https://github.com/e-Spirit/fsxa-pwa/blob/master/Dockerfile.template to show developers which steps we do, to get to a production deployment. Do you get any errors when following this or do is everything working when you try to start the PWA locally/in docker?
In our team we were not sure which is your real concern. Maybe you can clarify this for us.
Simply disabling SSR caused some additional errors on our platform that may take some time to track down.
Taking a step back, I gave some thought to how the application behaves running natively with nuxt
vs. how it behaves using our platform's proxy. Just running nuxt dev
or nuxt start
, requests to localhost:3000/api/fsxa/...
are processed directly, which I would expect. When running under our proxy, the behavior is a little different.
Our routing and edge infrastructure runs locally at :3000
and starts up nuxt at :3001
. Requests to :3000/api/fsxa/navigation
for example are passed to :3001/api/fsxa/navigation
with the same payload, and I can see additional headers that we inject. Now, on our dev instance, because that nuxt installation on port 3001 is wide open, that request succeeds. (In dev mode, we're basically running npx nuxt --port 3001
.) In prod mode, though, we're running Nuxt programmatically via http.createServer
and following https://nuxtjs.org/docs/internals-glossary/nuxt/ for importing the nuxt core and running loadNuxt('start')
. This means that there's no server running at port 3001; however the request is still dispatched to :3001/api/fsxa/navigation
which obviously fails.
I still have some testing to do with a bare-bones Nuxt app and some middleware to see if I can compare how requests would be handled using middleware I know I've gotten to work properly.
Hey folks, I think I finally have the issue fully understood - let me try to lay out my findings and we can talk about next steps.
Near as I can tell, requests from the PWA to /
are expected to be server-side rendered. The SSR component of the application uses the FSXAProxyApi
to initiate requests to a few endpoints under /api/fsxa/*
, which in turn start up the FSXARemoteApi
to dispatch one or more requests to whatever URL is specified in the FSXA_NAVIGATION_SERVICE
environment variable. The responses from that call are pieced together, filtered, etc., and then returned as the result of the POST
call to the /api/fsxa/*
route, which the SSR component uses to render the HTML response and serves it back to the browser.
Assuming all that is reasonably accurate, the part where we started running into problems was the fact that the FSXAProxyApi
was by default sending requests to localhost:3000/api/fsxa/*
. The defaults are configured in the templates/plugin.js
file. Now, I discovered a bug on our platform - we apparently were not reading the nuxt.config.TS
file (only nuxt.config.JS
) and so no matter what we did the NUXT_HOST
and NUXT_PORT
variables were never being populated in the publicRuntimeConfig
part of the nuxt config file, leading to that localhost
address always being used. We fixed that bug and are now processing the typescript config file properly. Based on some previous comments here, it looks like the assumption is that this module will be used in a containerized infrastructure, or at least one where the SSR environment will be able to respond to requests to localhost
. Our platform is not set up to allow requests to localhost
while in the SSR environment, which I think is the core of the issue here, likely the same with Netlify (though I don't know how their platform works under the hood), and potentially explains why we also had issues usingnuxt-start
to bootstrap the application. (The Netlify and nuxt-start
parts are speculation, but it would make sense.) So when the request is being sent to localhost
, it's immediately being denied. I don't know why this resulted in an infinite loop - perhaps we were trying to proxy the request to localhost:3001
which was being redirected by Nuxt...hard to say. I'm actually less concerned with why things broke down at that point, and more satisfied understanding that's where things broke down.
I did get this "fixed" to a point - after my colleagues fixed the typescript bug, I was able to set the values of NUXT_HOST
and NUXT_PORT
via the publicRuntimeConfig
key. Because setting those values to something that isn't localhost
was messing up my local development, here's a snippet from my config file:
if ('REMOTE_API_HOST' in process.env) {
config.publicRuntimeConfig = {
...config.publicRuntimeConfig,
NUXT_HOST: process.env.REMOTE_API_HOST,
NUXT_PORT: '443'
}
}
export default config
In my .env
file locally, I just don't specify REMOTE_API_HOST
; and deployed, I set it to the same hostname that the site uses. This means the rendering process looks like this:
/
handled by SSRFSXAProxyApi
starts up with a baseUrl
value of the same domain that the application is running on publiclyFSXAProxyApi
dispatches a few requests to the serverMiddleware api routeFSXARemoteApi
receives those requests, dispatches calls to the CMS, and returns the response to the FSXAProxyApi
FSXAProxyApi
returns those responses/results to the SSR processThere is one final piece, and this is the question in #75 - all things being equal, that request will be dispatched to http://[domain]:443
which won't work because HTTP requests aren't being served by port 443. I did try http://[domain]:80
and relying on our platform's ability to respond with a 301 to the HTTPS domain, but those redirects are not being followed. So I had to fork the module, patch it, build it, and push it up to our GH account so that we could use the patched version. Long term that's not sustainable, but I have validated that it works for now.
Ultimately I think the assumption that localhost
will always be accessible and/or that traffic to /api/fsxa/*
will only ever be over HTTP potentially limits the number of places that this module can be deployed. Our platform developers are looking at the localhost
issue internally to see if that's something that we can/would support, but for anyone else in the same boat who can't access localhost
from within the SSR context, the hard-coded HTTP is the other barrier to entry.
Happy to discuss further, and if I've gotten the request flow or any assumptions incorrect, please let me know. Thanks!
My team and I have been working on deploying this PWA to Edgio (https://docs.edg.io/guides/nuxt) and are running into some challenges with the serverMiddleware component of the module. High-level, when we deploy to our platform, our CLI first runs
nuxt build --standalone
, then bundles the result of that and uploads it to our platform. The serverless/SSR components are moved over to an AWS Lambda instance. The platform runs Nuxt in a protected environment using an arbitrary port and then exposes the Nuxt routes on port 443 for TLS requests. We also have the ability to run this configuration locally for quicker development - in that case, Nuxt runs on port 3001 and the CLI essentially proxies it on port 3000.What we're seeing when we run the standalone build as part of our platform is that any request to the application results in a near-infinite flood of status messages:
I wouldn't call this a "redirect" issue, more like a "request restart." On our infrastructure, the request first hits our proxy layer on
:3000
, and our layer requests the same route from Nuxt on:3001
. Best we can tell at this point, because of the value ofproxyApiConfig.serverUrl
(templates/plugin.js:36
) the request is dispatched back tolocalhost:3000
which starts the loop over again. I have tried a few ways of gettingNUXT_PORT
to be 3001 - I've put that value in a.env
file, hard-coded it innuxt.config.ts
as part of thepublicRuntimeConfig
key, and prefixed my build and run commands withNUXT_PORT=3001
and I've been unable to see a change in behavior or to confirm that what I'm doing is making any difference.As part of the troubleshooting as well, I went into
node_modules/fsxa_nuxt_module/templates.plugin.js
and hardcoded the host and port value to match the production environment, which gives a clearer picture of the issue, especially in the logs:It looks like the middleware is repeating the request rather than handling it transparently like I would expect middleware to do (eg. if the middleware is going to dispatch a request to the CMS, why doesn't the middleware simply do that? It appears here that the express server receives the POST request but then re-requests it.). It's possible that I'm misunderstanding how the proxy config is set up but the code makes it appear as though the request is being re-dispatched.
I have confirmed that running
npx nuxt build --standalone && npx nuxt start
without any special port considerations lets the system work properly. I realize this may not be a bug with the module per se but I was hoping that someone with some more experience with the overall architecture of this module might be able to take a look.