I'm developing a Nuxt app that is going to have multiple domains, e.g. example1.com, example2.com, etc (This is handled by nginx)
What is important here, is that the back-end API acts based on the Origin header which is sent from the Nuxt app and sends corresponding data based on Origin.
In nuxtServerInit I'm calling some back-end API to load some data (using axios), but the problem is that Origin header is not being sent to the back-end. It also does not make sense to set Origin manually as window is undefined in that initial API call.
Here's my nuxtServerInit function:
async nuxtServerInit(_vuexContext, { $accessor, error }: Context) {
try {
const config = await this.$axios.$get('/v1/config/')
console.log(config)
} catch (e: any) {
console.error(e)
return error({ statusCode: 500, message: e.message })
}
},
Now I want to know, is there a way to set the Origin header in server?
Is there a workaround for that? Or do you have a better solution for my case?
You can still set the Origin header manually, without access to the window. You’ll find the origin of the original request (eg. example1.com) in the req object, which is available in the Nuxt context (but only on the server side).
I think you know this already, but calling your API from nuxtServerInit generates a new request on the node side— which doesn’t have an origin header by default. You can grab the correct origin from the original request as above, and stick it in a header on the new request.
I’ll assume your use case lends itself to this approach, and you’ve considered alternatives to spoofing the origin of your node-side request.
Related
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.
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?
I have a React App that uses React Router and Redux as its state manager. The server side of the app uses Express and Node.
I am making API calls to an external service. I do not have the ability to enable CORS on the external service. Therefore, I need to use my app's server side to make the calls to the external service to remove the browser from the equation, and eliminate any CORS error.
I am able to get my data from the service on the server side successfully. I would like to know if it is possible to share the Redux store in between the client and server with some sort of middleware (looking for examples/resources).
The goal:
1) Handle a click event in the client
2) Have that event call a server side route to external api (don't know how to do this)
3) Then the server handles this route, makes the request, and sends the response to the client (through the shared react store - not sure if this is possible)
4) The store gets the new state, and then sends to the client side components, and the UI updates
Are there any examples/tutorials of this? Not looking for an initial server rendered page, but guides that inform how the above 4 steps can generally be implemented.
Thanks for the suggestions.
It turns out that I was severely over thinking the solution. All I really needed was the ability to launch a server side function (get resources from external API) from the client side event (load component). Sort of like how submitting a form, has an action that launches a server side function.
In my component:
componentDidMount() {
const product_api_results = productApi.getProductItems()
console.log('product_api_results in CART Component: ', product_api_results)
/* now I have results and can put it in the Redux Store via action to reducer for other components to work with on client */
}
The productAPI.getProductItems() that the component calls:
export function getProductItems () {
return axios.get('/api/get-products') // triggers a server side route
.then(function (response) {
console.log('client side response: ', response)
return response
})
}
In Express server.js file, the server will see this url and then get the proper data. The shopify.get() is from the shopify-node-api module:
app.get('/api/get-products', function (req, res) { // '/api/get-products' called from client
shopify.get('/admin/products.json', function (err, data, headers) {
res.send(data)
})
})
I am using the HTTP.call to make Restful API calls to a third party service provider.
I created relevant Meteor Methods at the server side and call them from the client.
I have no problem for the GET calls. However for POST and PUT calls, it returns Internal server error (500) at client and a 405 Method not allowed at server.
When I tried debugging it, I opened Meteor Shell and calling the POST and PUT calls there, they work. But they don't when I call the methods from client.
Client side I have...
Meteor.call('cancelCall', function (err, res) {
if (err) {
console.log(err);
} else {
console.log(res);
}
});
And Server side...
Meteor.methods('cancelCall', function () {
var url = 'http://example.com/some/params/cancel';
var result = HTTP.call('PUT', url);
return result;
});
What I type directly to Meteor Shell...
HTTP.call('PUT', 'http://example.com/some/params/cancel');
What's causing this behaviour and how to fix it?
Many thanks.
Wrapping these calls in methods is unnecessary, as HTTP.call (and associated methods) can be called directly on the client.
Docs: The call signature looks like this:
HTTP.call('PUT', url, [callOptions], [asyncCallback])
On the server you can omit the asyncCallback parameter, and the call simply blocks until it has a result.
On the client this cannot be omitted, as only async calls are possible.
Also you are not providing any data for the PUT (/POST) method. This should be passed in the callOptions parameter like this:
HTTP.call('PUT', url, {params: {user: userId}}, callbackFunc)
However for POST and PUT calls, it returns Internal server error (500)
at client and a 405 Method not allowed at server.
When you make POST and PUT requests server side you are getting Error 405 returned. That tells you that the api you are calling does not accept POST and PUT requests.
This part is a guess:
When you make these same requests from the client via Meteor.method calls, your app server is making the request, and getting 405 errors from the remote server. This then causes your server to return 500 (Internal Server Error) back to the client.
I have a REST server which returns a Link HTTP header with a response to a PUT to indicate the URL of the newly-created entity:
Link:<entities/6>; rel="created"
Is there any possibility to read that link header with Restangular?
The only facility to intercept HTTP requests with Restangular I've met so far is to register a response interceptor in the app config:
restangular.addResponseInterceptor(function (data, operation, what, url, response, deferred) {
console.log(response.headers())
return response.data;
});
However, with above demo implementation in place, the only HTTP header which gets logged is content-type. Still, I can see in the browser development toolbar that a response comes indeed with many additional HTTP response headers, such as Server, Date, and the aforementioned Link.
Why do I not have access to the full array of HTTP response headers through addResponseInterceptor()? Is there any way to capture the HTTP response header in question using Restangular?
Note: I don't search for an answer using HAL or any other special response body format. I would rather like to know whether I can use plain HTTP headers with Restangular or not (if not, I will probably resort to HAL or something).
You don't need a ResponseInterceptor to do this. You just need to set fullResponse to true to get the whole response (including the http headers) every time you do any request.
Restangular.setFullResponse(true);
You can set it globally in your app configuration. Something like this:
angular.module('YourApp')
.config(['RestangularProvider',
function (RestangularProvider) {
RestangularProvider.setFullResponse(true);
...
Then, every time you receive a response, you can access all the response headers.
Restangular.all('users').getList().then(function(response) {
$scope.users = response.data;
console.log(response.headers);
}
Example:
response.headers('Link')
NOTE: Be careful because using fullResponse, the response data is located in response.data, not directly in response.
EDIT: As #STEVER points, you also need to expose the headers in your server API.
Example:
Access-Control-Expose-Headers: Link
You can get more detailed information in Restangular documentation
Hope it helps.