Authentication between React frontend and Node backend - json

I think I'm having an issue passing a session from my Node backend to my React frontend, but I'm in kind of an I don't know what I don't know situation. Can anyone help?
Here's the issue:
I've got this route on the backend..
app.get('/account', ensureAuthenticated, function(req, res){
res.status(200).json({ user: req.user });
});
which spits out userdata JSON upon a successful Steam Passport authentication. I can verify this works when I check the account page generated by EJS views.
On the React server, I have a root page with a link to Steam auth. It successfully goes to Steam, then redirects back to the root page.
When I try to do a JSON fetch to '/account' from the root React page, the response is no longer JSON, but is HTML from the backend's '/account' template, but I need JSON of course.
I think it's not recognizing me as authenticated, because I get the same HTML response when doing a GET request using Chrome's Advanced REST client extension.
I should also note that I'm proxying the API server via Create React App's proxy feature.
UPDATE: Problem solved.
fetch('https://example.com:1234/users', {
credentials: 'include'
})

It sounds like the issue may be due to the order of app.get calls, or the configuration of your node server – likely the EJS templates.
I would look for where you're doing something like app.set('view engine', 'ejs'); and where you're doing app.get('/account'....
You'll want to do the app.get('/account'.. before you do app.set('view engine...
If you actually hit the /account route you should get either a 401 or the JSON response, not HTML (EJS).

Related

How to send html form data to nodejs

The answer for Node.js - How to send data from html to express solves the problem I have by using a different port for the server. I was wondering how live websites for example this website (stackoverflow's search bar) use a form action that is a directory ("/search") instead of a port similar to the answer at the link? Is node.js incapable of listening to a directory or am I ignorant when it comes to how http requests work?
You listen on a port for http requests. Your front end will do an ajax(asynchronous javascript and xml) request in your javascript code to a route on your server through a port.
If you want a good tool for making easy ajax requests, you can use jQuery, or Axios, and look up how to do ajax with those libraries.
On the back end your server is listening to a port for requests to routes. Set up a route(what you've called a directory) to respond to requests to a particular URL. The example you mentioned showed:
app.post('/myaction', function(req, res) {
res.send('You sent the name "' + req.body.name + '".');
});
Express is a backend framework for doing all kinds of things, but most commonly, handling HTTP requests and rendering HTML. So on the front end when you make your ajax request to /myaction, you can respond like this:
app.post('/myaction', function(req, res) {
res.render('templateFileToRender', { dataToDynamicallyTurnIntoHTML: data } );
});
Express will render your template file, then send the HTML to your front end, and you will update your frontend div or whatever with the rendered HTML.
If you want more info please leave a comment

How to serve static (or dynamic?) HTML files with RESTful API?

Hi I'm studying about RESTful API and making a website running on local to exercise.
I think RESTful is a quite good way. CRUD operations can be identified by HTTP methods and we can handle them with one url.
But most confusing things to me is that, How can we serve HTML files which are needed to request CRUD operations?
For example, If I'm implementing a forum, I need APIs to CRUD posts in forum like
[GET] /forum - see all posts in forum
[POST] /forum - create a new post
[GET] /forum/:id - see the post of id
[PUT] /forum/:id - modify the post of id
[DELETE] /forum/:id - delete the post of id
Think about how we use a forum, we need at least 3 type of HTML pages.
They are,
1. a page to see all posts in forum.
2. a page to see the specific post.
3. a page to type title and contents to create(or modify) a new post.
First and second type of HTML files can be served easily by GET requests above.
But in case of third type HTML files, I need to use extra parameters with above APIs or make a new API such like /forum/createpost to serve such HTML files.
I think, in the point of view of RESTful, I miss something and need to distinguish serving static (or dynamic) HTMLs and handling CRUD requests.
What is the bestpractices to handle this problem?
I also find some questions about this problem, but I couldn't find a clear answer.
I think you are mixing up two separate parts of the application. One is the REST API that provides the endpoints for CRUD operations. The HTML files that send the API requests are not part of the REST API. They are served by a web application that provides the front-end to the user, and makes calls to the REST API in the backend to fetch the information to display. To put it in another way, the web application making the calls is your Presentation layer. The REST API is your Business logic. Presumably, the REST API interacts with a database to write data to and read data from it. That is your Persistence or Storage layer.
You can use HTTP content type negotiation for that. POST/PUT requests (can) contain a Content-Type header declaring the type of content they're sending, and—more importantly—all requests contain an Accept header declaring the kinds of responses it accepts. If the client is accepting text/html responses, serve an HTML page; if they're accepting, say, application/json responses, serve a "RESTful" JSON response. This way your server can respond to different situations with the appropriate content and the same endpoint can serve as API and as HTML handler.
Alternatively, you can distinguish the request by using an extension: /posts.html serves a plain HTML file, while /posts gets served by a REST endpoint. That can easily be done in the web server configuration.
This might or might not be an anwser to your problem, however since you're working in Node + Express, routing might be a way to go (If I understood your question correctly). Below is an example of server implementation of accepted routes with parameters. Note, you can make parameters optional in some cases if needed.
app.get('/', function (req, res) {
res.send('Index')
})
app.get('/forum', function (req, res) {
res.send('Forum Index')
})
app.get('/forum/:id', function (req, res) {
// To access id you do 'req.params.id'
res.send('Forum Index')
})
app.put('/forum/:id', function (req, res) {
res.send('Modify Forum')
})
app.delete('/forum/:id', function (req, res) {
res.send('Delete Forum')
})
Reference : https://expressjs.com/en/guide/routing.html

MEAN.js $http.get() return index html content instead of json file

I'm doing a web app based on original MEAN.js framework. When I want to request local json test file using $http.get() method in my AngularJS file, it returned my index html content.Is it a routing problem? I didnot change the original mean.js routing code(https://github.com/meanjs/mean), just added a $http.get() method in home.client.controller.js file. Can anyone help me with this? Thanks!
That is most likely happening, because you didn't define an endpoint for that particular GET request in your app.
Everytime you make a request to your server (for example a GET request to /my-request) nodejs/express are configured in MEAN.js so that your server will try to find the endpoint for that request, if it does not find any, that request will be handled by this particular code block (specified in /modules/core/server/routes/core.server.routes.js):
// Define application route
app.route('/*').get(core.renderIndex);
Which will basically render the index view.
I'm not sure if you're using a custom module or not, eitherway, if you want that request to be handled in a different way in MEAN.js, you can specify your endpoint in your custom module routes file (or in core.server.controller.js) like so:
// Define application route
app.route('/my-request').get(core.sendMyJSON);
Be careful, because this route must be placed before the one I mentioned earlier, otherwise your request will still be handled the same way and the index view will be rendered and served again.
Then you will have to create the controller that should be called to handle that request:
exports.sendMyJSON = function (req, res) {
// logic to serve the JSON file
};
This way you should be able to get it done with a few adjustments.
Side note:
I'm not entirely sure but I think if you place your JSON file in the public directory of your app you should be able to directly access it without the need for the extra logic.

Where to implement webhook routes in a feathersjs app?

Assuming a Feathers app with the following directory structure:
- src
-- hooks
-- middleware
-- services
Where is an appropriate place to put webhook route handlers? Should this be done using middleware, or would it be more idiomatic to use standard Express routes and put them within a routes directory?
For context, I want to listen to events from Instagram, and they don't necessarily match up with the RESTful services I'm using.
A middleware is only a handler for a standard express route. I'd consider a webhook a middleware like any other non-service endpoint.
In that middleware you can retrieve services via req.app.service. For example an Instagram webhook that creates entries in the images service for the data retrieved by the webhook and then sends the status (or error back) can look like this:
app.use('/instagram', function(req, res) {
const imageService = req.app.service('images');
const images = req.body.data;
imageService.create(currentData).then(() => {
res.status(200);
res.end('ok');
}).catch(error => {
res.status(500);
res.end(error.message);
});
});
The data sent to the webhook should also be verified with Instagram before adding them to the database.

MarkLogic 7 REST API - Bad Request Error

I am building a webapp using AngularJS on top of a MarkLogic 7 XML database. I am using the REST API provided by MarkLogic to access the database. The code I'm using in my controller is as follows.
app.controller("mainController", function($scope, $http){
var addr = 'http://localhost:8011/v1/search?q=test&options=newtest';
$http({method:'GET', url: addr})
.success(function(data){
alert('Success');
console.log(data);
});
});
Now, when I open my view, a 'bad request' error is logged in the console.
OPTIONS http://localhost:8011/v1/search?q=test&options=newtest 400 (Bad Request)
angular.min.js:99
OPTIONS http://localhost:8011/v1/search?q=test&options=newtest No 'Access-Control-Allow-
Origin' header is present on the requested resource. Origin 'null' is therefore not
allowed access. angular.min.js:99
XMLHttpRequest cannot load http://localhost:8011/v1/search?q=test&options=newtest. No
'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null'
is therefore not allowed access. index.html:1
Are there any settings to be configured on the MarkLogic server to make the API accessible? Please help.
Thanks,
Krishna
Krishna, is your AngularJS code hosted by MarkLogic, or are you running it in node.js (via grunt, perhaps)? This looks like a cross-site scripting problem. Two solutions come to mind:
If you don't need a middle tier, MarkLogic can host the Angular code. Put it in the modules database of the app server on port 8011. Then the request is going to the same place the JS came from and the problem goes away.
If you want to keep a node layer, set up a proxy. Assuming you're using Grunt, you can see how I handled that in the Gruntfile.js of an app with the same stack.
Once you get past that error, you might consider moving the interaction with the MarkLogic REST API into a service. The Demo Cat application I linked to above has an early version of an MLRest AngularJS service; that might be a useful starting point.