Set API URL for Quasar in the Electron mode build - vue.js

I want to set my API URL for Electron mode.
When I built my code to Electron production mode, All of my API URLs disappear first of the URL such as this: file:///core/v1/api/main/login
How can I set my API URL(an external IP address) for Electron mode in Production?

I found the solution. for this case, we could change the axios.js in the boot directory.
For example, I need to change the baseURL to another when I build to Electron mode.
if (process.env.MODE === 'electron') {
var axiosInstance = axios.create({
baseURL: process.env.API_URL
})
Vue.prototype.$axios = axiosInstance
} else {
Vue.prototype.$axios = axios
}

Related

swagger express ui strips the prefix and redirects to host

I am not able to load swagger for my nestJS application which is deployed on EKS.
Here is my main.ts
import {NestFactory} from '#nestjs/core';
import {NestExpressApplication} from '#nestjs/platform-express';
import {DocumentBuilder, SwaggerModule} from '#nestjs/swagger';
const swaggerUi = require('swagger-ui-express')
import {AppModule} from './app.module';
import {json, NextFunction, Request, Response} from 'express';
(async () => {
const app = await NestFactory.create<NestExpressApplication>(AppModule);
const options = new DocumentBuilder()
.setTitle('Test')
.build();
const document = SwaggerModule.createDocument(app, options,{ ignoreGlobalPrefix: true
app.use("*/docs",swaggerUi.serve,swaggerUi.setup(document));
// Or
SwaggerModule.setup(`/docs`, app, document);
await app.listen(port, () => {
console.log(`Test service is running on port ${port}...`);
});
})
();
On my local machine the swagger doc loads correctly but when I deploy it to a development environment, it fails
dev url "https://dev-test-api.com/testservice/v1/docs/", it strips the /testservice/v1/ and redirects to "https://dev-test-api.com/docs/ and gives a 404.
I have tried couple of solutions mentioned in https://github.com/scottie1984/swagger-ui-express/issues/183
The forward-prefix option and the redirect too. None seem to work
Another problem I have is that the prefix "testservice/v1" changes as per different sandbox environments and since it is not an environment variable I don't have a way to set the path for swagger file before app is loaded.

How do I mock server-side API calls in a Nextjs app?

I'm trying to figure out how to mock calls to the auth0 authentication backend when testing a next js app with React Testing Library. I'm using auth0/nextjs-auth0 to handle authentication. My intention is to use MSW to provide mocks for all API calls.
I followed this example in the nextjs docs next.js/examples/with-msw to set up mocks for both client and server API calls. All API calls generated by the auth0/nextjs-auth0 package ( /api/auth/login , /api/auth/callback , /api/auth/logout and /api/auth/me) received mock responses.
A mock response for /api/auth/me is shown below
import { rest } from 'msw';
export const handlers = [
// /api/auth/me
rest.get(/.*\/api\/auth\/me$/, (req, res, ctx) => {
return res(
ctx.status(200),
ctx.json({
user: { name: 'test', email: 'email#domain.com' },
}),
);
}),
];
The example setup works fine when I run the app in my browser. But when I run my test the mocks are not getting picked up.
An example test block looks like this
import React from 'react';
import {render , screen } from '#testing-library/react';
import Home from 'pages/index';
import App from 'pages/_app';
describe('Home', () => {
it('should render the loading screen', async () => {
render(<App Component={Home} />);
const loader = screen.getByTestId('loading-screen');
expect(loader).toBeInTheDocument();
});
});
I render the page inside the App component like this <App Component={Home} /> so that I will have access to the various contexts wrapping the pages.
I have spent about 2 days on this trying out various configurations and I still don't know what I might be doing wrong. Any and every help is appreciated.
This is probably resolved already for the author, but since I ran into the same issue and could not find useful documentation, this is how I solved it for end to end tests:
Overriding/configuring the API host.
The plan is to have the test runner start next.js as custom server and then having it respond to both the next.js, as API routes.
A requirements for this to work is to be able to specify the backend (host) the API is calling (via environment variables). Howerver, access to environment variables in Next.js is limited, I made this work using the publicRuntimeConfig setting in next.config.mjs. Within that file you can use runtime environment variables which then bind to the publicRuntimeConfig section of the configuration object.
/** #type {import('next').NextConfig} */
const nextConfig = {
(...)
publicRuntimeConfig: {
API_BASE_URL: process.env.API_BASE_URL,
API_BASE_PATH: process.env.API_BASE_PATH,
},
(...)
};
export default nextConfig;
Everywhere I reference the API, I use the publicRuntimeConfig to obtain these values, which gives me control over what exactly the (backend) is calling.
Allowing to control the hostname of the API at runtime allows me to change it to the local machines host and then intercept, and respond to the call with a fixture.
Configuring Playwright as the test runner.
My e2e test stack is based on Playwright, which has a playwright.config.ts file:
import type { PlaywrightTestConfig } from '#playwright/test';
const config: PlaywrightTestConfig = {
globalSetup: './playwright.setup.js',
testMatch: /.*\.e2e\.ts/,
};
export default config;
This calls another file playwright.setup.js which configures the actual tests and backend API mocks:
import {createServer} from 'http';
import {parse} from 'url';
import next from 'next';
import EndpointFixture from "./fixtures/endpoint.json";
// Config
const dev = process.env.NODE_ENV !== 'production';
const baseUrl = process?.env?.API_BASE_URL || 'localhost:3000';
// Context
const hostname = String(baseUrl.split(/:(?=\d)/)[0]).replace(/.+:\/\//, '');
const port = baseUrl.split(/:(?=\d)/)[1];
const app = next({dev, hostname, port});
const handle = app.getRequestHandler();
// Setup
export default async function playwrightSetup() {
const server = await createServer(async (request, response) => {
// Mock for a specific endpoint, responds with a fixture.
if(request.url.includes(`path/to/api/endpoint/${EndpointFixture[0].slug}`)) {
response.write(JSON.stringify(EndpointFixture[0]));
response.end();
return;
}
// Fallback for pai, notifies about missing mock.
else if(request.url.includes('path/to/api/')) {
console.log('(Backend) mock not implementeded', request.url);
return;
}
// Regular Next.js behaviour.
const parsedUrl = parse(request.url, true);
await handle(request, response, parsedUrl);
});
// Start listening on the configured port.
server.listen(port, (error) => {
console.error(error);
});
// Inject the hostname and port into the applications publicRuntimeConfig.
process.env.API_BASE_URL = `http://${hostname}:${port}`;
await app.prepare();
}
Using this kind of setup, the test runner should start a server which responds to both the routes defined by/in Next.js as well as the routes intentionally mocked (for the backend) allowing you to specify a fixture to respond with.
Final notes
Using the publicRuntimeConfig in combination with a custom Next.js servers allows you to have a relatively large amount of control about the calls that are being made on de backend, however, it does not necessarily intercept calls from the frontend, the existing frontend mocks might stil be necessary.

How do I force or redirect my next.js website to use https

I thought this would be a simple task, but I struggle to find a way to force my webpage to use https.
The next.js webapp lives on the heroku servers and I've set up the SSL. Both https and http version works, but how to I force or redirect the website to use the https version.
I've seen some solution using express, but nothing in my webapp are using express, is it required?
Thanks.
As of Nextjs v12, you can use middleware instead of a setting up a custom server.
Middleware is a better solution for the following reasons:
a custom server often requires additional dependencies (like express)
you give up some of the box features like automatic static optimization
Middleware can be scope to specific paths using the built in routing paradigm
Create a /pages/_middleware.ts (or .js) file with something similar to this:
import { NextFetchEvent, NextRequest, NextResponse } from 'next/server'
type Environment = "production" | "development" | "other";
export function middleware(req: NextRequest, ev: NextFetchEvent) {
const currentEnv = process.env.NODE_ENV as Environment;
if (currentEnv === 'production' &&
req.headers.get("x-forwarded-proto") !== "https") {
return NextResponse.redirect(
`https://${req.headers.get('host')}${req.nextUrl.pathname}`,
301
);
}
return NextResponse.next();
}
I also created an npm package for this.
import sslRedirect from 'next-ssl-redirect-middleware';
export default sslRedirect({});
There is a solution with an NPM library called heroku-ssl-redirect.
First off, install the library using npm i heroku-ssl-redirect.
Then, create a new server.js file with the following script.
const next = require('next');
const express = require('express');
const sslRedirect = require('heroku-ssl-redirect').default; // to make it work with 'require' keyword.
const PORT = process.env.PORT || 3000;
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handle = app.getRequestHandler();
app.prepare().then(() => {
const server = express();
// Express's middleware to automatically redirect to 'https'.
server.use(sslRedirect());
server.all('*', (req, res) => {
return handle(req, res);
});
server.listen(port, err => {
if (err) throw err;
console.log(`Server starts on ${PORT}.`);
});
});
Then, change the start script to be like this:
"scripts": {
"dev": "next",
"build": "next build",
"start": "node server.js"
}
It should work.
Note that you could replace Express with the createServer method from native Node.js's http module. But I do this with Express to simplify the syntax.
Further reading: How to setup a custom server in Next.js.

How to get Expo static deep link for development?

I need an Expo static deep link for development to use for Oauth redirect with a 3rd party ( Cognito )
I have used Linking.makeUrl() but this returns a deep link with a dynamic local ipaddress
exp://10.0.0.107:19000 that will not be consistent for other developers on the team.
The documentation at:
https://docs.expo.io/versions/latest/workflow/linking/#linking-module
Says the various environment links look like
Published app in Expo client : exp://exp.host/#community/with-webbrowser-redirect
Published app in standalone : myapp://
Development : exp://wg-qka.community.app.exp.direct:80
I have tried that Development link but it fails to open.
I have the similar issue too, here is my solution
Also post in https://github.com/aws-amplify/amplify-js/issues/4244#issuecomment-586845322
In case anyone still needs help for expo+amplify+social logins
app.json
{
"expo": {
"scheme": "exposchemeappname://" // use any name you like, just make it unique
}
}
App.js
import { Linking } from 'expo';
import * as WebBrowser from 'expo-web-browser';
import awsconfig from './aws-exports';
const amplifyConfig = {
...awsconfig,
oauth: {
...awsconfig.oauth,
urlOpener: async (url, redirectUrl) => {
// On Expo, use WebBrowser.openAuthSessionAsync to open the Hosted UI pages.
const { type, url: newUrl } = await WebBrowser.openAuthSessionAsync(url, redirectUrl);
if (type === 'success') {
await WebBrowser.dismissBrowser();
if (Platform.OS === 'ios') {
return Linking.openURL(newUrl);
}
}
},
options: {
// Indicates if the data collection is enabled to support Cognito advanced security features. By default, this flag is set to true.
AdvancedSecurityDataCollectionFlag: true
},
}
};
const expoScheme = "exposchemeappname://"
// Technically you need to pass the correct redirectUrl to the web browser.
let redirectUrl = Linking.makeUrl();
if (redirectUrl.startsWith('exp://1')) {
// handle simulator(localhost) and device(Lan)
redirectUrl = redirectUrl + '/--/';
} else
if (redirectUrl === expoScheme) {
// dont do anything
} else {
// handle the expo client
redirectUrl = redirectUrl + '/'
}
amplifyConfig.oauth.redirectSignIn = redirectUrl;
amplifyConfig.oauth.redirectSignOut = redirectUrl;
Amplify.configure(amplifyConfig);
Make sure you add the following redirect urls to amplify amplify auth update
# development
exp://127.0.0.1:19000/--/
exp://192.168.1.101:19000/ # depends on your lan ip
# expo client
exp://exp.host/#[EXPO_ACCOUNT]/[EXPO_APPNAME]/
# expo scheme for standalone
exposchemeappname://
you can use Linking module
install it by running: expo install expo-linking
import it at the top of your file: import * as Linking from "expo-linking";
and then use: Linking.makeUrl(); to get the link to your app hosted by expo client
console it to see the url

Vue.js environment variables not working with axios on Heroku

I have deployed a Vue.js application to heroku an api also hosted on heroku.
The VueJS app uses axios to connect to the api. I have set a config variable in heroku:
VUE_APP_ROOT_API = https://[my-express-api].herokuapp.com/api
Here is my base axios call:
import axios from 'axios'
const token = localStorage.getItem('token')
export default () => {
console.log(process.env.VUE_APP_ROOT_API)
return axios.create({
baseURL: process.env.VUE_APP_ROOT_API,
headers: {
'Content-Type': 'application/json',
token: token,
},
validateStatus: function () {
return true;
}
})
}
However, the console log reveals that the variable is undefined and axios is using the Vue app url as the base for api calls (https://[my-vue-app].herokuapp.com/undefined/) instead of the one specified in the config variable.
Resolved this. It turns out that my config variable was being compiled into the code at build time, so once I deployed to trigger a rebuild, the new config var worked. Adding/Updating config vars will automatically restart the dynos, but that doesn't rebuild any compiled code.
For me, appending the build command in my package.json with '--mode production' before pushing to heroku fixed the issue.
https://forum.vuejs.org/t/production-env-on-app-deployed-in-heroku/71077
Good luck!