Fork me on GitHub

Hi, I have a re-frame project on top of a Django Rest Framework back-end. Token Auth. This is how I am working on it, upon log-in, the token received from Django is stored in the app-db (in case of remember-me, in the Local Storage). On each subsequent Ajax request, that token is attached to the header, anytime that token is nil (upon Logout, or expiration of that token), then the app-db is reset to initial value and login page is redirected with a message. Is this a right way of handling the flow?


What happens if someone changes the secret on the django server and you get an unexpected 403


Id prefer to use the cookie approach, that way the token is applied implicitly to http requests, and lower level concerns of auth aren't part of your app model. It is fine to store say { :active-user { :username :first-name :id } though . also if you use httpOnly then you reduce the attack vector of XSS and they can't steal the token


Well if you get a 403 on any request, your state is automatically reset and you're taken back to the Login Page with the error message. Thanks for the tips and the link, a friend of mine was suggesting that approach.

Pablo Fernandez20:10:06

If I use controlled components, the cursor behaves weirdly, as in, it jumps to the end of the line when I modify something in the middle. If I use uncontrolled component, it won't automatically reflect the status of the state, so, when the form is submitted and I clear the state, the inputs still show what the user entered. Is there a way around this? is there a middle ground?


@pupeno re:, why not get your application to update a key in app-db when it’s ready for rendering?


this would speed up running your prerenderer too, because it wouldn’t have to wait for no movement before rendering

Pablo Fernandez20:10:59

danielcompton: that optimization is planned, but it’s a nice to have, not the main way of working and even then, I’m not sure how workable it is.


wouldn’t that be a much more reliable way of working? You know exactly when you’re done, you don’t need to rely on timing heuristics which may be delayed depending on network blips, e.t.c.?

Pablo Fernandez20:10:16

There’s two reasons. 1) Prerenderer should be transparent. I’m designing it so that you can throw it on top of any project and it’ll just work (adding the prerendering code of course). and 2) in many cases there’s no clear “this is now done” point.

Pablo Fernandez20:10:52

danielcompton: for example, this page: issues a get-tools event, that eventually issues a got-tools event. this page: also issues a get-tools that issues a got-tools but it needs to keep on running to do more things before it’s done. So got-tools is the last event for one page but not for another. Depending on having to send a message when done rendering would require a lot of refactoring in this app and my bet is that it’s the same in most apps.

Pablo Fernandez20:10:26

Even then, the re-factored code won’t look very nice. It ends up being convoluted.


@pupeno in our app we have something like:

(defn ^:export mount-app
  (dispatch-sync [:bootstrap])


we’d just add a final (dispatch [:prerender-ready? true])

Pablo Fernandez20:10:55

Where would you add that?


After mount gui

Pablo Fernandez20:10:35

So, when the bootstrap handler finishes running, your app is completely rendered?


In our case I think it is


but I can see it wouldn’t always be the case

Pablo Fernandez20:10:55

In my case it isn’t by a long margin.

Pablo Fernandez20:10:44

We go: init-db -> get-current-user -> got-current-user -> get-tools -> got-tools (in an unpredictable order of course)


you could set something up to wait for all of your data to come back, then update the key

Pablo Fernandez20:10:11

What do you mean by wait for all my data?

Pablo Fernandez20:10:26

I know I could re-factor my app to have handlers that clearly are the last handler on each page, but that code doesn’t look nice.

Pablo Fernandez20:10:57

The important thing is that I don’t want to require people building apps in a special way to be able to use prerenderer.


Another option would be to put middleware on all of the handlers you want to instrument?

Pablo Fernandez20:10:45

That would be all the handlers and it should be automatic. Which is why I like the idea of having a callback that gets call for all events.


I understand what you’re saying, I’m just not sure that people are going to be able to lift a browser app and run it against the server with no other changes

Pablo Fernandez20:10:11

Well, I’m ambitious.


if people have to wait x00ms of stillness before returning HTML, won’t that be about the same speed as rendering on the client?

Pablo Fernandez20:10:37

I think some of those optimizations will be in place and will be common, but shouldn’t be necessary. If I forgot to add the we-are-done signal on a page, that page should still work, just slower.

Pablo Fernandez20:10:58

For me this isn’t about speed, it’s about non-JS agents, like the crawlers at Google, Bing, Facebook, Twitter, LinkedIn, etc.

Pablo Fernandez20:10:59

It can also help with speed. When I was working in Gmail we implemented a pre-renderer because the app got so slow at one point. It was very simple because it wouldn’t just pre-render any page, it would just pre-render the email that you were accessing in a very crude way while the app was loading.

Pablo Fernandez20:10:29

I can see hand-tuned or hand-coded pre-rendering functions in the future, but the last fallback would be something similar to what I have right now.


Hmm, I’ll have to think about this more and talk with Mike. Global middleware raises the issue of when it is executed

Pablo Fernandez20:10:36

I can appreciate that none of these solutions are simple.


what you can do today, is create your own middleware to add to every handler. we have that on our internal apps


so we just add [global-middleware]

Pablo Fernandez20:10:19

And I’m happy to work and help to find a good one. I think I won’t be the last person wanting some kind of global middleware or callback or tap.