I am new to Nuxt3. I tried to connect my Nuxt3 app to my backend site which is built with Laravel. My frontend URL is http://localhost:3000 and my backend is http://localhost:8000. When I connect to http://localhost:8000/api/names using "useFetch" inside a component, it runs fine. But when I do it inside server/api/names.js using $fetch, it shows a 500 (Internal server error).
This runs fine (sample.vue)
const getNames = async () => {
let { data } = await useFetch('http://localhost:8000/api/names')
console.log(data);
}
This does not
(sample.vue)
const getNames = async () => {
let { data } = await useFetch('/api/names')
console.log(data);
}
(/server/api/names.js)
export default defineEventHandler(async (event) => {
const { data } = await $fetch("http://localhost:8000/api/names");
return { data };
});
Here's the code on my Laravel app inside api.php (http://localhost:8000/api/names)
Route::get('/names', function (){
$users_name = User::all()->pluck('name');
return response()->json(['names' => $users_name]);
});
Here's the error that shows when I go to network tab
message: "terminated"
stack: "<pre><span class=\"stack internal\">at Fetch.onAborted (node:internal/deps/undici/undici:11000:53)</span>\n<span class=\"stack\">at Fetch.emit (node:events:513:28)</span>\n<span class=\"stack internal\">at Fetch.terminate (node:internal/deps/undici/undici:10272:14)</span>\n<span class=\"stack internal\">at Object.onError (node:internal/deps/undici/undici:11095:36)</span>\n<span class=\"stack internal\">at Request.onError (node:internal/deps/undici/undici:6477:31)</span>\n<span class=\"stack internal\">at errorRequest (node:internal/deps/undici/undici:8440:17)</span>\n<span class=\"stack internal\">at Socket.onSocketClose (node:internal/deps/undici/undici:7895:9)</span>\n<span class=\"stack\">at Socket.emit (node:events:513:28)</span>\n<span class=\"stack\">at TCP.<anonymous> (node:net:313:12)</span></pre>"
statusCode: 500
statusMessage: ""
url: "/api/names"
I tried to restart both servers hoping that doing this would fix the issue but the problem still persists. Also searched if it has something to do with CORS but it connects when I call the api inside a component.
I had exactly the same problem yesterday and luckily I found a solution without having to downgrade the version of NodeJS because Nuxt3 does not work well under version 16 of Node.
First use Laragon for your Laravel Backend. Laragon automatically creates Hostname for projects ex: laravelbackend.test if the project folder is called "laravelbackend".
Then on the file (/server/api/names.js) replace localhost:8000/api with laravelbackend.test/api
export default defineEventHandler(async (event) => {
const { data } = await $fetch("http://laravelbackend.test/api/names");
return { data };
});
Related
After update to Nextjs 12.1.0, when I call api via api route, the following error is returned. I'm using aws amplify.
The following error is returned in the CloudFront console:
My api route:
const handlerProducts = async (req: NextApiRequest, res:NextApiResponse) => {
const params = req.query;
try {
const { data } = await axios.get(URL, {
params,
});
res.status(200).send(data);
} catch (err: any) {
res.status(500).end();
}};
What could be causing this problem?
Thanks for all the help.
I downgraded next.js to 12.0.8 and it works again
While investigating possibly the same issue, I found https://github.com/serverless-nextjs/serverless-next.js/issues/2327
zhenjie states on GitHub: "Confirmed 12.0.8 works fine, and 12.0.9 does not work."
I'm trying to make socket.io-client work in a svelte front end app to talk to an existing API server that already uses socket.io. After a number of challenges, I managed to make this work but I can only get this to work with sveltekit's preview and not in dev mode. Wondered if someone with some knowledge of those could explain why or suggest what I need to do to get it connecting in dev?
svelte 3.34.0
sveltekit next-169
socket.io(-client) 4.2.0
basic code as follows, currently within a file $lib/db.js where I define a few stores that are pulled into the layout for general use..
import { io } from "socket.io-client";
import { browser } from '$app/env';
const initSocket = async () => {
console.log('creating socket...');
let socket = io('http://192.168.1.5:4000', { 'connect timeout': 5000 });
socket.on("connect", () => {
// always works in preview...
console.log('socket created with ID:', socket.id);
});
socket.on("connect_error", (error) => {
// permanently fired in dev...
console.error('Failed to connect', error);
});
socket.on("error", (error) => {
console.error('Error on socket', error);
});
socket.on("foo", data => {
// works in preview when server emits a message of type 'foo'..
console.log("FOO:", data);
});
};
if (browser) {
initSocket();
}
// stores setup and exports omitted..
with svelte-kit preview --host I see the socket creation log message with the socket ID and the same can be seen on the api server where it logs the same ID. The socket works and data is received as expected.
with svelte-kit dev --host however, the log message from socket.on("connect").. is never output and I just see an endless stream of error messages in the browser console from the socket.on("connect_error").. call..
Failed to connect Error: xhr poll error
at XHR.onError (transport.js:31)
at Request.<anonymous> (polling-xhr.js:93)
at Request.Emitter.emit (index.js:145)
at Request.onError (polling-xhr.js:242)
at polling-xhr.js:205
Importantly, there is no attempt to actually contact the server at all. The server never receives a connection request and wireshark/tcpdump confirm that no packet is ever transmitted to 192.168.1.5:4000
Obviously having to rebuild and re-run preview mode on each code change makes development pretty painful, does anyone have insight as to what the issue is here or suggestions on how to proceed?
I've had a similar problem, I solved it by adding this code to svelte.config.js:
const config = {
kit: {
vite: {
resolve: {
alias: {
"xmlhttprequest-ssl": "./node_modules/engine.io-client/lib/xmlhttprequest.js",
},
},
},
},
};
The solution was provided by this comment from the vite issues.
I am trying to integrate socket.io with strapi. But unfortunately I have been unable to do so without any proper tutorial or documentation covering this aspect.
I followed along with the only resource I found online which is:
https://medium.com/strapi/strapi-socket-io-a9c856e915a6
But I think the article is outdated. I can't seem to run the code mentioned in it without running into tonnes of errors.
Below is my attempt to implement it and I have been trying to connect it through a chrome websocket plugin smart websocket client But I am not getting any response when I try to run the server.
I'm totally in the dark. Any help will be appreciated
module.exports = ()=> {
// import socket io
var io = require('socket.io')(strapi.server)
console.log(strapi.server) //undefined
// listen for user connection
io.on('connect', socket => {
socket.send('Hello!');
console.log("idit")
// or with emit() and custom event names
socket.emit('greetings', 'Hey!', { 'ms': 'jane' }, Buffer.from([4, 3, 3, 1]));
// handle the event sent with socket.send()
socket.on('message', (data) => {
console.log(data);
});
// handle the event sent with socket.emit()
socket.on('salutations', (elem1, elem2, elem3) => {
console.log(elem1, elem2, elem3);
});
});
};
So I found the solution. Yay. I'll put it here just in case anybody needs it.
boostrap.js
module.exports = async () => {
process.nextTick(() =>{
var io = require('socket.io')(strapi.server);
io.on('connection', async function(socket) {
console.log(`a user connected`)
// send message on user connection
socket.emit('hello', JSON.stringify({message: await strapi.services.profile.update({"posted_by"})}));
// listen for user diconnect
socket.on('disconnect', () =>{
console.log('a user disconnected')
});
});
strapi.io = io; // register socket io inside strapi main object to use it globally anywhere
})
};
Found this at: https://github.com/strapi/strapi/issues/5869#issuecomment-619508153_
Apparently, socket.server is not available when the server starts. So you have to make use of process.nextTick that waits for the socket.server to initialize.
I'll also add a few questions that I faced when setting this up.
How do i connect from an external client like nuxt,vue or react?
You just have to connect through "http://localhost:1337" that is my usual address for strapi.
I am using nuxt as my client side and this is how set up my socketio on the client side
I first installed nuxt-socket-io through npm
Edited the nuxt.config file as per it's documention
modules:[
...
'nuxt-socket-io',
...
],
io: {
// module options
sockets: [
{
name: 'main',
url: 'http://localhost:1337',
},
],
},
And then i finally added a listener in one of my pages.
created() {
this.socket = this.$nuxtSocket({})
this.socket.on('hello', (msg, cb) => {
console.log('SOCKET HI')
console.log(msg)
})
},
And it works.
A clean way to integrate third-party services into Strapi is to use hooks. They are loaded once during the server boot. In this case, we will create a local hook.
The following example has worked with strapi#3.6.
Create a hook for socket.io at ./hooks/socket.io/index.js
module.exports = strapi => {
return {
async initialize() {
const ioServer = require('socket.io')(strapi.server, {
cors: {
origin: process.env['FRONT_APP_URL'],
methods: ['GET', 'POST'],
/* ...other cors options */
}
})
ioServer.on('connection', function(socket) {
socket.emit('hello', `Welcome ${socket.id}`)
})
/* HANDLE CLIENT SOCKET LOGIC HERE */
// store the server.io instance to global var to use elsewhere
strapi.services.ioServer = ioServer
},
}
}
Enable the new hook in order for Strapi to load it - ./config/hook.js
module.exports = {
settings: {
'socket.io': {
enabled: true,
},
},
};
That's done. You can access the websocket server inside ./config/functions/bootstrap.js or models' lifecycle hooks.
// ./api/employee/models/employee.js
module.exports = {
lifecycles: {
async afterUpdate(result, params, data) {
strapi.services.ioServer.emit('update:employee', result)
},
},
};
For those who are looking the answer using Strapi version 4
var io = require("socket.io")(strapi.server.httpServer)
I'm having trouble with Laravel Echo (I think). I've built a vue chat app that works locally.
I've even cloned it onto another machine and got it working fine. But when I get it onto production, it's not working.
I'm not running npm on the server, I'm just doing a run npm prod before committing and pushing to the server.
For some reason it just doesn't work though. The messages are getting through to pusher as I can see them in the debug console.
Here's some of the code:
mounted() {
console.log('mounted');
Echo.private(`messages.${this.user.id}`)
.listen('NewMessage', (e) => {
console.log('in echo');
this.hanleIncoming(e.message);
});
axios.get('/contacts')
.then((response) => {
this.contacts = response.data;
});
},
methods: {
startConversationWith(contact) {
this.updateUnreadCount(contact, true);
axios.get(`/conversation/${contact.id}`)
.then((response) => {
this.messages = response.data;
this.selectedContact = contact;
})
},
saveNewMessage(message) {
console.log(message);
this.messages.push(message);
},
hanleIncoming(message) {
if (this.selectedContact && message.from == this.selectedContact.id) {
console.log('inside if of handleincoming');
this.saveNewMessage(message);
return;
}
this.updateUnreadCount(message.from_contact, false);
}
}
When local I get all the console.logs, but on prod I only get one and that's because saveMessage gets called on hitting enter from the message chat window. Do I need to install something on the server to get echo to work since I'm not doing npm install on the server. I don't think node is even installed. How can I get echo to work on production? Any help would be appreciated!
Have you started echo server on production?
I have upgraded my CRA to version 3.10.8 as it has built in support for PWA.
As a next step I have registered my service worker in the index.js and I think it got registered succesfully.
Now my main goal is to have some offline caching for our API calls (backend in Rails), so that when there is no network I can serve the cached response .
Is there anything else that I need to do to serve cached API responses.
When I built my app with Create react App, all it did was create a file called
registerServiceWorker.js and then this gets called from the index.js.
Also the final app we are building is packaged with Codova so most of the Assets will be in local , our main aim is to cache the API calls. Is this the right way to go. We are using Redux for state management, but have not use any persistence as of now.
Any help/tips would be highly appreciated.
registerServiceWorker.js code below...
// In production, we register a service worker to serve assets from local cache.
// This lets the app load faster on subsequent visits in production, and gives
// it offline capabilities. However, it also means that developers (and users)
// will only see deployed updates on the "N+1" visit to a page, since previously
// cached resources are updated in the background.
const isLocalhost = Boolean(
window.location.hostname === 'localhost' ||
// [::1] is the IPv6 localhost address.
window.location.hostname === '[::1]' ||
// 127.0.0.1/8 is considered localhost for IPv4.
window.location.hostname.match(
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
)
);
export default function register() {
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
// The URL constructor is available in all browsers that support SW.
const publicUrl = new URL(process.env.PUBLIC_URL, window.location);
if (publicUrl.origin !== window.location.origin) {
// Our service worker won't work if PUBLIC_URL is on a different origin
// from what our page is served on. This might happen if a CDN is used to
// serve assets; see https://github.com/facebookincubator/create-react-app/issues/2374
return;
}
window.addEventListener('load', () => {
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
if (!isLocalhost) {
// Is not local host. Just register service worker
registerValidSW(swUrl);
} else {
// This is running on localhost. Lets check if a service worker still exists or not.
checkValidServiceWorker(swUrl);
}
});
}
}
function registerValidSW(swUrl) {
navigator.serviceWorker
.register(swUrl)
.then(registration => {
registration.onupdatefound = () => {
const installingWorker = registration.installing;
installingWorker.onstatechange = () => {
if (installingWorker.state === 'installed') {
if (navigator.serviceWorker.controller) {
// At this point, the old content will have been purged and
// the fresh content will have been added to the cache.
// It's the perfect time to display a "New content is
// available; please refresh." message in your web app.
console.log('New content is available; please refresh.');
} else {
// At this point, everything has been precached.
// It's the perfect time to display a
// "Content is cached for offline use." message.
console.log('Content is cached for offline use.');
}
}
};
};
})
.catch(error => {
console.error('Error during service worker registration:', error);
});
}
function checkValidServiceWorker(swUrl) {
// Check if the service worker can be found. If it can't reload the page.
fetch(swUrl)
.then(response => {
// Ensure service worker exists, and that we really are getting a JS file.
if (
response.status === 404 ||
response.headers.get('content-type').indexOf('javascript') === -1
) {
// No service worker found. Probably a different app. Reload the page.
navigator.serviceWorker.ready.then(registration => {
registration.unregister().then(() => {
window.location.reload();
});
});
} else {
// Service worker found. Proceed as normal.
registerValidSW(swUrl);
}
})
.catch(() => {
console.log(
'No internet connection found. App is running in offline mode.'
);
});
}
export function unregister() {
if ('serviceWorker' in navigator) {
navigator.serviceWorker.ready.then(registration => {
registration.unregister();
});
}
}
I am using the Create-react-app version 3.
change the condition statement, Remove the codition (process.env.NODE_ENV === 'production' &&) it should only have if('serviceWorker' in navigator).
create your custom-service-worker file in public folder rewrite the following code as const swUrl = ${process.env.PUBLIC_URL}/service-worker.js as swUrl = ./custom-service-worker.js.
In the custom-service-worker.js file in public folder add the follow code, please refer the sample external api calls( place your api urls to be cached)
importScripts("https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js");
if (workbox) {
console.log('workbok loaded', workbox.routing)
}
//to cache the css html js and images files
workbox.routing.registerRoute(
/\.(?:js|html|css|images|svg)$/,
new workbox.strategies.NetworkFirst()
);
workbox.routing.registerRoute(
'http://localhost:3000',
new workbox.strategies.NetworkFirst()
);
//to cache the external api calls
workbox.routing.registerRoute(
new RegExp('https://jsonplaceholder.typicode.com/users'),
new workbox.strategies.StaleWhileRevalidate()
);
//to cache the external api calls
workbox.routing.registerRoute(new RegExp('http://insight.dev.schoolwires.com/HelpAssets/C2Assets/C2Files/C2ImportUsersSample.csv'),
new workbox.strategies.StaleWhileRevalidate()
);