System Information
Strapi Version: 4.2.0-beta.2
Operating System: Mac OS Monterey
Node Version: v16.14.2
NPM Version: 8.5.4
Hello everybody,
Does anyone know how to set the APP_KEYS asynchronously?
My code is:
// index.ts
export default {
async register({ strapi }) {
const credentials = await getAwsSecrets();
strapi.config.set("server", {
host: credentials.HOST,
port: credentials.PORT,
app: {
keys: credentials.APP_KEYS,
},
});
}
}
// server.ts
export default ({ env }) => ({
host: env("HOST", "0.0.0.0"),
port: env.int("PORT", 1337),
app: {
keys: env.array("APP_KEYS"),
},
});
But this error is occurs:
debug: ⛔️ Server wasn't able to start properly.
error: Middleware "strapi::session": App keys are required. Please set app.keys in config/server.js (ex: keys: ['myKeyA', 'myKeyB'])
at instantiateMiddleware (node_modules/#strapi/strapi/lib/services/server/middleware.js:12:11)
at resolveMiddlewares (node_modules/#strapi/strapi/lib/services/server/middleware.js:56:18)
at registerApplicationMiddlewares (node_modules/#strapi/strapi/lib/services/server/register-middlewares.js:66:29)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async Object.initMiddlewares (node_modules/#strapi/strapi/lib/services/server/index.js:99:7)
at async Strapi.bootstrap (node_modules/#strapi/strapi/lib/Strapi.js:436:5)
at async Strapi.load (node_modules/#strapi/strapi/lib/Strapi.js:448:5)
at async Strapi.start (node_modules/#strapi/strapi/lib/Strapi.js:196:9)
Related
I am building a platform that offers different applications, the main platform is running on http://localhost and the applications will run each on a specific subdomain, at the moment I have an application running on http://sub.localhost.
I am using Nginx and Docker to host both the platform and the application, my goal would be to authenticate on http://localhost and use the session of the platform in the applications (subdomains), I have already taken a look at every single source/similar problem but could not find a solution, some of the sources I have read are the following:
https://github.com/nextauthjs/next-auth/discussions/1299
https://github.com/nextauthjs/next-auth/issues/405
https://github.com/nextauthjs/next-auth/issues/2718
At the moment this is my .env.local on the main platform:
NODE_ENV=development
GOOGLE_CLIENT_ID=...
GOOGLE_CLIENT_SECRET=...
GOOGLE_AUTH_URL=...
NEXTAUTH_URL=http://localhost/
NEXTAUTH_URL_INTERNAL=http://mygames:3000/
NEXTAUTH_SECRET=...
DATABASE_URL=...
NEXT_PUBLIC_API_KEY=...
NEXT_SECRET_API_KEY=...
The following is the .env.local of the application (subdomain):
NEXTAUTH_URL=http://sub.localhost/
NEXTAUTH_URL_INTERNAL=http://mygames:3000/
NEXTAUTH_SECRET=...
DATABASE_URL=...
NEXT_PUBLIC_API_KEY=...
NEXT_SECRET_API_KEY=...
The following is my [...nextauth].js for the main platform:
import NextAuth from 'next-auth';
import GoogleProvider from 'next-auth/providers/google';
import { PrismaAdapter } from '#next-auth/prisma-adapter';
import prisma from '../../../lib/prisma';
import Stripe from 'stripe';
const getDomainWithoutSubdomain = url => {
const urlParts = new URL(url).hostname.split('.');
return urlParts
.slice(0)
.slice(-(urlParts.length === 4 ? 3 : 2))
.join('.');
};
const hostName = getDomainWithoutSubdomain(process.env.NEXTAUTH_URL);
console.log("HOSTNAME", hostName);
const options = {
secret: process.env.NEXTAUTH_SECRET,
adapter: PrismaAdapter(prisma),
providers: [
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
}),
],
pages: {
signIn: '/signin'
},
callbacks: {
async signIn({ user, account, profile, email, credentials }) {
return true;
},
async redirect({ url, baseUrl }) {
return baseUrl;
},
async session({ session, user, token }) {
return { ...session, ...user };
},
async jwt({ token, user, account, profile, isNewUser }) {
return token;
}
},
cookies: {
sessionToken: {
name: process.env.NODE_ENV === 'production' ? `__Secure-next-auth.session-token` : 'next-auth.session-token',
options: {
httpOnly: true,
sameSite: 'lax',
path: '/',
secure: process.env.NODE_ENV === 'production' ? true: false,
domain: '.' + hostName
}
}
}
}
export default (req, res) => NextAuth(req, res, options)
When I use getSession in the subdomain application I receive a null object, what can I do to solve this? Feel free to ask for anything for more details!
Spent ages looking for a solution...
Solution:
https://github.com/nextauthjs/next-auth/discussions/4089#discussioncomment-2290660
TLDR; You cannot use localhost subdomains as intended. You must use example.com and app.example.com. To set these go to the hosts file in you system.
Follow the steps in the github post if needed
I am having some trouble with converting Nestjs to serverless.
My tech stack is, Nestjs, Graphql and Prisma.
I have followed multiple guide buy to no avail, below are the tutorials I have follow.
https://nishabe.medium.com/nestjs-serverless-lambda-aws-in-shortest-steps-e914300faed5
https://github.com/lnmunhoz/nestjs-graphql-serverless
The error that i am facing.
It happens when i start to navigate to it. Example, http://localhost:3000/dev/graphql, I wanted to access the playground
The problem shows that serverless file is missing, but its there under src
This is my serverless.ts file inside src folder
import { NestFactory } from '#nestjs/core';
import { ExpressAdapter } from '#nestjs/platform-express';
import { Context, Handler } from 'aws-lambda';
import serverless from 'aws-serverless-express';
import express from 'express';
import { Server } from 'http';
import { AppModule } from './app.module';
export async function bootstrap() {
const expressApp = express();
const adapter = new ExpressAdapter(expressApp);
const app = await NestFactory.create(AppModule, adapter);
await app.init();
return serverless.createServer(expressApp);
}
let cachedServer: Server;
export const handler: Handler = async (event: any, context: Context) => {
if (!cachedServer) {
const server = await bootstrap();
cachedServer = server;
return serverless.proxy(server, event, context);
} else {
return serverless.proxy(cachedServer, event, context);
}
};
And this is my serverless.yml file
service: laundry-api
provider:
name: aws
runtime: nodejs12.x
region: ap-southeast-1
stage: dev
profile: default # Config your AWS Profile
plugins:
- serverless-offline
functions:
index:
handler: src/serverless.handler
environment:
SLS_DEBUG: true
events:
- http:
path: graphql
method: any
cors: true
I have been cracking my head for hours on where is the problem, tried webpack too.
Would be greate if you guys can point me to the right direction
Thank you.
I would like to simply deploy my Next.js 9 to AWS Lambdas using just API Gateway in front and make a proxy to the static path pointing to S3, but the only available option (without having to write all the stuff from the scratch) is https://github.com/serverless-nextjs/serverless-next.js which is currently using a beta version of Serverless Components (very buggy and lack of control over resources created as it does not uses CloudFormation), also this SLS Component forces the user to use CloudFront which is not my need, I have PR environments created all the time and allocating CloudFront for that is just waste of time/money/resources.
I tried to use the old version of the plugin serverless-nextjs-plugin but it seems not to work with Next.js 9, it fails to create the Lambdas for .html generated pages.
Is there any light in the end of this tunnel?
https://github.com/serverless-nextjs/serverless-next.js/issues/296 by this issue it looks like there's no way to do that.
I managed to make it work
serverless.base.yml file:
service: my-app
provider:
name: aws
runtime: nodejs12.x
timeout: 10 # seconds
memorySize: 1792 # Mb
custom:
webpack:
packager: yarn
includeModules:
forceInclude:
- chalk
functions:
nextJsApp:
handler: server.handler
events:
- http: 'ANY /'
- http: 'ANY {proxy+}'
server.js:
const { parse } = require('url');
const next = require('next');
const serverless = require('serverless-http');
const app = next({
dev: false
});
const requestHandler = app.getRequestHandler();
export const handler = serverless(async (req, res) => {
const parsedUrl = parse(req.url, true);
await requestHandler(req, res, parsedUrl);
});
wepback.config.js:
const CopyWebpackPlugin = require('copy-webpack-plugin');
const nodeExternals = require('webpack-node-externals');
module.exports = {
...
externals: [nodeExternals()],
plugins: [
new CopyWebpackPlugin({
patterns: [
{ from: '.next', to: '.next' },
{ from: 'public', to: 'public' }
]
})
]
};
and here is the trick for working with serverless and webpack, use a serverless.js that modifies the serverless.base.yml and add all dependencies to the required dependencies to be included in the bundle:
const yaml = require('yaml-boost');
const minimist = require('minimist');
const path = require('path');
module.exports = (() => {
const params = minimist(process.argv.slice(2));
const serverless = yaml.load(path.join(__dirname, 'serverless.base.yml'), params);
const packageJson = require(path.join(__dirname, 'package.json'));
const dependencies = Object.keys(packageJson.dependencies);
serverless.custom.webpack.includeModules.forceInclude.push(...dependencies);
return serverless;
})();
I want to use socket.io in my Nuxtjs. Is it possible?
I tried this tutorial but I am getting the following error:
These dependencies were not found:
* fs in ./node_modules/socket.io/lib/index.js
* uws in ./node_modules/engine.io/lib/server.js
The better way to play with Nuxt.js + Socket.io is to follow this official example from core-team: https://github.com/nuxt/nuxt.js/tree/dev/examples/with-sockets
Updated answer with linked example on GitHub
I would suggest to use the nuxt-socket-io module. It is really easy to set up and has a nice documentation.
I built this litte demo example and I will list the steps that I took to build it (this is even a bit more thorough than the Setup section of the npm package):
Add nuxt-socket-io dependency to your project:
yarn add nuxt-socket-io # or npm install nuxt-socket-io
(If you already have a socket.io server you can skip this part)
Add following line to your nuxt.config.js file: serverMiddleware: [ "~/serverMiddleware/socket-io-server.js" ] (Please do not mix up serverMiddleware with middleware, this are two different things)
Then, create the file ./serverMiddleware/socket-io-server.js where you can implement your socket.io server.
// This file is executed once when the server is started
// Setup a socket.io server on port 3001 that has CORS disabled
// (do not set this to port 3000 as port 3000 is where
// the nuxt dev server serves your nuxt application)
const io = require("socket.io")(3001, {
cors: {
// No CORS at all
origin: '*',
}
});
var i = 0;
// Broadcast "tick" event every second
// Or do whatever you want with io ;)
setInterval(() => {
i++;
io.emit("tick", i);
}, 1000);
// Since we are a serverMiddleware, we have to return a handler,
// even if this it does nothing
export default function (req, res, next) {
next()
}
(If you already have Vuex set up, you can skip this)
Add following empty Vuex store, i.e., create the file ./store/index.js, since the module needs Vuex set up.
export const state = () => ({})
Add nuxt-socket-io to the modules section of nuxt.config.js, this will enable socket-io client:
{
modules: [
'nuxt-socket-io',
],
// socket.io configuration
io: {
// we could have multiple sockets that we identify with names
// one of these sockets may have set "default" to true
sockets: [{
default: true, // make this the default socket
name: 'main', // give it a name that we can later use to choose this socket in the .vue file
url: 'http://localhost:3001' // URL wherever your socket IO server runs
}]
},
}
Use it in your components:
{
data() {
return {
latestTickId: 0,
};
},
mounted() {
const vm = this;
// use "main" socket defined in nuxt.config.js
vm.socket = this.$nuxtSocket({
name: "main" // select "main" socket from nuxt.config.js - we could also skip this because "main" is the default socket
});
vm.socket.on("tick", (tickId) => {
vm.latestTickId = tickId;
});
},
}
Run it with npm run dev and enjoy your tick events :)
Nuxt + socket.io
For me worked:
Create project as nodejs app (not static page);
Install socket.io npm i socket.io;
Add serverMiddleware section to nuxt.config.js:
export default {
...,
serverMiddleware: [
{path: '/ws', handler: '~/api/srv.js'},
],
}
Create middleware /app/srv.js:
const app = require('express')()
const socket = require('socket.io')
let server = null
let io = null
app.all('/init', (req, res) => {
if (!server) {
server = res.connection.server
io = socket(server)
io.on('connection', function (socket) {
console.log('Made socket connection');
socket.on('msg', msg => {
console.log('Recived: ' + msg)
setTimeout(() => {
socket.emit('msg', `Response to: ${msg}`)
}, 1000)
})
socket.on('disconnect', () => console.log('disconnected'))
})
}
res.json({ msg: 'server is set' })
})
module.exports = app
Socket.io needs server which is not created in middleware, that's why is taken from firest request to app from res.connection.server.
Create page pages/index.vue:
<template>
<div class="container">
<input v-model="msg">
<button #click="socket.emit('msg', msg)">send</button>
<br/>
<textarea v-model="resps"></textarea>
</div>
</template>
<script>
export default {
head: {
script: [
{src: 'https://cdnjs.cloudflare.com/ajax/libs/socket.io/3.0.4/socket.io.js'},
],
},
data () {
return {
socket: null,
msg: 'wwJd',
resps: '',
}
},
mounted () {
this.$axios.$get('/ws/init')
.then(resp => {
this.socket = io()
this.socket.on('msg', msg => this.resps += `${msg}\n`)
})
},
}
</script>
Run it npm run dev;
Modify and enjoy :-)
With the following AWS SAM template process.env is an empty object. I expect it to contain the environment variable from the template defined as dbURL.
AWSTemplateFormatVersion: "2010-09-09"
Transform: "AWS::Serverless-2016-10-31"
Description: "An example RESTful service"
Resources:
ExampleFunction:
Type: "AWS::Serverless::Function"
Properties:
Runtime: "nodejs6.10"
Handler: "/dist/getTickets/index.handler"
Events:
RootDeveloperHub:
Type: "Api"
Properties:
Path: "/new"
Method: "any"
Environment:
Variables:
dbURL: "dbURL_Value"
handler
exports.handler = (event, context, callback) => {
// logs {}
console.log(process.env)
}
Things I've ruled out:
webpack react process.env always empty (windows 10) - I don't have a DefinePlugin configuration. I'm also using mac.
I should have tested the code I posted...
The handler works when it is set up as
exports.handler = (event, context, callback) => {
// logs {}
console.log(process.env)
}
The fix for my code was to add the following to my webpack config.
{
...
target: 'node'
}