1

I'm trying to fetch data from http://www.recipepuppy.com/api/?q=onion&p=1. (Sample query)

It works in a browser, but I was trying to fetch it inside my React app and I'm encountering “No 'Access-Control-Allow-Origin' header is present on the requested resource error.

So I changed my strategy and now I'm trying to use JSONP (https://github.com/mzabriskie/axios/blob/master/COOKBOOK.md#jsonp).

But I can't make it work. I'm getting this error all the time. Can someone please help me with my issue?

Error:

Uncaught ReferenceError: jp0 is not defined at ?q=onion&p=1&callback=__jp0:1

My Code:

import jsonp from 'jsonp'

export const FETCH_RECIPES = 'FETCH_RECIPE'
export const SHOW_INFO = 'SHOW_INFO'

export function fetchRecipes (searchTermToDOoooooooooo) {
  const request = jsonp('http://www.recipepuppy.com/api/?q=onion&p=1', null, function (err, data) {
    if (err) {
      console.error(err.message)
    } else {
      console.log(data)
    }
  })

  return (dispatch) => {
    /*
    request.then(({ data: data1 }) => {
      dispatch({ type: FETCH_RECIPES, payload: data1 })
    })
    */
  }

}

export function showInfo (info) {
  return {
    type: SHOW_INFO,
    payload: info
  }
}

How that error looks in dev tools:

enter image description here

John Taylor
  • 729
  • 3
  • 11
  • 22
  • 3
    JSONP only works if the target site understands that. If it just returns with JSON, then JSONP will fail. You'll have to write your own server-side proxy. You can't "hack around" the same-origin policy. *edit* wait; that site does look like it responds with JSONP. It looks like something's not correctly setting up the global callback. – Pointy Aug 04 '17 at 13:50
  • Do you have experience using that Axios stuff? I think that's probably where the problem is. It should be creating that global function "jp0" for you, but apparently it isn't. – Pointy Aug 04 '17 at 13:56
  • @Pointy I don't understand why it isn't. So I should use axios combined with JSONP, right? – John Taylor Aug 04 '17 at 14:07
  • 1
    Well JSONP is extremely simple to do: you add `&callback=name` to the end of the URL query and then ensure there's a global function called "name" (can be any name of course). Then you create a new script tag with the "src" set to that URL, and you add the tag to your page. That's it: when the response comes back, your function will be called. I don't know anything about configuring that library, so I don't know why it's not working for you. – Pointy Aug 04 '17 at 14:31

1 Answers1

2

You can't do it with client-only code, at least not with JSONP+Axios (Axios doesn't (natively) support JSONP; the "jsonp" library is different from Axios), because it's the server you're getting information from that's in violation of the cross-origin rules. In this case, it's Recipe Puppy that isn't set up for Access-Control-Allow-Origin headers.

One option is to use a server-side proxy, as @Pointy mentions.

Your flow would then shift to:

  1. Client calls server-side proxy for information.
  2. Proxy calls Recipe Puppy's API and translates or passes through information as needed.
  3. Proxy relays that information to the client-side code for further processing.

As for your current shift to jsonp, it appears the jsonp library is not exporting jp0 properly for some reason. This could be an error with your build tool. You'll want to double-check your setup and make sure your build tool is picking up the jsonp library and actually putting it into the compiled source.

Shauna
  • 9,495
  • 2
  • 37
  • 54
  • 2
    In this case, as I mentioned in my (updated) comment, that server *does* understand JSONP. I think the problem is in that library the OP is trying to use. – Pointy Aug 04 '17 at 13:56
  • You don't need `Access-Control-Allow-Origin` for JSONP request – SouXin Aug 04 '17 at 14:09
  • 1
    @Pointy you're right. I've updated my response to take that into account. – Shauna Aug 04 '17 at 14:12
  • @Shauna, ok, so I need to build this proxy on my own? Something like that?: https://stackoverflow.com/questions/2558977/ajax-cross-domain-call or like this in node.js: https://stackoverflow.com/questions/34685030/server-side-proxy-using-node-js – John Taylor Aug 04 '17 at 14:21
  • That's one way to do it, yes. It's just a simple thing on your server that acts as an intermediary. – Shauna Aug 04 '17 at 15:37