VueJs Vite build for production undefined properties - vuejs3

Using Vue 3 to build a form input page. Exporting default props in the <script setup> block with reference to the docs as follows:
<script setup>
...
const props = defineProps({
orgName: String,
contactName: String,
contactEmail: String,
addressLine1: String,
addressLine2: String,
city: String,
stateAbbrev: String,
zip: String
})
const emit = defineEmits([
'update:orgName',
'update:contactName',
'update:contactEmail',
'update:addressLine1',
'update:addressLine2',
'update:city',
'update:stateAbbrev',
'update:zip'
])
...
Using the props in the <template> block as follows:
<template>
....
<form #submit.prevent="onSubmit" class="add-form">
<input
class="form_input"
type="text"
id="OrgName"
v-model="orgName"
#input="$emit('update:orgName', $event.target.value)"
required
placeholder="Organization Name"
/>
<input .....
/>
.....
</form>
....
</template>
I'm using Vite to build the distributable. Running in development mode locally, page renders and responds to input fields and submits data to the API request just fine. Using Vue Developer tools, I can see the following responses from the props variable.
I'm deploying the distributable in a container running in an nginx server in a container behind a load balancer. App builds and deploys without issue and is accessible as desired. However, when I start to hit the form input fields, I receive the following errors in the console:
Uncaught ReferenceError: orgName is not defined
at a.onUpdate:modelValue.t.<computed>.t.<computed> [as _assign] (organization-add-page.98800913.js:1:2044)
at HTMLInputElement.<anonymous> (index.0b002e58.js:1:58059)
a.onUpdate:modelValue.t.<computed>.t.<computed> # organization-add-page.98800913.js:1
(anonymous) # index.0b002e58.js:1
This same message, but with respective property names, occur on each field in the form.
I'm having a hard time trying to figure out if this is a Vite build setting/issue, nginx setting/issue, or something else. I haven't found the magical SO or Google search as most results come back regarding environment variable deployment issues which I have working successfully.
My nginx config is fairly straightforward, and works across all pages in the app.
server {
listen 80;
listen [::]:80;
server_name localhost;
#access_log /var/log/nginx/host.access.log main;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
include /etc/nginx/mime.types;
try_files $uri $uri/ /index.html;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
I'm trying to figure out next steps in troubleshooting the production version of the app deployed when it works as expected locally running in dev mode.

Related

Intercept all nginx requests to serve series of static content?

Question: Is there a way to 'intercept' more specific locations? Before many locations (e.g., location /activity, location = /search, location ~ "^/content/([a-f\d]{24})/$", etc.), I would like to do potentially serve html and then handle the original request.
Background: An nginx.conf I'm working with serves up a series of html pages (e.g., international agreement page, location page, supplier welcome page, etc.) following user SSO login and the user attempting to access a URL of our product.
The current nginx configuration works by adding a try_files $uri /<location that could serve .html page>?redirecturi=$redirecturi; to many location blocks. This is cumbersome because numerous locations point to the same location (e.g., /landing as seen below); it would be more maintainable to have a single location as an entry point to this 'flow' of html pages.
Example location block that refers to a location (e.g., /landing) that can server html
location /workitem {
...
auth_request /auth;
...
recursive_error_pages on;
try_files $uri /landing?redirecturi=$redirecturi;
}
Example location that can serve html
location = /landing {
internal;
...
proxy_method GET;
proxy_pass <scheme>://<host>/api/internationalAgreement?redirecturi=$redirecturi;
recursive_error_pages on;
error_page 378 =200 /internationalAgreement.html;
error_page 395 =200 /supplier?redirecturi=$redirecturi;
}
On the backend, we expose APIs to that update the user's session when they've seen a page:
router.get('/internationalAgreement',
(req, res) => {
const redirectUri = req.query.redirecturi;
if (!redirectUri) {
return res.status(403).end();
}
// International Agreement not posted yet
if (req.session.showContentLandingPage === 'true') {
return res.status(378).end();
}
...
});
Pending response code, the location block either serves the .html page or routes to a different block that might serve html (e.g., /supplier as referenced above in /landing). When the user clicks 'Next' on the html page, an HTTP request is made, the backend updates the user's session with the page they saw, then the request if 'forwarded' to another block that could serve html.
Example location arrived when user clicks next
location = /api/ge/itc {
limit_except POST { deny all; }
...
proxy_pass <scheme>://<host>/api/internationalAgreement?redirecturi=$arg_ouri;
recursive_error_pages on;
error_page 379 =200 /userLocation?redirecturi=$upstream_http_x_mbe_redirect;
}
Eventually, these locations just pass through requests after the users has stepped through the required pages.
I've tried searching for examples of locations that match all locations but generally can only find the '/' would match as a catch all and not intercept more specific locations.

Nginx dynamic route

I made a sample application that produces dynamic static files. I basically do not want to enter all the routes manually into the default file of Nginx. I saw some solutions here but the answers were not understandable for me in my simple case.
So basically my structure looks like this :
the main link of the application:
https://mysite.come/myproject/products
dynamic routes are numbers that also the link has query string
for example:
https://mysite.come/myproject/products/1?rand=something
https://mysite.come/myproject/products/2?rand=something
https://mysite.come/myproject/products/3?rand=something
https://mysite.come/myproject/products/4?rand=something
I could basically write :
location /myproject/products/1/ {
proxy_pass http://localhost:8000/1;
}
and need to repeat this for all the products which are none sense. Is there any way to do it automatically?
...
when I use dev mode ( npm run dev) I get
maybe using try_files? see the last part of this article
location /myproject/products/ {
proxy_pass http://localhost:8000;
}
server {
listen 8000;
server_name localhost;
location / {
root path_of_web_bundle;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
}

Vue.js SPA with vuex-oidc has redirect loops on release version

I have a single page application built in Vue.js 2.5 which also has OAuth2.0 support using IdentityServer4 + vuex-oidc and runs on an nginx server. Everything with my setup works fine when running the app on webpack dev server, but the release version has a redirect loop problem which I highly suspect might be due to nginx misconfiguration.
Problem: The redirect loop behavior is always the same
User requests navigation to /app
oidc plugin redirects to /connect/authorize?...
redirect to /app/oidc-login (authorization request's redirect uri)
redirect to /app (back to step 2)
For the dev server I am using a reverse proxy configured as
location /app {
fastcgi_buffer_size 128k;
fastcgi_buffers 4 256k;
fastcgi_busy_buffers_size 256k;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass https://127.0.0.1:55100;
proxy_temp_path C:/myapp/nginxRP;
}
But since I'm using history mode in router, the release version is configured as per https://router.vuejs.org/guide/essentials/history-mode.html#example-server-configurations
fastcgi_buffer_size 128k;
fastcgi_buffers 4 256k;
fastcgi_busy_buffers_size 256k;
location /app {
try_files $uri $uri/ /index.html;
}
Where the release version of the app (index.html and static files) are located at ..\nginx\html\app
Here's my vue-router configuration
const router = new Router({
mode: "history",
base: "/app/",
routes: [
{
path: "/oidc-login",
name: "oidcCallback",
component: OidcCallback,
meta: {
isOidcCallback: true,
isPublic: true
}
},
{
path: "/oidc-silent-login",
name: "oidcSilentCallback",
component: OidcSilentCallback,
meta: {
isOidcCallback: false,
isPublic: true
}
},
{
path: "/",
name: HOME_PAGE_TITLE,
component: Main
},
{
path: "*",
name: "Page Not Found",
component: NotFound
}
]
});
And the OidcCallback components is
<template>
<div></div>
</template>
<script>
import { mapActions } from "vuex";
import { OIDC_MODULE_NAMESPACE } from "../../store/store";
export default {
name: "OidcCallback",
methods: {
...mapActions(OIDC_MODULE_NAMESPACE, [
"oidcSignInCallback"
])
},
mounted () {
this.oidcSignInCallback()
.then((redirectPath) => {
this.$router.push(redirectPath);
})
.catch((err) => {
console.error(err);
this.$router.push("/signin-oidc-error"); // TODO
});
}
};
</script>
I've configured vuex-oidc pretty much exactly as instructed in https://github.com/perarnborg/vuex-oidc/wiki#how-to-implement-vuex-oidc except that I dynamically add the oidcStore module to vuex.
Since everything just works in the dev server and I already think this is an nginx issue, I'm not sure providing what other parts of my code/setup would be helpful but please let me know in case I'm missing something and I'll share more.
Thanks
As I suspected earlier, the problem was in fact a misconfiguration on the nginx part. basically the webserver was stripping the id_token parameter returned from IdentityServer (and any other query parameters) which resulted in the redirect loop. There are two solution to this. the easy solution is to add a rewrite rule to nginx configuration and basically replace it with something like
location ^~ /app/ {
if (!-f $request_filename) {
rewrite ^/app/(.*)$ /app/index.html;
}
}
So that it correctly passes every url query to the Vue app which is then handled by Vue-Router and the vuex-oidc middleware (no changes required in setting up vue-router, only the above nginx configuration is enough).
Another solution is to use a "Front Controller Pattern" design and pass the complete uri with its arguments to the SPA. This still requires configuring nginx a bit differently like
location /app {
try_files $uri $uri/ /index.html?route=$uri&$args;
}
No more rewrites, but additionally imposes special treatment in Vue-Router to perform navigation from there using a navigation guard and this route query similar to what is proposed here.

Cannot load static file in custom nginx error page

I have following static files:
/home/nginx/js/a.js
/home/nginx/errors/403.html
nginx.conf:
[...]
location / {
root /home/nginx;
}
error_page 403 /errors/403.html;
location = /errors/403.html {
root /home/nginx;
}
[...]
403.html code:
[...]
<script src="js/a.js"></script>
[...]
However it causes an error, it cannot find wanted .js file.
I tried to change it with ../js/a.js, move 403.html to root directory (with changes in nginx.conf's location) but still no effect. Is it a problem with nginx configuration?

nginx how to include rewrite outside of root

How do you call get a file that outside of the root to the be processed. i was reading about the alias and couldnt get it working. so ive tried adding a new root within the location no luck.
this is a cutdown of my config file
server {
listen 443;
server_name domain.com;
---
root ../var/www/domain/public_html;
# works as being called form within the root
location /login {
rewrite ^/login /account/login permanent;
}
#need to
location /validation/code.png {
root /var/www/domain/include;
rewrite ^/validation/code.png /captcha/display_captcha.php;
}
}
You are rewriting the png file to a php file. This will create a sub request for /captcha/display_captcha.php. Is there a location for php in your config? Assuming the php location uses the general root, when the sub request hits this, /captcha/display_captcha.php will not be found an you will get a 404 error.
Your best bet is to copy the php location and create a php location specifically for the php file.
server {
listen 443;
server_name domain.com;
root /var/www/domain/public_html;
...
location = /validation/code.png {
rewrite ^/validation/code.png /captcha/display_captcha.php;
}
location ~ ^/captcha/display_captcha.php {
root /var/www/domain/include
...
# copy php processing code from normal php location.
}
}
Better still, just use '/captcha/display_captcha.php' directly in your html and drop '/validation/code.png' altogether.

Resources