Giter VIP home page Giter VIP logo

Comments (12)

chriskozlowski avatar chriskozlowski commented on August 11, 2024 4

@lynndylanhurley - I will put this on our list to work on once we ship what we're working on now. About 1-2 months. Gettin' married next week so time is a little tight!

from redux-auth.

lynndylanhurley avatar lynndylanhurley commented on August 11, 2024 1

Congrats 💯

from redux-auth.

lynndylanhurley avatar lynndylanhurley commented on August 11, 2024

@chriskozlowski - can you post the code for the request?

from redux-auth.

chriskozlowski avatar chriskozlowski commented on August 11, 2024

@lynndylanhurley Sure! I can't post the project as a repo but here are some excerpts. I could create a test repo if needed but that would take a little more time to set up. In case I wasn't totally clear above, the redux-auth fetch does work client side just fine. This issue only happened to me on the server. Made me wonder if the redux-auth fetch needs something that is only in the browser environment...

The component:

class ProjectsAppRoot extends Component {

  static fetchData(store, props) {
    return store.dispatch(fetchProjects());
  }
...

The action creator:

import { fetch } from 'redux-auth';
// import fetch from 'isomorphic-fetch'; <-- This will work but doesn't send auth headers 

export function fetchProjects() {
  return (dispatch) => {
    dispatch(requestProjects());

    return fetch('http://127.0.0.1/api/v1/projects', { method: 'get' }) <-- This does not resolve
      .then(response => response.json())
      .then(json => dispatch(receiveProjects(json)));
  };
}

The SSR middleware

store.dispatch(configure(
    {
      apiUrl: 'http://127.0.0.1',
      tokenValidationPath: '/auth/validate_token',
      authProviderPaths: {
        google: '/auth/google_oauth2',
      },
    },
    {
      isServer: global.__SERVER__,
      cookies: request.headers.cookie,
      currentLocation: url,
    }
  )).then(({ redirectPath, blank } = {}) => {
    store.dispatch(match(url, (error, redirectLocation, routerState) => {
      if (redirectLocation) {
        response.redirect(redirectLocation.pathname + redirectLocation.search);
      } else if (error) {
        console.error('ROUTER ERROR:', pretty.render(error));
        response.status(500);
        hydrateOnClient();
      } else {
        const rootComponent = (
        <div>
          <Provider store={store}>
            <div>
              <AuthGlobals />
              <ReduxRouter />
            </div>
          </Provider>
        </div>
        );

        const fetchingComponents = routerState.components
        // if you use react-redux, your components will be wrapped, unwrap them
        .map(component => component.WrappedComponent ? component.WrappedComponent : component)
        // now grab the fetchData functions from all (unwrapped) components that have it
        .filter(component => component.fetchData);

        // Call the fetchData functions and collect the promises they return
        const fetchPromises = fetchingComponents.map(component => {
          let promise = component.fetchData(store, routerState) // <-- We don't make it past here bc the promise hangs
          return promise;
        });

        Promise.all(fetchPromises)
          .then(() => {           
            const status = getStatusFromRoutes(routerState.routes);
            if (status) {
              response.status(status);
            }
            response.send('<!doctype html>\n' +
              renderToString(
                <Html store={ store } component={ rootComponent } assets={ global.webpackIsomorphicTools.assets() } />
              )
            );
          });
      }
    }));
  });

from redux-auth.

lynndylanhurley avatar lynndylanhurley commented on August 11, 2024

What is the result of dispatch(receiveProjects(json))? Are you sure that it returns something resolvable? For example, should you be doing something like this instead?

    return fetch('http://127.0.0.1/api/v1/projects', { method: 'get' }) <-- This does not resolve
      .then(response => response.json())
      .then(json => Promise.resolve(dispatch(receiveProjects(json))));

from redux-auth.

chriskozlowski avatar chriskozlowski commented on August 11, 2024

Thanks for your help on this!

receiveProjects() is just a plain object action creator that signals the api call succeeded and the response data can be merged into the redux state:

export function receiveProject(payload) {
  return { type: RECEIVE_PROJECT, payload };
}

Actually, while working this out, I actually commented out those additional promise then statements so it was isolating just the fetch call and the result was the same:

return fetch('http://127.0.0.1/api/v1/projects', { method: 'get' }) <-- This does not resolve
  //.then(response => response.json())
  //.then(json => dispatch(receiveProjects(json)));

The hope was to just get the request to happen. It definitely isn't firing off as nothing even shows in the rails log. Of course the response data would not ultimately be merged into the state so I wouldn't see it in the rendered html but I was just hoping to get it to render and then add those additional promise then statements back in.

Take a look at this code from utils/session-storage.js. This file has the retrieveData function that looks like it tries to load the auth info from localStorage or a cookie depending on whats available. This function is used by the redux-auth fetch function to generate the auth headers:

// even though this code shouldn't be used server-side, node will throw
// errors if "window" is used
var root = Function("return this")() || (42, eval)("this");
... and then later ...
export function retrieveData (key) {
  var val = null;

  switch (root.authState.currentSettings.storage) {
    case "localStorage":
      val = root.localStorage && root.localStorage.getItem(key);
      break;

    default:
      val = Cookies.get(key);
      break;
  }

  // if value is a simple string, the parser will fail. in that case, simply
  // unescape the quotes and return the string.
  try {
    // return parsed json response
    return JSON.parse(val);
  } catch (err) {
    // unescape quotes
    return unescapeQuotes(val);
  }

Seems like this might not work in the server side use case?

I tried your suggestion just to be sure...no luck.

from redux-auth.

lynndylanhurley avatar lynndylanhurley commented on August 11, 2024

Actually now that I think about it, the bundled fetch was meant to be used in the client, normally in the componentDidMount phase of the component lifecycle. Is there a reason that the request needs to be made server-side in your app?

See these posts for more details:

from redux-auth.

chriskozlowski avatar chriskozlowski commented on August 11, 2024

Totally makes sense where you're coming from there. Here is the story on that:
We are building a public website and a private internal app that both use the same rails api (CORS). My goal is to get them both to authenticate with the rails api with different user classes and permissions which is why your libraries are a great fit. Both the public website and internal app are redux/react based. I have been posting about the internal app which I suppose doesn't absolutely need to SSR the page with data preloaded (although I'd prefer it). However, I will definitely need it for the public site so I render out the full content for SEO reasons.

I wonder if others would want to be able to hit an external api server side like this too? I would be willing to help improve the fetch wrapper to support this type of usage.

from redux-auth.

yury-dymov avatar yury-dymov commented on August 11, 2024

I implemented server-side fetch in my fork: https://github.com/yury-dymov/redux-oauth

Implementation details:

  1. I added new server action to update headers in redux without touching user;
  2. In fetch in getAuthHeaders and updateAuthCredentials I am checking if it server-side and updating session-storage.js instead of cookies/local storage and dispatching new action

from redux-auth.

lynndylanhurley avatar lynndylanhurley commented on August 11, 2024

@yury-dymov - do you want to merge that stuff into this repo?

from redux-auth.

yury-dymov avatar yury-dymov commented on August 11, 2024

@lynndylanhurley in my fork I dropped multiple endpoint support and it might take too much time from my side to merge my changes and test if I haven't forgot something to support correctly all your features, which I am not using.

But I will be more than happy if other folks, who want to have that functionality in their projects will provide PR based on my code.

from redux-auth.

lynndylanhurley avatar lynndylanhurley commented on August 11, 2024

I wonder if others would want to be able to hit an external api server side like this too? I would be willing to help improve the fetch wrapper to support this type of usage.

@chriskozlowski - I'll accept a PR for this if you have time.

from redux-auth.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.