react-native: ImageSource in Image doesn't send headers

Description

According to the docs, the ImageSource prop in the Image component should allow for sending headers like this:

<Image
    source={{uri: "http://myimage.com", headers: {"Authorization":token}}}
/>

However, the headers aren’t sent in any request.

Version

0.64.3

Output of npx react-native info

System: OS: Windows 10 10.0.19042 CPU: (8) x64 Intel® Core™ i7-8550U CPU @ 1.80GHz Memory: 2.02 GB / 15.85 GB Binaries: Node: 16.13.2 - C:\Program Files\nodejs\node.EXE Yarn: Not Found npm: 8.1.2 - C:\Program Files\nodejs\npm.CMD Watchman: Not Found SDKs: Android SDK: API Levels: 27, 28, 29 Build Tools: 27.0.3, 28.0.3, 29.0.2 System Images: android-24 | Google Play Intel x86 Atom, android-27 | Google APIs Intel x86 Atom, android-28 | China version of Wear OS Intel x86 Atom, android-28 | Google APIs Intel x86 Atom, android-29 | Google Play Intel x86 Atom Android NDK: Not Found Windows SDK: Not Found IDEs: Android Studio: Version 3.5.0.0 AI-191.8026.42.35.6010548 Visual Studio: Not Found Languages: Java: 11.0.11 - C:\Program Files\AdoptOpenJDK\jdk-11.0.11.9-hotspot\bin\javac.EXE npmPackages: @react-native-community/cli: Not Found react: 17.0.1 => 17.0.1 react-native: 0.64.3 => 0.64.3 react-native-windows: Not Found npmGlobalPackages: react-native: Not Found

Steps to reproduce

  1. Create a project (I’ve been using Expo but don’t see how that would be an issue)
  2. Import image from ‘react-native’
  3. Try sending any header e.g.: <Image source={{ uri: "url to any image", headers: { "Content-Type": "image/jpeg", "X-Authorization": "thisismyauthtoken" } }} />
  4. Inspect the HTTP request, no headers are sent (I’m running in browser and using Chrome dev tools to inspect HTTP)

Snack, code example, screenshot, or link to a repository

image image image

About this issue

  • Original URL
  • State: open
  • Created 2 years ago
  • Reactions: 3
  • Comments: 19 (1 by maintainers)

Most upvoted comments

Also from a security aspect this is important because some websites allow to sent the authentication in the url as „?bearer=…“. When doing this and saving the image the token gets saved too as file name.

the adding of headers is therefore essential

I am experiencing the exact same problem.

Please fix this

Any solution here guys? I’m facing the same problem. The header in Image acting really weird on Android, but on IOS everything is still smooth

After a fix for this too. Our UAT env’s are closed behind headers, so we can’t get images working properly in some cases.

Same here on Android. It worked for me in version 0.68.2, but after upgrading to 0.73.4 all the images disappeared! I quickly need to update the app in the stores, because of new regulations… help! 😦

Update: If you are using Expo, there is a package called “expo-image”, that works with headers. For non Expo users, you could try “react-native-fast-image”.

Happens to me on ios if newArch is on, haven’t check Android. And it’s clearly not implemented: https://github.com/facebook/react-native/blob/main/packages/react-native/ReactCommon/react/renderer/imagemanager/platform/ios/react/renderer/imagemanager/RCTImagePrimitivesConversions.h#L110 That todo’s been there for 6 years now. Works if disable newArch.

I can confirm the headers are still not sent. Here’s how I solved this in my app (I used Avatar component from the UI Kitten library but it’s actually a small wrapper for the native Image so it’s the same situation).

import { useState, useCallback, useEffect } from 'react';
import { ImageSourcePropType } from 'react-native/Libraries/Image/Image';
import { Avatar } from '@ui-kitten/components';
import { EvaSize } from '@ui-kitten/components/devsupport';

import { authorizationHeaders } from '../services/apiSvc';

type TPhotoProps = {
  src: string;
  size?: EvaSize;
};

export default function Photo({ src, size }: TPhotoProps) {
  const [source, setSource] = useState<ImageSourcePropType | undefined>(undefined);

  const load = useCallback(async () => {
    try {
      const response = await fetch(src, { headers: authorizationHeaders });
      const blob = await response.blob();
      const reader = new FileReader();
      reader.readAsDataURL(blob);
      reader.onloadend = () => setSource({ uri: reader.result as string });
    } catch (err) {
      // file loading failed
      setSource(require('../../assets/images/fallback-avatar.png'));
    }
  }, [src]);

  useEffect(() => {
    load();
  }, [load]);

  return (
    <Avatar source={source} size={size} />
  );
}