Code Monkey home page Code Monkey logo

fetch's People

Contributors

bryanrsmith avatar chromakode avatar danez avatar dgraham avatar itsmattking avatar jamesplease avatar joaovieira avatar josh avatar kirill-konshin avatar kruppel avatar kwgithubusername avatar lrowe avatar matthew-andrews avatar mikemcquaid avatar mislav avatar mruhlin avatar nikhilm avatar othree avatar pcowgill avatar remcohaszing avatar roneythomas avatar samsch avatar satya164 avatar scarlac avatar steveluscher avatar tamird avatar tschaub avatar vagishvela avatar wheresrhys avatar xymostech avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

fetch's Issues

read() returns `number` instead of `Uint8Array`

I am trying to read() a text/event-stream. The backend already works in curl and in a Next.js app.

value returned from reader.read() is a number instead of a Uint8Array, which means the Typescript types are broken.

const fetchMessage = async() => await fetch("http://192.168.1.27:3000/api/chat", {
    "credentials": "include",
    "headers": {
        "User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:120.0) Gecko/20100101 Firefox/120.0",
        "Accept": "*/*",
        "Accept-Language": "en-US,en;q=0.5",
        "Content-Type": "text/plain;charset=UTF-8",
        "Sec-Fetch-Dest": "empty",
        "Sec-Fetch-Mode": "cors",
        "Sec-Fetch-Site": "same-origin",
        "Pragma": "no-cache",
        "Cache-Control": "no-cache"
    },
    "body": "{}",
    "method": "POST",
    "mode": "cors"
});

  useEffect(() => {

    function createChunkDecoder() {
      const decoder = new TextDecoder();
        return function(chunk: Uint8Array) {
          console.log(typeof chunk)
          if (!chunk)
            return "";
          return decoder.decode(chunk, { stream: true });
        };
    }

    fetchMessage()
      .then(response => response.body)
      .then(async (stream) => {
        if(!stream){
          return
        }
        const reader = stream.getReader();      
        const decode = createChunkDecoder();

        let streamedResponse = ''

        while(true) {

          const { done, value } = await reader.read();
          if (done) {
            break;
          }

          streamedResponse += decode(value);
          console.log(streamedResponse)

        }
      })
    },[])
   

Invalid responseType: blob

After installing this library and using react-native-polyfill-globals to polyfill, I'm unable to successfully fetch any data because every request results in Invalid responseType: blob. I encountered this both on an existing project (which uses react-native v0.72.7) and on a completely new/clean app that I spun up to test (again using react-native v0.72.7).

If I add the following to the root index.js file, it works but I'm not sure why this fixes it (this is some code recommended to get network logs working in the now deprecated React Native Debugger) or what the implications would be:

global.XMLHttpRequest = global.originalXMLHttpRequest || global.XMLHttpRequest;

"Cannot read property 'blobId' of undefined" from HTTP 204 No Content response

When performing a "DEL" request to a server which responds with an HTTP "204 No Content" response, I get the following error:

Cannot read property 'blobId' of undefined

This is a JSON dump of the symbolicated stack:

[
  {
    file: 'my-project-root/node_modules/react-native/Libraries/Blob/BlobManager.js',
    methodName: 'createFromOptions',
    arguments: [],
    lineNumber: 113,
    column: 34,
    collapse: false
  },
  {
    file: 'my-project-root/node_modules/react-native-fetch-api/src/BlobResponse.js',
    methodName: 'constructor',
    arguments: [],
    lineNumber: 6,
    column: 51,
    collapse: false
  },
  {
    file: 'my-project-root/node_modules/react-native-fetch-api/src/Fetch.js',
    methodName: '__didCompleteNetworkResponse',
    arguments: [],
    lineNumber: 243,
    column: 47,
    collapse: false
  },
  {
    file: null,
    methodName: 'next',
    arguments: [Array],
    lineNumber: null,
    column: null,
    collapse: false
  },
  {
    file: 'my-project-root/node_modules/@babel/runtime/helpers/asyncToGenerator.js',
    methodName: 'asyncGeneratorStep',
    arguments: [],
    lineNumber: 3,
    column: 24,
    collapse: false
  },
  {
    file: 'my-project-root/node_modules/@babel/runtime/helpers/asyncToGenerator.js',
    methodName: '_next',
    arguments: [],
    lineNumber: 22,
    column: 27,
    collapse: false
  },
  {
    file: 'my-project-root/node_modules/@babel/runtime/helpers/asyncToGenerator.js',
    methodName: 'Promise$argument_0',
    arguments: [],
    lineNumber: 27,
    column: 12,
    collapse: false
  },
  {
    file: '/root/react-native/ReactAndroid/hermes-engine/.cxx/Release/5e6w3h5p/arm64-v8a/lib/InternalBytecode/InternalBytecode.js',
    methodName: 'tryCallTwo',
    arguments: [],
    lineNumber: 61,
    column: 9,
    collapse: false
  },
  {
    file: '/root/react-native/ReactAndroid/hermes-engine/.cxx/Release/5e6w3h5p/arm64-v8a/lib/InternalBytecode/InternalBytecode.js',
    methodName: 'doResolve',
    arguments: [],
    lineNumber: 216,
    column: 25,
    collapse: false
  },
  {
    file: '/root/react-native/ReactAndroid/hermes-engine/.cxx/Release/5e6w3h5p/arm64-v8a/lib/InternalBytecode/InternalBytecode.js',
    methodName: 'Promise',
    arguments: [],
    lineNumber: 82,
    column: 14,
    collapse: false
  },
  {
    file: 'my-project-root/node_modules/@babel/runtime/helpers/asyncToGenerator.js',
    methodName: 'Promise$argument_0',
    arguments: [],
    lineNumber: 19,
    column: 23,
    collapse: false
  },
  {
    file: null,
    methodName: 'apply',
    arguments: [Array],
    lineNumber: null,
    column: null,
    collapse: false
  },
  {
    file: 'my-project-root/node_modules/react-native-fetch-api/src/Fetch.js',
    methodName: 'Fetch',
    arguments: [],
    lineNumber: 254,
    column: 5,
    collapse: false
  },
  {
    file: null,
    methodName: 'apply',
    arguments: [Array],
    lineNumber: null,
    column: null,
    collapse: false
  },
  {
    file: 'my-project-root/node_modules/react-native-fetch-api/src/Fetch.js',
    methodName: 'Networking.addListener$argument_1',
    arguments: [],
    lineNumber: 88,
    column: 16,
    collapse: false
  },
  {
    file: null,
    methodName: 'apply',
    arguments: [Array],
    lineNumber: null,
    column: null,
    collapse: false
  },
  {
    file: 'my-project-root/node_modules/react-native/Libraries/vendor/emitter/EventEmitter.js',
    methodName: 'emit',
    arguments: [],
    lineNumber: 105,
    column: 36,
    collapse: true
  },
  {
    file: null,
    methodName: 'apply',
    arguments: [Array],
    lineNumber: null,
    column: null,
    collapse: false
  },
  {
    file: 'my-project-root/node_modules/react-native/Libraries/BatchedBridge/MessageQueue.js',
    methodName: '__callFunction',
    arguments: [],
    lineNumber: 427,
    column: 32,
    collapse: true
  },
  {
    file: 'my-project-root/node_modules/react-native/Libraries/BatchedBridge/MessageQueue.js',
    methodName: '__guard$argument_0',
    arguments: [],
    lineNumber: 113,
    column: 26,
    collapse: true
  },
  {
    file: 'my-project-root/node_modules/react-native/Libraries/BatchedBridge/MessageQueue.js',
    methodName: '__guard',
    arguments: [],
    lineNumber: 368,
    column: 10,
    collapse: true
  },
  {
    file: 'my-project-root/node_modules/react-native/Libraries/BatchedBridge/MessageQueue.js',
    methodName: '__guard$argument_0',
    arguments: [],
    lineNumber: 112,
    column: 17,
    collapse: true
  }
]

Debugging

I removed the comments from some methods in Fetch.js to reveal this:

LOG  fetch __didCreateRequest {"requestId": 10}
LOG  fetch __didReceiveNetworkResponse {"headers": {"Content-Encoding": "gzip", "Date": "Wed, 26 Apr 2023 21:54:56 GMT", "Strict-Transport-Security": "max-age=31536000; includeSubdomains;", "Vary": "Origin", "X-Appservices-Request-Id": "64499db00f4b7d44b52b7ad5", "X-Frame-Options": "DENY"}, "requestId": 10, "status": 204, "url": "http://10.0.2.2:9090/api/admin/v3.0/groups/643fd5800f4b7d44b53802af/apps/64499dae0f4b7d44b52b79d2"}
LOG  fetch __didCompleteNetworkResponse {"didTimeOut": undefined, "errorMessage": null, "requestId": 10}

This shows that contrary to other responses the __didReceiveNetworkData method is never called, which is why this._nativeResponse remains undefined, hence the error.

Workaround

I found that I can work around the issue by passing the extra reactNative: { textStreaming: true } options to the fetch function:

await fetch(url, {
  method: "DELETE",
  reactNative: { textStreaming: true },
});

Slow iterations

Hello, I have issue with fetch, it's working extremally slow ~10 seconds for fetch and stream creation :(

I use React Native + Android Studio (virtual device)

UPD: on the real phone it is works fine

Technical planning and discussion

@cpojer I'm reaching out to follow up on a previous discussion about coming up with a custom Fetch API implementation for React Native at https://github.com/react-native-community/fetch with support for streaming (facebook/react-native#27741). We, MOXY and Protocol Labs, are planning to start this effort shortly and we'd like to know your thoughts on the matter.

In short, what we currently have in mind is as follows:

  • Rewrite whatwg-fetch in modern JS.
  • Remove XHR out of the equation and implement fetch directly on top of RN's JavaScript Network API exactly for the same reasons outlined at react-native-community/discussions-and-proposals#99.
  • Assume ReadableStream is available in RN's environment which can be polyfilled with web-streams-polyfill. If ReadableStream is expected to only be used in the context of Fetch, we can probably bundle them together.
  • Have tests in place running in an actual RN app on GitHub's CI.

Even if Facebook has no plans to add support for streaming to Fetch for the time being, app developers can easily swap out whatwg-fetch for @react-native-community/fetch manually. Even better would be React Native to do this automatically via some sort of extension or plugin API.

Are there any guidelines which React Native Community packages should conform to? e.g. linter and linting config, CI process config, etc.

CC @satazor @hugomrdias

StreamBlobResponse should not return a promise

I'm working on integrating this polyfill to enable text streaming in my app and have encountered a problem that goes like this:

fetch('...').then(response => {
    console.log(response.headers); // map object
    const clone = response.clone();
    console.log(clone.headers); // undefined, and headers isn't optional
    clone.then(cloneResponse => {
        console.log(cloneResponse.headers); // map object
    })
})

It seems like StreamBlobResponse constructor should not return a promise https://github.com/react-native-community/fetch/blob/master/src/StreamBlobResponse.js#L11-L22

I experimented with removing the returns and that does seem to fix it. The implementation treats the respective class properties as optional so everything continues to work. Was this an oversight or is there a deeper reason that it's implemented like this which breaks the Response object?

[Android] Streaming broken in development builds on Expo SDK50 due to ReactNativeFlipper

As previously pointed out in #13 (comment) , ReactNativeFlipper breaks streaming completely.

With Expo SDK50, the nature of these files have changed:

React Native 0.73 changed from Java to Kotlin for Android Main* classes: MainApplication.java/MainActivity.java are now MainApplication.kt/MainActivity.kt. If you depend on any config plugins that use dangerous modifications to change these files, they may need to be updated for SDK 50 support.

In android/app/src/main/java/com/[name]/[app]/MainApplication.kt, here is the ReactNativeFlipper initialization:

if (BuildConfig.DEBUG) {
    ReactNativeFlipper.initializeFlipper(this, reactNativeHost.reactInstanceManager)
}

Simply comment it out and streaming will work once more.

if (BuildConfig.DEBUG) {
    // hacky fix for: https://github.com/react-native-community/fetch
    // ReactNativeFlipper.initializeFlipper(this, reactNativeHost.reactInstanceManager)
}

Though the issue is fixed on my end, I am leaving this here for the few people who come across this problem.

Get rid of the dependency on TextEncoder and TextDecoder

It should be possible to rewrite the code to not rely on both TextEncoder and TextDecoder, just like GitHub as done:

By removing the dependency on both APIs, the app's bundle size can be further reduced. Considering that React Native's environment does not provide these APIs, there would be no need to polyfill them anymore. However, we should, by default, check whether TextEncoder and TextDecoder are available and only then fallback.

Cannot getReader of ReadableStream

Hey,

I cannot get the reader from the readableStream I get following Error:
Error: [TypeError: This stream has already been locked for exclusive reading by another reader]

I also have added the auto import for the polyfills to the root _layout.tsx as I use filebased routing.
import 'react-native-polyfill-globals/auto';

const res = await fetch("https://www.lotti.ai/api/lotti", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          Connection: "keep-alive",
        },
        mode: "cors",
        body: JSON.stringify(message),
        "reactNative": { textStreaming: true }
      })

      const reader = res.body?.getReader();
image

I should also mention that the type for reactNative: {textStreaming: true} seems to not be detected correctly:
image

response.clone() still throwing this stream has already been locked

Hello Team,

Looks like response.clone() does not work as expected when trying to re-read the response.

const myRequest = new Request('https://restcountries.com/v3.1/region/europe');

fetch(myRequest)
  .then((response) => {
    const response2 = response.clone();

    response.json().then((myRes) => {
      console.log('Response', myRes);
    });

    response2
      .json()
      .then((myRes) => {
        console.log('Response2 --->', myRes);
      })
      .catch((e) => {
        console.log('@@@@@@');
        console.log(e);
        console.log('@@@@@@');
      });
  });
@@@@@@
[TypeError: This stream has already been locked for exclusive reading by another reader]
@@@@@@```

Text streaming not working on Android

First of all, thank you so much for providing this repo ❤️ . We use streams for our subscribe requests and I was able to integrate with your project in order to get streaming working on iOS. However, I'm still running into an issue where Android is behaving as it did before the web stream polyfill. I can see the subscribe request come through, but it just hangs and no data ever comes through.

I have a working demo here where the stream is fully functional on iOS but not on Android: xmtp/example-chat-react-native#8.

To reproduce, you can run the app & press Generate address. Then press Send gm. That should trigger a message to come through the stream. If you have a chance to take a look, I'm so curious what could be causing Android specifically to have trouble here.

JS env: Hermes
RN version: 0.71
All polyfills should be included as well in .polyfills.js

Regular requests fail on android build. Works in Development

Im using this package & populating polyfills like this:
import 'react-native-polyfill-globals/auto';

my fetch requests (both streaming & non-streaming) work in iOS. It does not work in Android, but I know that is a known problem for development builds.

Im testing it in a production build, and android fails for regular non-streaming HTTP requests. The request is received by my backend which returns a 200. But there is no response or error produced by my app.

 "dependencies": {
    "@joaosousa/react-native-progress-steps": "^0.4.0",
    "@react-native-async-storage/async-storage": "1.18.2",
    "@react-native-community/slider": "4.4.2",
    "@react-native-google-signin/google-signin": "^10.1.1",
    "@react-navigation/bottom-tabs": "^6.5.11",
    "@react-navigation/native": "^6.1.9",
    "@react-navigation/native-stack": "^6.9.17",
    "@react-navigation/stack": "^6.3.20",
    "expo": "~49.0.15",
    "expo-constants": "^14.4.2",
    "expo-dev-client": "~2.4.12",
    "expo-splash-screen": "~0.20.5",
    "expo-status-bar": "~1.6.0",
    "react": "18.2.0",
    "react-native": "0.72.6",
    "react-native-fetch-api": "^3.0.0",
    "react-native-gesture-handler": "~2.12.0",
    "react-native-markdown-display": "^7.0.1",
    "react-native-paper": "^5.11.3",
    "react-native-purchases": "^7.4.0",
    "react-native-safe-area-context": "^4.6.3",
    "react-native-screens": "~3.22.0",
    "react-native-vector-icons": "^10.0.2",
    "react-redux": "^9.0.2",
    "redux": "^5.0.0"
  },
  "devDependencies": {
    "@babel/core": "^7.20.0",
    "@types/react": "~18.2.14",
    "@types/react-native-vector-icons": "^6.4.18",
    "react-native-polyfill-globals": "^3.1.0",
    "typescript": "^5.1.3"
  },
  "private": true
}

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.