I am using express the first time in a project as a kind of reverse proxy in between my frontend and backend. The backend authentication is cookie based.
First I was using http-proxy-middleware to make my requests. This works fine and the cookie gets passed no problem.
The problem is that I want to decouple the front and backend as the api isn't very usable right now (for example 3 requests necessary to get data for one view). So instead of making requests directly I want to have my express server handle the heavy lifting in the background.
Currently I am using axios for the requests and pass the cookie through with the request and the new one back with the response. This works fine but feels very hacky and error prone. For example I have to split the returned setcookie string in a very weird way.
app.get('/api/myrequest', (req, res) => {
axios.get('backendserver/url', {
headers: {
Cookie: req.cookies['auth'],
},
responseType: 'json',
})
.then((response) => {
let tempCookie = response.headers['set-cookie'][0];
tempCookie = tempCookie.split(';')[0];
tempCookie = tempCookie.split('=');
res.cookie(tempCookie[0], tempCookie[1]);
res.send(response.data);
})
});
I suppose there is a much better way to handle this. I was looking at things like passportjs but am not sure if it fits this special use case as the auth isn't handled by express itself.
Maybe someone can point me in the right direction?
Related
I'm working on the frontend part of some REST API (link, json validation and in generale controlling)
I'm trying to figure out how it works in the backhand, there should be a database I guess and each API call correspond to a specific query?
could you suggest me guide on how such implementation are usually build?
I'm only finding formal guide on how to shape url for rest API
thanks
It is a quite generale / cultural question, not technical
There's no standard way, the point of a protocol like HTTP (what REST is based on) is to decouple this kind of details and leave the server implementor to be free of doing it however it wants.
There are a lot of different ways and listing them all is very hard.
For a simple service what you said is true, for more complex scenario behind a REST endpoint there could be a service doing calls to other services and aggregating their responses into the json you see.
You would usually have a single endpoint do a single task but you could also do anything you want with the data provided from the user. You could carry out regex validations, store it inside a database, send it to another API, extract data out of it, and plenty of other things.
Here is an example I wrote in Node.js:
const signup_post = async (req, res) => {
const { email, password, username } = req.body;
try {
const user = await User.create({ email, password, username });
const token = createToken(user._id);
res.cookie('jwt', token, { httpOnly: true, maxAge: maxAge * 1000 });
res.status(201).json({ user: user._id });
}
catch(err) {
const errors = handleErrors(err);
res.status(400).json({ errors });
}
}
This example code, we are taking the user-provided data, making a new entry in the database with a pre-defined schema, creating a JWT token and attaching it to a cookie, and sending the cookie back to the client. This is one way to handle authentication- and as long as the client has this cookie, they will stay logged in.
We are also handling any errors and validating the user-provided data to make sure it fits our database schema.
I have an endpoint written in expressjs
router.post("/mkBet", async (req, res) => {
console.log(req.body)
const betToPush = new Bet({
addr: req.body.address,
betAmount: req.body.amount,
outcome: req.body.didWin,
timePlaced: Math.round(+new Date()/1000)
})
try {
const newBet = await betToPush.save()
res.status(201).json(newBet)
} catch(err) {
res.status(400).json({message: err.message})
}})
And I am trying to make it so that it can only be called when an action is performed on the frontend. So users cannot call it with custom arguments to make it so the outcome is always true. What would be the best way to achieve this?
It is not possible to securely tell what client sent the request. In other words, a request from your client and a different one can be identical in general.
Talking about unmodified browsers (as opposed to non-browser tools like Postman), you can tell the origin of the request (~the url loaded in the browser when the request was sent) with some confidence from the Origin and Referer request headers. However, your backend needs authentication and authorization anyway.
With the latter two in place, ie. with proper security implemented on the server-side, it doesn't matter anymore what client sends the requests.
Can't see to find any good docs on how to mock/stub the server Sider side requests with playwright.
An example would be to intercept the getServerSideProps in nextjs: hitting the routes makes the server do a request (db API etc). Then it can do some business logic (which should also be covered by testing) before it is passed to the component as props which is sent to the client (being server side rendered).
Mocking that db API request without having some test logic mixed into the business logic is what I am hoping to find an answer for.
Playwright allows you to do interception and mocking/stubbing.
UI action can triger the API call, and without sending request you can intercept
the response.
And you can use moks and stubs as well.
const mock = { animals: [] }
await page.route('**/Zoo/v1/books', (animals) =>
route.fulfill({
status: 304,
body: JSON.stringify(mock),
})),
);
await page.goto('https://www.demoqa/animals');
See more https://github.com/microsoft/playwright/issues/1774#issuecomment-769247500
And https://playwright.dev/docs/next/network#modify-responses
I have this use case:
- I'm working on a game with a webapp for user management and chat, which is on MERN, and a unity game, with socket.io as the real time messaging layer for the multiplayer game.
- User may register to webapp by either providing a pair of email/password, or getting authenticated on FB/Gamil/etc. as usual, in which case the user's email is obtained and saved to MongoDB and this is done by passport.
- There is no session in express side, and socket.io is on a redis. There is no cookie but JWT is used.
My problem is that I don't know what's the best practices in this. I read this
article
and this
one
which both have content and code close to what I want to do, but in the first one:
app.use(express.cookieParser());
while I don't want to use cookie at all, and the other one also has in code:
cookie: {
secure: process.env.ENVIRONMENT !== 'development' && process.env.ENVIRONMENT !== 'test',maxAge: 2419200000}...
Also, I found this on
github
which suggests for the client side (unity):
var socket = io.connect('http://localhost:9000');
socket.on('connect', function (socket) {
socket.on('authenticated', function () {
//do other things
})
.emit('authenticate', {token: jwt}); //send the jwt
});
meaning that:
1. socket is created
2. authentication is requested
but I think that the approach I found in the other article is better, where the socket is not created at all if the JWT for auth is not provided at the first ever connection request sent to "io", so if I'd do it I'd issue:
var socket = io.connect('http://localhost:9000', {query: {"JWT":"myjwt"}});
and in my server side where I have:
io.on("connection", function(socket){...});
I'd like to first get the JWT:
var jwt = socket.handshake.query["JWT"];
and then if auth will be unsuccessful, simply return socket.disconnect('reason') and do not open any connection at all (here maybe I just didn't understand, say, that the approach the Author took in the github source is using a middle ware technique and it is maybe also done before anything else).
I still could not find out what is the best practice that Gurus use, please help me get clear.
Does there exist a thirdparty middleware or a way to create such middleware for Express.js that allows for intercepting all requests and inspecting the request's body content without affecting subsequent middleware such as bodyParser or route endpoints which may rely on the raw body such as express-http-proxy?
From what I can tell bodyParser itself seems to work in a somewhat obtrusive way that does not allow a route to override the default parsing behavior. The express documentation describes how request.body is filled in by middleware such as bodyParser. This behavior of bodyParser makes sense from simplicity and performance perspective but doesn't make it a great candidate for creating middleware which needs to inspect the contents of a request and let the remaining portion of the app working without modification. This is especially true seeing that depending on the parsing middleware the results may be in entirely different formats. After some digging I'm left wondering if it's generally possible to pull this off with express or perhaps once you read the request body you eliminate the ability to make use of further middleware such as bodyParser or express-http-proxy which expect to access the body directly.
Possibly related:
express req.pipe() does not work
You could always use the raw-body package with express middleware like so:
var getRawBody = require('raw-body');
var typer = require('media-typer');
app.use(function (req, res, next) {
getRawBody(req, {
length: req.headers['content-length'],
limit: '1mb',
encoding: typer.parse(req.headers['content-type']).parameters.charset
}, function (err, string) {
if (err) return next(err)
req.text = string
next()
})
})
If your only concern is performance, I wouldn't worry too much about body-parser as it's unlikely to have a massive performance impact. If you can, I'd suggest you just use body-parser with a typical express middleware app.use(..) to inspect the request body.