Using nest js SSE not working as per our request.
Client side code:
const eventSource = new EventSource('http://localhost:8083/sse')
eventSource.onmessage = ({ data }) => {
console.log(data)
}
Server-side code on nest js:
controller file ->
#Sse('sse')
sse(): Observable<MessageEvent> {
return this.indexSer.sse('Test SSE on')
}
service file->
sse(headers, de): Observable<MessageEvent> {
return interval(1000).pipe(map((_) => ({ data: {hello:'world'} } as MessageEvent)))
}
Need help in call
Another controller to call service file SSE but not send data on the client-side.
xyz controller -> like :
return this.indexSer.sse('Test SSE again on')
Related
I have a remix application to act like frontend.
I load data from my backend and for some data I need to load it only once and reuse it on different pages.
In previous frontend we used localstorage but here is server side which returns me ReferenceError: window is not defined
import {LoaderFunction} from "#remix-run/node";
import authenticator from "~/services/auth.server";
import Layout from "~/src/Layout";
import {fetchData} from "~/services/fetch.service";
export let loader: LoaderFunction = async ({request}) => {
const user = await authenticator.isAuthenticated(request, {failureRedirect: "/login",});
const configs = await fetchData('GET', request, 'api/configs/all')
.then((response) => {
return response;
})
.catch(async error => {
await authenticator.logout(request, {redirectTo: "/login"});
});
try {
localStorage.setItem('parameters', configs);
} catch (e) {
console.log(e);
}
return {
user: user,
request: request
};
};
export default function DashboardPage() {
const data = useLoaderData();
return (
<Layout user={data?.user} request={data.request}>
</Layout>
);
}
I need the config to be accessable at any time, it's not usefull if I need to load it all the time.
You can't use localStorage on the server-side, since it is first set on the client. You could use cookies since they are accessible on the server-side.
I am writing React.js application talking to API server. I have read tons of articles on how to mock these calls and send some fake response from API. I can do testing using #testing-library/react, I can easily mock axios with axios-mock-adapter and test fetch requests using HTTP GET method. But I cannot find anywhere how to make sure that my app, when it sends some POST request, sends correct data to API, i.e. that my app sends json payload with e.g. "id" field, or "name" field set to "abc", or something like this.
I am new to React.js. Please advise how to make tests asserting what the app sends to API. Is it possible?
Let's say that I have a function named doSomething, like below, called with onClick of some button.
const doSomething = async (userId, something) => {
try {
await REST_API.post('doSomething', {
user_id: userId,
something: something
});
return true;
} catch (error) {
window.alert(error);
return false;
}
};
REST_API above is axios instance.
How can I ensure that the I (or some other developer) didn't make a typo and didn't put "userId" instead of "user_id" in the payload of the request?
If you have to be sure you call correctly the api, I'd use jest as follow:
jest.mock('axios', () => ({
post: jest.fn(),
}));
describe('test', () => {
it('doSomething', () => {
const userId = 123;
const something = 'abc';
doSomething(userId, something);
expect(axios.post).toBeCalledWith(
'doSomething', {
user_id: userId,
something,
},
);
});
});
or if you use instance, define it in another file (axios_instance.js) and using the follow test:
jest.mock('./axios_instance', () => ({
instance: {
post: jest.fn(),
},
}));
describe('test', () => {
it('doSomething', () => {
const userId = 123;
const something = 'abc';
doSomethingInstance(userId, something);
expect(instance.post).toBeCalledWith(
'doSomething', {
user_id: userId,
something,
},
);
});
});
For your need I would use Swagger and its tooling. You would kill three birds with one stone :
Have a proper API documentation : https://swagger.io/tools/swagger-ui/
Protect Backend : Ensure inputs/outputs are valid, and throw detailed exception if a client sends bad data : https://github.com/cdimascio/express-openapi-validator-example
Protect Frontend : Use client api generation to genrate js classes used by your clients .. That way they won't arbitrarily create objects manually and send them to server (crossing fingers) but use a dedicated API with setters : https://github.com/swagger-api/swagger-codegen
That way you have a rock solid Frontend + Backend + Documentation combo ..
I am working on an application where I want to implement the message Inbox. I have created the message inbox using Angular8 and NodeJS REST API. Now I want to get the on inbox message in every 30 Second on the background when user login also it doesn't want to affecting the performance of the Angular app.
So I want to Implement the Web-worker with Angular8 to get the Data from NodeJS REST API but I am unable to create.
I have added following code in Angular 8 App
Add this code to app.component.ts
getWorker(token){
if (typeof Worker !== 'undefined') {
// Create a new
const worker = new Worker('../../web-worker/messenger.worker', { type: `module` });
worker.postMessage(token);
worker.onmessage = (e) => {
setTimeout(() => {
worker.postMessage(token)
}, 15000);
};
} else {
// Web Workers are not supported in this environment.
// You should add a fallback so that your program still executes correctly.
}
}
Created worker file with fetch
/// <reference lib="webworker" />
addEventListener('message', ({ data }) => {
const response = `worker response to ${data}`;
postMessage(response);
});
import { environment } from "src/environments/environment";
onmessage = (message:any) => {
fetch(environment.apiUrl +'messages/notification/1/1',
{ method:'GET',
headers:new Headers({
Authorization: `Bearer ${message.data}`
})
}
)
.then(response => {
return response.json()
})
.then(commits => {
// self.onmessage(message)
return commits
});
};
but it shows the type as fetch is should be show web worker Right?
Can anyone help me with this?
I'm building an electron app and need to call APIs where the API provider has not enabled CORS. The typically proposed solution is to use a reverse proxy which is trivial to do when running locally by using node and cors-anywhere like this:
let port = (process.argv.length > 2) ? parseInt (process.argv[2]) : 8080;
require ('cors-anywhere').createServer ().listen (port, 'localhost');
The app can then be configured to proxy all requests through the reverse proxy on localhost:8080.
So, my questions are:
Is it possible to use node and cors-anywhere in an electron app to create a reverse proxy? I don't want to force the app to make calls to a remote server.
Is there a better or standard way of doing this in an Electron app? I'm assuming I'm not the first to run into CORS issues. :)
Just overide header before send request using webRequest.onBeforeSendHeaders
const filter = {
urls: ['*://*.google.com/*']
};
const session = electron.remote.session
session.defaultSession.webRequest.onBeforeSendHeaders(filter, (details, callback) => {
details.requestHeaders['Origin'] = null;
details.headers['Origin'] = null;
callback({ requestHeaders: details.requestHeaders })
});
put these codes in renderer process
In my application, it wasn't sufficient to remove the Origin header (by setting it to null) in the request. The server I was passing the request to always provided the Access-Control-Allow-Origin header in the response, regardless of it the Origin header is present in the request. So the embedded instance of Chrome did not like that the ACAO header did not match its understanding of the origin.
Instead, I had to change the Origin header on the request and then restore it on the Access-Control-Allow-Origin header on the response.
app.on('ready', () => {
// Modify the origin for all requests to the following urls.
const filter = {
urls: ['http://example.com/*']
};
session.defaultSession.webRequest.onBeforeSendHeaders(
filter,
(details, callback) => {
console.log(details);
details.requestHeaders['Origin'] = 'http://example.com';
callback({ requestHeaders: details.requestHeaders });
}
);
session.defaultSession.webRequest.onHeadersReceived(
filter,
(details, callback) => {
console.log(details);
details.responseHeaders['Access-Control-Allow-Origin'] = [
'capacitor-electron://-'
];
callback({ responseHeaders: details.responseHeaders });
}
);
myCapacitorApp.init();
});
Try this if you are running web apps in localhost
const filter = {
urls: ['http://example.com/*'] // Remote API URS for which you are getting CORS error
}
browserWindow.webContents.session.webRequest.onBeforeSendHeaders(
filter,
(details, callback) => {
details.requestHeaders.Origin = `http://example.com/*`
callback({ requestHeaders: details.requestHeaders })
}
)
browserWindow.webContents.session.webRequest.onHeadersReceived(
filter,
(details, callback) => {
details.responseHeaders['access-control-allow-origin'] = [
'capacitor-electron://-',
'http://localhost:3000' // URL your local electron app hosted
]
callback({ responseHeaders: details.responseHeaders })
}
)
Just had this issue today API calls with axios inside a React app bundled in Electron is returning 400
From what I can see Electron calls act as normal calls to the API urls meaning they are not affected by CORS.
Now when you wrap your calls with a CORS proxy and make a regular call to the proxy, it should error with a 400 error because it's not a CORS call.
This thread explains why cors-anywhere responds like that => https://github.com/Rob--W/cors-anywhere/issues/39
I actually removed my CORS proxies from the app before the Electron build. I still need the CORS proxy for development since I'm testing in the browser.
Hope this helps.
You can have the main process, the NodeJS server running Electron, send the request. This avoids CORS because this is a server-to-server request. You can send an event from the frontend (the render process) to the main process using IPC. In the main process you can listen to this event, send the HTTP request, and return a promise to the frontend.
In main.js (the script where the Electron window is created):
import { app, protocol, BrowserWindow, ipcMain } from ‘electron’
import axios from 'axios'
ipcMain.handle('auth', async (event, ...args) => {
console.log('main: auth', event, args) const result = await axios.post(
'https://api.com/auth',
{
username: args[0].username,
password: args[0].password,
auth_type: args[1],
},
) console.log('main: auth result', result)
console.log('main: auth result.data', result.data) return result.data
})
In your frontend JS:
import { ipcRenderer } from 'electron'
sendAuthRequestUsingIpc() {
return ipcRenderer.invoke('auth',
{
username: AuthService.username,
password: AuthService.password,
},
'password',
).then((data) => {
AuthService.AUTH_TOKEN = data['access_token']
return true
}).catch((resp) => console.warn(resp))
}
I wrote an article that goes into more depth here.
While I have struggled a while with the existing answers I will provide here the solution that finally worked for me, assuming that you are on the main process.
Here are the steps involved:
You need to have access to the session object which can be obtained by one of two ways:
A) via the global session.defaultSession which is available after the app is ready.
const { session } = require('electron');
const curSession = session.defaultSession;
B) The other method is via the session on the BrowserWindow, this assumes that the windnows is already created.
win = new BrowserWindow({});
const curSession = win.webContents.session;
Once you have the session object you set the response header to the site you are sending the request from.
For example, let's say your electron BrowserWindow is loaded from http://localhost:3000 and you are making a request to example.com, here would be some sample code:
const { app, BrowserWindow, session } = require('electron');
app.whenReady().then(_ => {
// If using method B for the session you should first construct the BrowserWindow
const filter = { urls: ['*://*.example.com/*'] };
session.defaultSession.webRequest.onHeadersReceived(filter, (details, callback) => {
details.responseHeaders['Access-Control-Allow-Origin'] = [ 'http://localhost:3000' ];
callback({ responseHeaders: details.responseHeaders });
}
// Construct the BrowserWindow if haven't done so yet...
});
Have you tried using fetch()
Check how to use fetch to make a no-cors request here
https://developers.google.com/web/updates/2015/03/introduction-to-fetch?hl=en
Im building a small chat application using react,redux,socketio and node with mongoose. Normally redux flows through actions (which makes API calls and receive data) and dispatch the data. But in my case the socket will emit to a certain event but it would not return data until we manually emit the data from the back-end. so to achieve the proper redux flow should i add a socket event on actions to retrieve the data (coming from back-end) and then dispatch it or is there any other proper way to achieve this?
Here is a sample code of what i'm planing to do in
Actions file
function sendMessage(data) {
return {
type: SEND_MESSAGE,
payload: data
};
}
export const sendNewMessage = (socket,data) => {
return dispatch => {
socket.emit("send message",data);
socket.on("new message",function(data){
dispatch(sendMessage(data));
});
};
};
That seems perfectly reasonable to me. I would suggest using thunk's "extra argument" for this such that your components do not need to know about the actual socket object:
const store = createStore(
reducer,
applyMiddleware(thunk.withExtraArgument({ socket }))
)
export const sendNewMessage = (data) =>
(dispatch, getState, { socket }) => {
socket.emit("send message", data)
socket.on("new message", (data) => {
dispatch(sendMessage(data))
})
}