Error ServerMiddleware should expose a handle nuxt - websocket

The new nuxt.js setup does not come with a server folder
You create an API folder and put a file inside which exposes the server
I am trying to use websockets using the ws library to parse user session and getting this error
Here is my code for app.js placed inside api folder
import http from 'http'
import logger from 'express-pino-logger'
import express from 'express'
import cookieParser from 'cookie-parser'
import WebSocket from 'ws'
const app = express()
const sessionParser = cookieParser()
const map = new Map()
app.use(logger())
app.use(express.json())
app.use(express.urlencoded({ extended: true }))
app.use(sessionParser)
app.use('/v1', (req, res) => res.json('hello'))
const server = http.createServer(app)
const wss = new WebSocket.Server({ noServer: true })
wss.on('connection', function connection(ws, request, client) {
ws.on('message', function message(msg) {
console.log(`Received message ${msg} from user ${client}`)
})
})
server.on('upgrade', function (request, socket, head) {
console.log('Parsing session from request...')
sessionParser(request, {}, () => {
if (!request.session.userId) {
socket.destroy()
return
}
console.log('Session is parsed!')
wss.handleUpgrade(request, socket, head, function (ws) {
wss.emit('connection', ws, request)
})
})
})
wss.on('connection', function (ws, request) {
const userId = request.session.userId
map.set(userId, ws)
ws.on('message', function (message) {
//
// Here we can now use session parameters.
//
console.log(`Received message ${message} from user ${userId}`)
})
ws.on('close', function () {
map.delete(userId)
})
})
server.listen(3000)
export default server
My nuxt.config.js file
export default {
/*
** Nuxt rendering mode
** See https://nuxtjs.org/api/configuration-mode
*/
mode: 'universal',
/*
** Nuxt target
** See https://nuxtjs.org/api/configuration-target
*/
target: 'server',
/*
** Headers of the page
** See https://nuxtjs.org/api/configuration-head
*/
head: {
title: process.env.npm_package_name || '',
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{
hid: 'description',
name: 'description',
content: process.env.npm_package_description || '',
},
],
link: [{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }],
},
/*
** Global CSS
*/
css: [],
/*
** Plugins to load before mounting the App
** https://nuxtjs.org/guide/plugins
*/
plugins: [],
/*
** Auto import components
** See https://nuxtjs.org/api/configuration-components
*/
components: true,
/*
** Nuxt.js dev-modules
*/
buildModules: [
// Doc: https://github.com/nuxt-community/eslint-module
'#nuxtjs/eslint-module',
// Doc: https://github.com/nuxt-community/stylelint-module
'#nuxtjs/stylelint-module',
],
/*
** Nuxt.js modules
*/
modules: [
// Doc: https://axios.nuxtjs.org/usage
'#nuxtjs/axios',
'#nuxtjs/pwa',
],
/*
** Axios module configuration
** See https://axios.nuxtjs.org/options
*/
axios: {},
/*
** Build configuration
** See https://nuxtjs.org/api/configuration-build/
*/
build: {},
serverMiddleware: ['~/api/app'],
}
How do I expose the websocket server from app.js?

Yo should export you server middleware . At the bottom add :
// export the server middleware
module.exports = {
path: '/api',
handler: app
}

Related

Revert of Filepond is not working on Live server but works on local Server while using laravel

It was all good and working when i was testing my code on local server.
But always when i test the same code on live server it gives errors.
Actually, I am working with Filepond using Laravel and creating a website.
This is Edit Blade Js
<pre>
<script>
// Register the plugin with FilePond
FilePond.registerPlugin(
FilePondPluginMediaPreview,
FilePondPluginImagePreview,
FilePondPluginFileValidateType,
FilePondPluginFileValidateSize,
FilePondPluginFilePoster
);
const inputElement1 = document.querySelector('input[id="card_image_id"]');
const inputElement2 = document.querySelector('input[id="video"]');
const workimages = document.querySelector('input[id="workimages"]');
const pond1 = FilePond.create(inputElement1, {
acceptedFileTypes: ['image/*'],
fileValidateTypeDetectType: true,
maxFileSize: 10000000, //10 mbs max size
allowFileSizeValidation: true,
onaddfilestart: (file) => {
isLoadingCheck();
},
onprocessfile: (files) => {
isLoadingCheck();
},
});
const pond2 = FilePond.create(inputElement2, {
acceptedFileTypes: ['video/*'],
fileValidateTypeDetectType: true,
maxFileSize: 35000000, //35 mbs max size
allowFileSizeValidation: true,
onaddfilestart: (file) => {
isLoadingCheck();
},
onprocessfile: (files) => {
isLoadingCheck();
},
});
const pond3 = FilePond.create(workimages, {
acceptedFileTypes: ['image/*'],
fileValidateTypeDetectType: true,
maxFileSize: 10000000, //10 mbs max size
allowFileSizeValidation: true,
onaddfilestart: (file) => {
isLoadingCheck();
},
onprocessfile: (files) => {
isLoadingCheck();
},
});
FilePond.setOptions({
server: {
process: '/tempupload',
revert: '/tempdelete/{{ $fileid }}',
// fetch: '/tempfetch',
headers: {
'X-CSRF-TOKEN': '{{ csrf_token() }}',
'work_id': '{{ $work->id }}'
},
},
});
</script>
</pre>
This is web routes
<pre>
Route::delete('tempdelete', [WorkController::class, 'tempdelete'])->name('tempdelete');
</pre>
This is controller
<pre>
public function tempdelete()
{
$this->WorkService->tempdelete();
return response()->json(null, 204);
}
</pre>
This is Service
<pre>
public function tempdelete()
{
$work_id = (request()->header('work-id'));
$temporaryfile = TemporaryFile::where('fid', request()->getContent())->first();
if ($temporaryfile) {
$filesexist_in_workimages = Workimage::where([
'size' => $temporaryfile->size,
'name' => $temporaryfile->filename,
'work_id' => $work_id,
])->first();
if (isset($filesexist_in_workimages)) {
if (File::exists($filesexist_in_workimages->folder)) {
File::delete($filesexist_in_workimages->folder);
}
$filesexist_in_workimages->delete();
}
if (isset($temporaryfile->folder)) {
if (File::exists($temporaryfile->folder . $temporaryfile->filename)) {
File::delete($temporaryfile->folder . $temporaryfile->filename);
}
}
$temporaryfile->delete();
}
}
</pre>
The point is that this code works perfectly for deleting a file on local server but shows this error on live server
On Console:
<pre>
DELETE http://brokenclient1.000webhostapp.com/tempdelete net::ERR_EMPTY_RESPONSE
</pre>
On Network:
Failed to load responce, No data found for source with given identifier
When i try to dd on controller or service it does not even works to show dd.
This problem is not connected with FilePond. Are you using Postman or Insomnia to check your API and connection? Check your server settings. Try this solution provided in this link
Laravel Project ERR_EMPTY_RESPONSE
This is typical server error response or sometimes Internet Service Provider error.

Redirect to maintenance page if 503 error

I have the api build in laravel, so I enabled the maintenance mode : php artisan down;
Now on frontend, I use vuejs :
router.beforeEach(async (to, from, next) => {
const _next = next;
next = function newnext(loc) {
return _next(loc);
};
await initStore();
console.log('-----BEFORE------');
await getCSRFCookie();
console.log("-----IS MAINTENANCE ON ----- : " +
$store.getters['system/maintenanceIsOn']);
if ($store.getters['system/maintenanceIsOn']) {
if (to.fullPath !== '/maintenance') {
next({ name: 'maintenance' });
}
}
............
503 error is intercepted correctly by axios; Now the question is how I can redirect to my maintenance page ? I tried with router.push but a loop is started;
By maintenance route :
{
path: '/maintenance',
name: 'maintenance',
meta: {
title: 'Maintenance',
centered: true,
public: true,
maintenance: true,
},
component: () => import(/* webpackChunkName: "maintenance" */ '#/views/Maintenance.vue'),
},
Here is the browser console with all logs :
I tried like this but there is a loop and I'm not redirected to maintenance:
if ($store.getters['system/maintenanceIsOn']) {
console.log('-------REDIRECT------------');
return next({ name: 'maintenance' });
}

There is no matching message handler error in NestJs TCP E2E test

I'm playing around with Microservice architecture using NestJs. I've made a simplified repository with a few services that communicate over TCP with a mix of message and event patterns.
I have moved on to writing E2E tests for the using Supertest, and while I'm able to run the needed microservice, the requests respond with {"error": "There is no matching message handler defined in the remote service.", "statusCode": 500}
GatewayService: HTTP Rest Api where the E2E tests are run. Calls the service
AuthService: NestJs microservice running on 0.0.0.0:3001 by default
configService: a simple service that returns information needed to set up the services, like host and port. I have tried eliminating it from the test and hardcoding the values.
The E2E test file
import { INestApplication, ValidationPipe } from '#nestjs/common';
import { ClientProxy, ClientsModule, Transport } from '#nestjs/microservices';
import { Test, TestingModule } from '#nestjs/testing';
import * as request from 'supertest';
import { configService } from '../src/config.service';
import { RpcExceptionFilter } from '../src/filters/rpc-exception.filter';
import { AppModule } from './../src/app.module';
describe('AuthenticationController (e2e)', () => {
let app: INestApplication;
let authClient: ClientProxy;
beforeAll(async () => {
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [
AppModule,
ClientsModule.register([
{
...configService.getServiceConfigs().authService,
transport: Transport.TCP,
},
]),
],
}).compile();
// Setup the app instance
app = moduleFixture.createNestApplication();
// Setup the relevant micorservice(s)
app.connectMicroservice({
transport: Transport.TCP,
name: configService.getServiceConfigs().authService.name,
options: configService.getServiceConfigs().authService.options,
});
app.startAllMicroservices();
// Add request validation
app.useGlobalPipes(
new ValidationPipe({
transform: true,
whitelist: true,
forbidNonWhitelisted: true,
forbidUnknownValues: true,
}),
);
// Add needed filters
app.useGlobalFilters(new RpcExceptionFilter());
await app.init();
authClient = app.get(configService.getServiceConfigs().authService.name);
await authClient.connect();
console.log('authClient', authClient);
});
describe('POST /auth/login', () => {
it('Should return status 200 and a user object with access token', () => {
return (
request(app.getHttpServer())
.post('/auth/login')
.send({ username: 'exmple#user.com', password: 'password' })
// .expect(200)
.expect((response) => {
console.log('response', response.body);
expect(response.body).toHaveProperty('id');
expect(response.body).toHaveProperty('username');
expect(response.body).toHaveProperty('accessToken');
})
);
});
});
afterAll(async () => {
await app.close();
await authClient.close();
});
});
I have attempted adding a provider which I've used before when working with Grpc as the transport layer (this is TCP). Didn't change anything.
beforeAll(async () => {
const moduleFixture: TestingModule = await Test.createTestingModule({
...
providers: [
{
provide: 'AUTH_SERVICE',
useFactory: () => {
return ClientProxyFactory.create({
transport: Transport.TCP,
options: { host: 'localhost', port: 3001 },
});
},
},
],
I know that the microservice starts up and the gateway service is able to connect to it since when printing the authClient: Client proxy it returns a correct object with URL 0.0.0.0:3001. If I change the URL, or the name of the service in any part of the setup then errors about missing providers show, further confirming that it is supposedly correctly set up.
One of the best guides I've found on this matter. Sadly it doesn't work for my code.

RTK type Error when using injectedEndpoints with openApi

I define config file for openApi to create automatically endpoints with types:
const config: ConfigFile = {
schemaFile: 'https://example.com/static/docs/swagger.json',
apiFile: './api/index.ts',
apiImport: 'api',
outputFile: './api/sampleApi.ts',
exportName: 'sampleApi',
hooks: true,
};
export default config;
I used :
"#rtk-query/codegen-openapi": "^1.0.0-alpha.1"
"#reduxjs/toolkit": "^1.7.2",
Then I define an index.tsx that has
export const api = createApi({
baseQuery: axiosBaseQuery({ baseUrl: '' }),
endpoints: () => ({}),
});
and So I generate successfully my sampleApi.tsx file with all of endpoints and types.
like here:
const injectedRtkApi = api.injectEndpoints({
endpoints: (build) => ({
postUsersCollections: build.mutation<
PostUsersCollectionsApiResponse,
PostUsersCollectionsApiArg
>({
query: (queryArg) => ({
url: `/users/collections`,
method: 'POST',
body: queryArg.postCollectionBody,
}),
}),
getUsersCollections: build.query<
GetUsersCollectionsApiResponse,
GetUsersCollectionsApiArg
>({
query: (queryArg) => ({
url: `/users/collections`,
params: { name: queryArg.name },
}),
}),
overrideExisting: false,
});
export const {
usePostUsersCollectionsMutation,
useGetUsersCollectionsQuery
} = injectedRtkApi;
when in a component I use hook function useGetUsersCollectionsQuery as bellow I got an error that TypeError: Cannot read properties of undefined (reading 'subscriptions'). There is no lint typescript error related to typescript in my project.
const { data: collectionData = [] } = useGetUsersCollectionsQuery({});
It's Interesting that this hook called and I see API call in network tab but immediately I got this error. I remove this line and error is disappeared.
And Also for mutation hook I send data within it but I got 400 error. as Below:
const [postCollection, { data: newCollect }] =
usePostUsersCollectionsMutation();
...
const handleCreateItem = async () => {
const response: any = await postCollection({
postCollectionBody: { name: 'sample' },
}); }
Please help me! I really thanks you for taking time.
Finally I resolved it!
I should define reducerPath as this:
export const api = createApi({
reducerPath: 'api', <=== add this and define `api` in reducers
baseQuery: axiosBaseQuery({ baseUrl: '' }),
endpoints: () => ({}),
});

Laravel-echo in Vue returning "private is not a function"

I'm trying to build a Chat App that use Laravel Broadcast with laravel-echo and pusher but when I'm listening to the channel it returns laravel_echo__WEBPACK_IMPORTED_MODULE_6__.default.private is not a function
here's my script:
<script>
import ConfirmationModal from "../pages/User/ConfirmationModal";
import Message from '../models/Message';
import Echo from 'laravel-echo'
export default {
name: 'UserLayout',
components : {
ConfirmationModal
},
data: () => ({
isLoading : false,
user : {},
drawer: false,
rawConversations : {},
}),
mounted () {
this.user = JSON.parse(localStorage.user);
this.fetchConversations();
},
created () {
Echo.private("userStatus").listen("StatusEvent", e => {
console.log('Event listen CommentSent');
});
}
}
</script>
here's my directory. BTW, I'm using Quasar Framework for my CSS and directory Laravel and Vue is separate.

Resources