I'm coming across code where there's an additional parameter for express route handlers beyond the path and the callback.
For example:
app.get('/path', authUser, (req,res) => {
...
}
where authUser is a function. Can anybody explain the role of such functions? To date I've only seen express routes with the two parameters.
These are middleware, which are functions that run before your route handler (your third function). You can have as many as these as possible. They basically modify/perform an action based on the request, or maybe manipulate the response.
So this is likely middleware that checks the request for an authenticated user, and will return a 401/403 if not authenticated, meaning that you can write your route handler under the assumption that you are authenticated.
For more info, check out this article
The family of methods such as app.get(), app.post(), app.use(), accept any number of request handlers as successive arguments:
app.get('/path', fn1, fn2, fn3, fn4);
These requests handlers can be used for a variety of purposes. Often times, they are what is generally referred to as middleware which prepares a request for further processing or in some cases blocks a request from further processing. But, they can also be normal request handlers too, they are not just limited to what most people call middleware.
In your specific case:
app.get('/path', authUser, (req,res) => {
...
}
We can guess by the name that authUser is checking to see if the user making the request has been properly authenticated and, if not, then an error status is probably sent as the response and the next request handler in the chain is not called. Or conversely, because authUser has already filtered out any unauthenticated users, the request handler here at the end of the chain can safely assume that the user is already authenticated. So, this particular use is a means of applying middleware to one specific route with no consequences for any other routes defined later.
But, I want to emphasize that this is a generic mechanism that is not limited to just what is classically described as middleware. It can also be used for request handlers that might execute conditionally based on other parameters. For example here's one such example where the first request handler looks the URL and decides to handle the whole request itself based on what it sees in the URL and, if not, passes it on to the next handler:
app.get('/book/:id', (req, res) => {
// check if id is purely numeric
if (/^\d+$/.test(req.params.id)) {
// this is a request for a book by numeric id
// look up the book numeric id in the database and return the meta
// data about this book
} else {
// not a book id, let next request handler have the request
next();
}
}, (req, res) => {
// must be a book title lookup
// look up the book in the title database and return the id
});
Related
Suppose I module export "/route1" in route1.js, how would I pass parameters into this route from "/route2" defined in route2.js?
route1.js
module.exports = (app) => {
app.post('/route1', (req,res)=>{
console.log(req.body);
});
}
route2.js
const express = require('express');
const app = express();
//import route1 from route1.js
const r1 = require('./route1')(app);
app.post('/route2', (req, res) => {
//how to pass parameters?
app.use(???, r1) ?
})
In short, route 1 output depends on the input from route 2.
You don't pass parameters from one route to another. Each route is a separate client request. http, by itself, is stateless where each request stands on its own.
If you describe what the actual real-world problem you're trying to solve is, we can help you with some of the various tools there are to use for managing state from one request to the next in http servers. But, we really need to know what the REAL world problem is to know what best to suggest.
The general tools available are:
Set a cookie as part the first response with some data in the cookie. On the next request sent from that client, the prior cookie will be sent with it so the server can see what that data is.
Create a server-side session object (using express-session, probably) and set some data in the session object. In the 2nd request, you can then access the session object to get that previously set data.
Return the data to the client in the first request and have the client send that data back in the 2nd request either in query string or form fields or custom headers. This would be the truly stateless way of doing things on the server. Any required state is kept in the client.
Which option results in the best design depends entirely upon what problem you're actually trying to solve.
FYI, you NEVER embed one route in another like you showed in your question:
app.post('/route2', (req, res) => {
//how to pass parameters?
app.use(???, r1) ?
})
What that would do is to install a new permanent copy of app.use() that's in force for all incoming requests every time your app.post() route was hit. They would accumlate forever.
I am creating form in which I must post one input before the others.
I must get the id from that post before I post the rest of the Form.
I have successfully dispatched the create action.
const createPromise = Promise.resolve(
this.props.crudCreate(
this.props.reference,
{ description: this.state.addInputValue },
this.getBasePath(),
null,
)
);
createPromise.then(res => console.log(res))
After dispatch, I can log via the promise the following:
However, I am, looking to get the response body after the post which would be my id as seen below.
I thought about adding the functions from ReferenceInputController in my component but it does not seem be a good practice.
What would be the best way to get the id from the HTTP response?
According to the documentation https://hapijs.com/api/16.0.1#route-configuration a route method may not be of the type 'HEAD' but I do not understand why I can not override the behavior.
HEAD routes are automatically created with every GET route you define. Therefore there's very little reason you'd need to define your own.
If you want to optimize your handling of HEAD requests, simply check your GET handler for the method, and if it is head, return an empty response with the correct headers. This is only worth doing for some very expensive GET requests, where you are expecting clients to use HEAD directly.
The main reason not to support it, is that I am expecting very few developers to use this, but it will add an extra lookup for every HEAD request.
This has been already been addressed on Github.
As to further elaborate on #Ankh's response, you can check the request method property to abbreviate the response on the GET handler:
const getHandler = (req, h) => {
// HTTP status 204 -> NO CONTENT
if (req.method as string === 'head') return h.response().code(204)
// continue the GET handler logic here
}
I am creating a web redux-react app which will have a number of different permission levels. Many users may be interacting with one one piece of data but some may have limitations on what they can do.
To me, the obvious way to set permissions on interactions on the data (held behind the app server) would be to associate certain permissions with different redux actions. Then, when a user saves their state the client side app would bundle up the users action history and send it back to the server. These actions could then be applied to the data in the server and permissions could be checked, action by action, against a user jwt.
This would mean lots our reducer code could be used isomorphically on the server.
I cannot find any resources/disscussions on this. What is the normal way of handling complex permissions in a redux app? Having auth purely at the endpoint seems cumbersome , this would require rewriting a ton of new code that is already written in client side reducers. Is the any reason not to go ahead and create a reducer which checks auth on each action?
Points:
We must assume actions sent to the server are authenticated, but sent by users that do not have permission dispatch these actions
If the permissions have been checked and are inside the actions then the reducer can check permissions and be pure
I think it's not the responsibility of action creators to check the permissions but using a reducer and a selector is definitively the way to go. Here is one possible implementation.
The following component requires some ACL checks:
/**
* Display a user record.
*
* A deletion link is added if the logged user has sufficient permissions to
* delete the record.
*/
function UserRecord({ username, email, avatar, isGranted, deleteUser }) {
return (
<div>
<img src={avatar} />
<b>{username}</b>
{isGranted("DELETE_USER")
? <button onClick={deleteUser}>{"Delete"}</button>
: null
}
</div>
)
}
We need to connect it to our store to properly hydrate all props:
export default connect(
(state) => ({
isGranted: (perm) => state.loggedUser.permissions.has(perm),
}),
{deleteUser},
(stateProps, dispatchProps, ownProps) => ({
...stateProps,
...ownProps,
deleteUser: () => dispatchProps.deleteUser(ownProps.user)
})
)(UserRecord)
The first argument of connect will create isGranted for the logged user. This part could be done using reselect to improve performance.
The second argument will bind the actions. Nothing fancy here.
The third argument will merge all props and will pass them to the wrapped component. deleteUser is bound to the current record.
You can now use UserRecord without dealing with ACL checks since it will auto-update depending on what is stored in loggedUser.
<UserRecord user={someUser} />
In order to get the above example work you need to store the logged user in Redux's store as loggedUser. You don't need check ACL on actions since the UI won't trigger them if current user lacks of permissions. Moreover, ACL have to be checked server-side.
You can set up an helper function that would be built into actions for checking user rights (locally or remotely) where you would also provide with a callback action creator on error. Of course redux-thunk or similar would be needed so you can dispatch actions from other actions.
The key rule you should observe here is:
Reducers are pure functions.
Action creators can be impure. That means reducers always return the same value given the same arguments. Checking for ACL rights in reducer will violate that rule.
Say let's say you need to fetch the list of contacts. Your action is REQUEST_CONTACTS. The action creator would first dispatch something like:
// ACL test function
function canAccessContacts(dispatch) {
if (user !== 'cool') {
dispatch({type: 'ACCESS_DENIED'});
return false;
}
}
// Action creator
function fetchContacts() {
return (dispatch) => {
if (!canAccessContacts(dispatch)) {
return false;
}
// your logic for retrieving contacts goes here
dispatch({
type: 'RECEIVE_CONTACTS',
data: your_contacts_data_here
});
};
}
RECEIVE_CONTACTS will be fired once you have data back. Time between REQUEST_CONTACTS and RECEIVE_CONTACTS (which is likely an async call) is ian opportunity to show your loading indicator.
Of course, this is a very raw example, but it should get you going.
I'm making a restfull API with Laravel 4 for an external website doing web scraping.
The target site has a login form so each request requires authentication.
If the user want to post or view something, he make a request to my server, that make another request to the target server, get the info, and encodes it in JSON.
My problem is how I get the credentials in my API request?
Now I have something like http://myapi.local/login (this make a request to http://externalsite.com/admin/login),
POST params are username=test&password=1234 and that returns a session ID
Then for every action, I append the session ID to my api requests
http://myapi.local/posts/all?session_id=4D2FtE...
But this is not restfull at all, so the best is to do it with HTTP Basic Auth, that is doing one login for each request
url: http://myapi.local/posts/all
header: Authorization: Basic dGVzdDoxMjM0
and call the login function in my controller.
It's slower because it makes two request to the target site each time, but seems better because I don't save any session or credentials.
How I handle the Authorization header in Laravel? decode base64 and then split credentials?
Is there a better way to do this?
Thank you!
Laravel handles basic auth himself, the only thing to do is think where you can use the filter (Laravel handles the basic auth with filters), so:
a) In a route:
Route::get('posts/all', array('before' => 'auth.basic', function()
{
// Only authenticated users may enter...
}));
b) Constructor in the controller (i prefer this):
function __construct() {
$this->beforeFilter('auth.basic');
}
Also make this adjust if apply for your case, as laravel docs say:
By default, the basic filter will use the email column on the user
record when authenticating. If you wish to use another column you may
pass the column name as the first parameter to the basic method in
your app/filters.php file:
Route::filter('auth.basic', function()
{
return Auth::basic('username');
});
Basic Auth Docs
EDITED
In your case then maybe you want implement a custom filter with this two methods as basis.
/**
* Get the credential array for a HTTP Basic request.
*/
function getBasicCredentials(Request $request, $field)
{
return array($field => $request->getUser(), 'password' => $request->getPassword());
}
/**
* Get the response for basic authentication.
*
* #return \Symfony\Component\HttpFoundation\Response
*/
function getBasicResponse()
{
$headers = array('WWW-Authenticate' => 'Basic');
return new Response('Invalid credentials.', 401, $headers);
}
See the default implementation here: