felixhageloh / uebersicht

ˈyːbɐˌzɪçt
GNU General Public License v3.0
4.59k stars 165 forks source link

Not loading JSON data from URL... #438

Open TechJedi51 opened 3 years ago

TechJedi51 commented 3 years ago

The URL when accessed in FireFox does return a JSON response. I used it for the initialState. But when the widget is refreshed, no data is returned and there is no error in the Console. If I add the Proxy 'http://127.0.0.1:41417/' to the fetch, I get back a error when evaluating 'data.sessions.length'. Is there a way to force data to be logged to the Console? I tried both console.log(data) and console.error(data).

Code Segment:

export const command = dispatch => {
  fetch(options.protocol + "://" + options.plexpyHost + "/api/v2")
    .then(res => {
      res.json().then(data => {
        dispatch({ type: "FETCH_SUCCEDED", data: data });
      });
    })
    .catch(error => {
      dispatch({ type: "FETCH_FAILED", error: error });
    });
};

export const updateState = (event, previousState) => {
  if (event.data && !('error' in event.data)) {
    return {
      results: event.data
    }
  } else {
    return initialState;
  }
};

export const render = state => {
    if (!state || !state.results) {
        state = initialState;
    }
    const plexData = computePlexNowPlaying(state.results.response.data);
    console.error(plexData);
TheOptimist commented 3 years ago

I'm having a similar problem, with my code below. Essentially, the fetch is made and is successful - I can see the response in the Network tab, but the response object in the command is not populated with the data.

export const command = (dispatch) => {
  console.log("fetching data from " + apiUrl);
  fetch(apiUrl, options)
    .then(response => {
      console.log("fetch succeeded");
      console.log(response);
      dispatch({ type: 'FETCH_SUCCEEDED', data: response });
    })
    .catch((error) => {
      console.log("fetch failed");
      console.log(error);
      dispatch({ type: 'FETCH_FAILED', error: error });
    });
};

export const updateState = (event, previousState) => {
  console.log("updating state...");
  if (event.error) {
    console.log(event.error.message);
    return { ...previousState, error: event.error.message };
  }
  console.log(event.data);
  return  { output: event.data };
};

export const render = ({output, error}) => {
  console.log("rendering...");
  if (error) {
    console.log(error);
    return <div>cannot see the moon</div>
  } else {
    console.log(output);
    return <div>{String(output)}</div>
  };
};

export const initialState = { output: 'gazing at the moon' };

The response object that's logged to the console looks like this:

[Log] Response (moonphase-index-jsx, line 36)
  body: null
  bodyUsed: false
  headers: Headers {append: function, delete: function, get: function, has: function, set: function, …}
  ok: false
  redirected: false
  status: 0
  statusText: ""
  type: "opaque"
  url: ""

I can see the actual fetch in the Network to "api", and the correct data is returned by this call. It seems it never makes it into the widget code though. I am only beginning with Übersicht, and am even more beginner at React/JSX so forgive the blooper if it's obvious from my code what I've done wrong. I've even commented out my updateState after reading (lots) the README on widget development to see if a default {output, error} works, but I get an undefined. Although I think any problem is happening before updateState because I cannot see the response data in the fetch promises.

TheOptimist commented 3 years ago

Rats. I might delete my comment above - it seems my issue is related to CORS. Back to school for me to understand how I can either workaround this, or find a different API to pull data from.

rjksn commented 3 years ago

These are both CORS issues.

A "simple" solution is to just use the shell command capability. This will return the raw json from the server.

export const command =curl -sS "https://example.com/json";

rjksn commented 3 years ago

For the future: This package allows for sending remote requests through a proxy. It's in the docs here: built-in-proxy-server.

The short of it is, prepend "http://127.0.0.1:41417/" to your remote url.

export const command = (dispatch) =>
  fetch('http://127.0.0.1:41417/https://example.com/data')
    .then((response) => {
       // ...
    });
TechJedi51 commented 3 years ago

It is still giving the same error: [Error] Failed to load resource: the server responded with a status of 400 (Header required) (v2, line 0) http://127.0.0.1:41417/http://192.168.1.10:8181/api/v2

If I load that page in a browser it says: Missing required request header. Must specify one of: origin If I go to the URL without the Proxy start, in a browser, it shows the expected JSON response.

fetch(PROXY + options.protocol + "://" + options.tautulliHost + "/api/v2", { mode: 'no-cors' }) .then((response) => { dispatch({ type: 'FETCH_SUCCEDED', plexData: response.json() }); }) .catch((error) => { dispatch({ type: 'FETCH_FAILED', error: error }); });