p5.js icon indicating copy to clipboard operation
p5.js copied to clipboard

Add 'credentials: include' to fetch request in loadImage()

Open dfd0226 opened this issue 4 years ago • 10 comments

Most appropriate sub-area of p5.js?

  • [ ] Color
  • [ ] Core/Environment/Rendering
  • [ ] Data
  • [ ] Dom
  • [ ] Events
  • [x] Image
  • [ ] IO
  • [ ] Math
  • [ ] Typography
  • [ ] Utilities
  • [ ] WebGL
  • [ ] Other (specify if possible)

New feature details:

I recently found an issue with p5.js loadImage() and how the fetch() request handled cookies in Safari (macOS/iOS) and Chrome (iOS). Due to Apple-specific security features, cookies were not being attached for image requests.

I'm using Express.js middleware to manage user sessions/issue cookies and the requests from loadImage() were not aware of the session cookie, causing the request to fail. This can evidently be fixed by including credentials: include in the fetch request.

If possible, this would be a useful addition to the library for others who encounter a similar situation.

dfd0226 avatar May 01 '20 18:05 dfd0226

+1

The lack of this feature makes p5.js pretty much incompatible with Safari when using private assets. We need the cookie from the client to identify the user's session and their ability to access different assets.

Is there a workaround where we can get the assets with an http request and then use the HTMLImageElement as the image to be loaded?

Something like this would be great

const myImage = new Image(100, 200);
myImage.src = 'picture.jpg';
const p5Image = loadImage(myImage)
// or
const p5Image = image(myImage)

I imagine I can manually get the pixels of the HTMLImageElement and transfer them to a p5.Image using createImage and modifying the pixels one by one, but I'm asking in case there's a better way of doing it

dgrcode avatar Jun 02 '20 10:06 dgrcode

I've implemented the following workaround, in case someone find it useful

const getImage = async path => {
  const response = await fetch(path, {
    credentials: 'include'
  })
  const blob = await response.blob()
  const resourceUrl = URL.createObjectURL(blob)

  return window.loadImage(resourceUrl) // this is p5.js loadImage
}

This creates a local url to a blob and tells p5js to load the resource at that url. That way you can control the fetching and send the cookies that you want

dgrcode avatar Jun 02 '20 12:06 dgrcode

If credentials are sent with the request, the responding server cannot reply with a header of Access-Control-Allow-Origin: * which will cause problem with using cross origin requested images.

One thing we can possibly do is to overload the function so that for the first argument instead of just providing the path to the image, you can provide a Request object which will be passed directly to fetch. That way you can setup the fetch request however you like, including using POST requests and custom headers.

limzykenneth avatar Jun 13 '20 11:06 limzykenneth

I think overloading the function sounds like a very good plan. I like the idea of sending a Request as the argument, so developers have full control about how they request assets

dgrcode avatar Jun 13 '20 11:06 dgrcode

Is anyone currently working on this?

Ashley-Y-Lin avatar Mar 25 '23 06:03 Ashley-Y-Lin

Not yet @Ashley-Y-Lin!

davepagurek avatar Mar 25 '23 12:03 davepagurek

Ok! I'd like to try working on this, and will start with the suggestion above to overload the function.

Ashley-Y-Lin avatar Mar 26 '23 16:03 Ashley-Y-Lin

Sounds good, I'll assign this to you!

davepagurek avatar Mar 27 '23 12:03 davepagurek

@davepagurek @Ashley-Y-Lin , should I raise a PR with required changes if no one is working on this currently?

ayushanand308 avatar Jan 03 '24 16:01 ayushanand308

@ayushanand308 I think that should be ok! But @Ashley-Y-Lin feel free to let us know if you're still interested but could use some help.

davepagurek avatar Jan 07 '24 16:01 davepagurek