I've just taken a deep dive into React Native this past weekend, and (as suspected) I'm liking it a lot. Great job!
When I first started working with the fetch API to request resources, I had chrome dev-tools opened and I was _really_ hoping that I would be able to inspect the web requests happening in chrome's "Network" tab. Of course, that is not the case :(
I am not sure what sort of hoops would have to be jumped through in order to make this a possibility, but I think it would be a great addition if it is possible. Adding this would bring the mobile development workflow _even closer_ to the web development workflow, which RN has done such a good job of doing thus far. This is a huge pain-point for me in normal objective-c development as well, since there are not really any good free HTTP-debugging apps out there for mac OS, and even if there are, that would be yet-another-window to have open at all times.
This is an interesting. Idea. We polyfill the XMLHttpRequest API using native code when running in the JavaScriptCore executor, because XHR is a browser API and as such, simply doesn't exist in a pure-JS context.
But in theory, when running in a browser, we could offer the option to _un_-polyfill the API, and use the browser's HTTP request infrastructure instead. It would have to be an option that was separate from normal debug mode, because it wouldn't be a true test of the app behaviour (it would mask differences in the native XHR implementation), but it seems like a reasonable thing to want to do.
Another option would be to simply pipe request/response headers and bodies through to the JS console so they can be inspected. That would be simpler, but perhaps less useful?
Thoughts, @vjeux?
I had it un-polyfilled before but you run into CORS issues. If you correctly setup CORS then you can comment this line and see all the http requests in the chrome dev tools :)
For convenience it sounds like you can also turn off CORS (and maybe more - use at your own risk) by running Chrome with --disable-web-security. https://blog.nraboy.com/2014/08/bypass-cors-errors-testing-apis-locally/
@vjeux - very cool how easy that is to accomplish!
@ide that's a nifty command line argument. Do you know if I would I be able to just launch chrome with that command line arg and then whenever I launch the debugger from RN it would just work? Or is there a place in the RN source code where I would want to add that command line argument? I will try and test out the former along with @vjeux 's changes myself when I get a chance.
I got this working in a crude way. First quit Chrome so none of its processes are running. I didn't find a way to apply the CLI switch to a single tab. Then run:
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" --disable-web-security
note: a malicious site now can get your gmail, facebook, bank account, etc if you are logged in, so after you're done be sure to restart Chrome. also why I think it's better just to set up CORS if you own the endpoint or write a proxy.
Comment out the line in InitializeJavaScriptAppEngine.js mentioned above in this thread and then when you enable Chrome debugging in an app you get this:
It seems useful to track down issues like too many network requests or forgetting to gzip the responses but it won't help with debugging issues with Cocoa's networking stack that users are running. Also for more than basic HTTP requests (ex: NSURLSession) then advanced apps won't use the XMLHttpRequest polyfill. So, I think it's a good tool to have but Charles Proxy or getting PonyDebugger hooked up looks more fruitful in the longer term.
I wonder if the original implementation of XHR could be saved somewhere else in GLOBALS, e.g. GLOBALS.originalXhr = XMLHttpRequest ? Then it would be possible to undo the polyfill in application code rather than needing to patch and unpatch the RN libraries?
Out of curiosity why was this issue closed? Seems like it's still a very useful to have feature. The workaround is pretty dangerous.
You are right, this is a useful feature to have. Reopening it. @brentvatne is there a duplicate one somewhere?
Is there a good fix? Here are all the ideas I have:
Kind of depends how far you want to go with the Chrome tools compared to investing in the JSC ones instead.
These issues only occur in the absence of CORS, right? Maybe it's possible
to detect CORS-compatible domains and route appropriately?
On Mon, Oct 5, 2015 at 4:53 PM James Ide [email protected] wrote:
Is there a good fix? Here are all the ideas I have:
- Use Charles Proxy or something similar. I do this and find it works
well since you can capture all traffic, and it works across all RN
environments.- Don't use Chrome since people have important cookies saved there.
Run in some kind of sandboxed Electron environment instead since you don't
use Electron to log into your bank.- Run a proxy server and rewrite all URLs to go through it. Maybe can
be done cleanly.Kind of depends how far you want to go with the Chrome tools compared to
investing in the JSC ones instead.—
Reply to this email directly or view it on GitHub
https://github.com/facebook/react-native/issues/934#issuecomment-145700543
.
That's a good point... actually what if we just didn't solve the CORS issue? 1/ if you're talking to your own server, send back the right CORS header w/1-3 lines of code. 2/ if you're talking to someone else's server w/out the right CORS headers then you have lots of workarounds (proxy server, disable web security, Charles Proxy).
:+1: Would prefer that
So if we ignore CORS issues we just need a way to tell RN not to polyfill XHR and fetch.
Do we want to do this by default? Pro: good debugging experience. Con: i'm concerned about getting too attached to Chrome's behavior. RN can do a better job in a lot of ways that make more sense for mobile. So I don't really want to set the expectation that if something works in RN it will totally work in other environments.
We could also expose the original XHR/fetch implementations as global.originalFetch and global.originalXMLHttpRequest, and let users set global.fetch = global.originalFetch.
Well, not polyfilling allows users to polyfill themselves if they want to (e.g. if they're in their debug environment, they may want to).
Aren't we already pretty attached to Chrome behavior anyway (with code being executed in that context when it's active)? Might as well go all the way and make that even more consistent - even if that makes it _less_ consistent with a JSC environment
Simply exposing the original implementations seems like a reasonable approach too, if there are too many concerns going further down the Chrome rabbit-hole
We could also expose the original XHR/fetch implementations as global.originalFetch and global.originalXMLHttpRequest, and let users set global.fetch = global.originalFetch.
Seems like the best solution. If you know what you are doing, just put that js line at the top of your file and boom, you use chrome to download and have to deal with XHR yourself.
Sounds great! As a dev I can deal with CORS myself. I would love to be able to override with just one line. :+1:
You can do that today btw, in your app entry point, write
var _oldXHR = XMLHTTPRequest;
require('react-native');
XMLHTTPRequest = _oldXHR;
should do the trick. We initialize all those variables the first time we require react-native right now (I want to change it to be there before, but that's another story)
Aren't we already pretty attached to Chrome behavior anyway (with code being executed in that context when it's active)?
Well I'm interested in potentially killing the Chrome dev tools and replacing them with Node.js dev tools (you'd run in a Node context). We're already moving away from a Chrome environment by running the RN code in a WebWorker.
Anyone want to send a PR for the proposal of exposing the original implementations if they exist? (Also in advance -- would we want these to be non-enumerable properties? Doesn't get us anything I think but also doesn't hurt.)
Thanks @nevir!
works for me
require('react-native');
delete GLOBAL.XMLHttpRequest;
A support request related to this issue: http://stackoverflow.com/questions/33997443/how-can-i-view-network-requests-for-debugging-in-react-native
If anybody in this thread would like to provide an answer there, I'd appreciate it - making sense of this issue as an outsider is pretty difficult, and given that there are apparently security issues involved (or have they been fixed by @nevir's last contribution? I don't really understand), it would be useful to have some instructions on how to get this working from somebody who knows what they're talking about.
Failing that, I'll try to make sense of this tonight and self-answer.
Hmm, sorry, just realised that delete GLOBAL.XMLHttpRequest;
seems to work. (EDIT: Scratch that, it causes FormData
payloads sent with fetch()
to get sent as [object Object]
and thereby breaks everything in my app. Not sure if this should be a separate issue.) Could somebody clarify whether there are still any security issues involved with this somehow?
@ExplodingCabbage I belive there is GLOBAL.originalXMLHttpRequest
which you can use
@satya164, hmm, now all my requests fail in a new way - with CORS errors:
XMLHttpRequest cannot load http://example.com. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8081' is therefore not allowed access. The response had HTTP status code 400.
@ExplodingCabbage Ah, forgot about CORS :(
We really need a way to debug network requests in dev tools. I'll look into integrating Stetho into RN when I've some time, so that we can debug network requests.
Unless I'm making a mistake that somebody wants to point out, it sounds like @MattFoley's commit wasn't sufficient to really resolve this issue and it needs reopening.
@satya164 This is a help-wanted for me for sure, not just to sniff external http but also for internal http to and from a device database server.
@ssomnoremac Yeah. I've not gotten time to look into it. PR is welcome.
Not entirely sure how I've been attached to this, but just an FYI, that was not my commit. Seems to have happened across a large number of commits.
For CROS, you can open chrome in a new instance. This way you do not have to close your other tabs and loose security.
For Mac:
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --user-data-dir="/tmp/chrome_dev_session" --disable-web-security
For Linux:
open -n -a Google\ Chrome --gs --user-data-dir="/Users/yourUsername/dev/chrome" --disable-web-security
This works right now ( in react-native version 0.29 ) with stetho.
Well documented for react-native <0.29 and as a comment (from me) for react-native 0.29 .
@RakanNimer Do you have the instructions on how you set it up? Would be nice to add this into the official docs.
Yep but only on Android for now.
Below are the instructions on how I set it up, will update when I run it on iOS:
In android/app/build.gradle
, add
compile 'com.facebook.stetho:stetho:1.3.1'
compile 'com.facebook.stetho:stetho-okhttp3:1.3.1'
In android/app/src/main/java/com/{yourAppName}/MainApplication.java
, add the following imports :
import com.facebook.react.modules.network.ReactCookieJarContainer;
import com.facebook.stetho.Stetho;
import okhttp3.OkHttpClient;
import com.facebook.react.modules.network.OkHttpClientProvider;
import com.facebook.stetho.okhttp3.StethoInterceptor;
import java.util.concurrent.TimeUnit;
In android/app/src/main/java/com/{yourAppName}/MainApplication.java
add the function:
public void onCreate() {
super.onCreate();
Stetho.initializeWithDefaults(this);
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(0, TimeUnit.MILLISECONDS)
.readTimeout(0, TimeUnit.MILLISECONDS)
.writeTimeout(0, TimeUnit.MILLISECONDS)
.cookieJar(new ReactCookieJarContainer())
.addNetworkInterceptor(new StethoInterceptor())
.build();
OkHttpClientProvider.replaceOkHttpClient(client);
}
react-native run-android
chrome://inspect
, click on 'Inspect device' (the one followed by "Powered by stethos")@RakanNimer That's awesome. Will try it tomorrow. Wanna send a PR to add it to the docs? I'm sure it'll be useful to lots of people.
@satya164 Yeah for sure. Will do that later today :)
It doesn't show WebSocket frames after integrating Stetho. Anyone up for working on stetho support in the WebSocket module?
I am trying to setup stetho per the instructions and am getting a build error:
import com.facebook.react.modules.network.ReactCookieJarContainer;
^
symbol: class ReactCookieJarContainer
location: package com.facebook.react.modules.network
/Users/srhise/native/fastlane-mobile-app/android/app/src/main/java/com/abcregistration/MainActivity.java:19: error: package okhttp3 does not exist
import okhttp3.OkHttpClient;
^
/Users/srhise/native/fastlane-mobile-app/android/app/src/main/java/com/abcregistration/MainActivity.java:74: error: no suitable method found for onCreate(no arguments)
super.onCreate();
^
method Activity.onCreate(Bundle) is not applicable
(actual and formal argument lists differ in length)
method Activity.onCreate(Bundle,PersistableBundle) is not applicable
(actual and formal argument lists differ in length)
method ReactActivity.onCreate(Bundle) is not applicable
(actual and formal argument lists differ in length)
/Users/srhise/native/fastlane-mobile-app/android/app/src/main/java/com/abcregistration/MainActivity.java:76: error: cannot find symbol
OkHttpClient client = new OkHttpClient.Builder()
^
symbol: class OkHttpClient
location: class MainActivity
/Users/srhise/native/fastlane-mobile-app/android/app/src/main/java/com/abcregistration/MainActivity.java:80: error: cannot find symbol
.cookieJar(new ReactCookieJarContainer())
^
symbol: class ReactCookieJarContainer
location: class MainActivity
/Users/srhise/native/fastlane-mobile-app/android/app/src/main/java/com/abcregistration/MainActivity.java:76: error: package OkHttpClient does not exist
OkHttpClient client = new OkHttpClient.Builder()
I added the .jar libraries to /android/app/libs
What am I missing?
Hey @srhise,
Which version of RN are you running ?
Is there a way of logging these ? I would even be open to enabling a flag that would just output it to console.log
Commenting that line or explicitly deleting that property doesn't work for me. Later I am keep getting: Network request failed
errors. Which kind of makes sense for me - we don't have any XMLHttpRequest
implementation. Running on 0.32.0
RN0.29.2 when I use remote debugger,chrome got this below:
'No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8081' is therefore not allowed access. The response had HTTP status code 404.'
I googled it and try to figured it out,but not successfully,i have no idea,who can help me out!
@xiDaiDai You can use this chrome plugin https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi to quickly enable/disable CORS
@krzkaczor not work for me
@facebook-github-bot label Icebox
Hi there! This issue is being closed because it has been inactive for a while.
But don't worry, it will live on with ProductPains! Check out its new home: https://productpains.com/post/react-native/show-network-requests-such-as-fetch-websocket-etc-in-chrome-dev-tools
ProductPains helps the community prioritize the most important issues thanks to its voting feature.
It is easy to use - just login with GitHub.
Also, if this issue is a bug, please consider sending a PR with a fix.
We're a small team and rely on the community for bug fixes of issues that don't affect fb apps.
@facebook-github-bot close
@charpeni tells me to close this issue. If you think it should still be opened let us know why.
would be super nice have this out of the box!
Would be interested in helping if we could settle on approach for an
alternative solution
On Mon, Nov 14, 2016 at 7:01 PM Guilherme Decampo [email protected]
wrote:
would be super nice have this out of the box!
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/facebook/react-native/issues/934#issuecomment-260503789,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AA3ywT0iioxx0-_Smj5r8PLcDdhc_f8Vks5q-PZHgaJpZM4EEc2q
.
This feature would be awesome.
I'm currently doing this to log all fetch requests and responses:
// fetch logger
global._fetch = fetch;
global.fetch = function(uri, options, ...args) {
return global._fetch(uri, options, ...args).then((response) => {
console.log('Fetch', { request: { uri, options, ...args }, response });
return response;
});
};
@brunolemos Very nice!
Now I'm using this much better solution:
GLOBAL.XMLHttpRequest = GLOBAL.originalXMLHttpRequest || GLOBAL.XMLHttpRequest;
The requests will appear on Chrome Network tab if the Remote JS Debugging is enabled.
EDIT: If the response body is not appearing to you, use the answer above as a complement.
--
🐦 Twitter: @brunolemos
^ this has CORS implications, right?
@jaredly yes.
@brunolemos this has CORS Access-Control-Allow-Origin problem.
I rarely need to debug api calls, but didn't have any cross domain problems yet with this solution workaround. Just to be clear, I comment this line of code after using it.
Where exactly in your RN project do you put this code?
Sean Hise
On Thu, Jan 5, 2017 at 9:24 PM, Bruno Lemos notifications@github.com
wrote:
I use this solution rarely, when I need to inspect some api calls, but
didn't have any cross domain problems yet.—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/facebook/react-native/issues/934#issuecomment-270815128,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AA3ywcUnBbcaMF-mDueZmH2S7bp_D2-Tks5rPaXygaJpZM4EEc2q
.
@srhise For me it worked properly when I've added it, for example, in the index.android.js
just after imports:
//...
import React from 'react'
GLOBAL.XMLHttpRequest = GLOBAL.originalXMLHttpRequest || GLOBAL.XMLHttpRequest
@brunolemos Do I need to do additional setup in chrome? I install plugin, but not understand correct settings in it. Can you add screenshot with right configuration?
I'm still seeing [Object object]
for FormData requests with files in them.
We're also missing the first request we send to the server right at the start of the application. When does "Debug JS Remotely" bridge get formed? It seems to me that the request happens before the remote debugging bridge is initialized and I'm not quite sure how to detect if the bridge is up or not.
@brunolemos Your solution works best ! Easy and clean ! Thanks :)
Thanks for the solution ;)
@brunolemos thanks guys
Would definitely like to see this implemented. https://react-native.canny.io/feature-requests/p/show-network-activity-in-dev-tools
I see the Network requests coming through using the proposed solution, but I don't see anything in Response or Preview tabs. Is anyone seeing the actual response payload in the Network tab? I tried on Chrome and Canary, same result for both.
I am never able to see anything in the response or preview tab either.
Sean Hise
On Wed, Apr 19, 2017 at 8:28 PM, seanadkinson notifications@github.com
wrote:
I see the Network requests coming through using the proposed solution, but
I don't see anything in Response or Preview tabs. Is anyone seeing the
actual response payload in the Network tab? I tried on Chrome and Canary,
same result for both.—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/facebook/react-native/issues/934#issuecomment-295509395,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AA3ywf4HggI9ct4AIq5EwQki24VNEBR_ks5rxqaUgaJpZM4EEc2q
.
Using @brunolemos's
GLOBAL.XMLHttpRequest = GLOBAL.originalXMLHttpRequest || GLOBAL.XMLHttpRequest
in the index.ios.js
as recommended by @tomaszpolanski:
I see the network requests in Chrome Dev Tools Network Tab,
BUT get the console error:
XMLHttpRequest cannot load https://<site>.com/api/users.
Response to preflight request doesn't pass access control check:
No 'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'http://localhost:8081' is therefore not allowed access.
The response had HTTP status code 405.
Which breaks all requests (so breaks the app)
Any thoughts on how to add a header, or resolve this issue?
@peterjacobson start a new instance of Chrome with flags --disable-web-security --user-data-dir
. Makes sure you close all instances of Chrome first. E.g. on Windows: "C:\Program Files (x86)\Google\Chrome\Application\Chrome.exe" --disable-web-security --user-data-dir
@brunolemos solution works well. But doesn't gives response bodies for some reason.
It sure doesn't, which is unfortunate. It would be awesome if this issue
was revisited.
On Thu, May 25, 2017 at 8:37 AM Oliver Benns notifications@github.com
wrote:
@brunolemos https://github.com/brunolemos solution works well. But
doesn't gives response bodies for some reason.—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/facebook/react-native/issues/934#issuecomment-303999853,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AA3ywSJRdqc9V2oZfPpVkATCvFQ0PEHtks5r9XXtgaJpZM4EEc2q
.
@brunolemos same here
Cannot believe, this is 2017, and we do not have a solution to this.
First hack done not work for me. Second hack do not print headers. All
these are hack. Network Tab should only be the place to see network
requests. I was very surprised to see that we still need to use these hacks
at the year too.
I am using fetch APIs and I want to check whether I am sending cookies or
not. Checking this much taking huge pain.
@nsisodiya if that's a need to you, maybe you can dive in to the react native source code and help with a pull request
I wish I could. From last 10 years, I only coded JavaScript. I am pretty
sure, this bug needs Java skills. I am ready to contribute when it comes to
JavaScript.
@brunobar79 I've been using that other way but it slows down the app when debugging because of console.log
@peterjacobson
GLOBAL.XMLHttpRequest = GLOBAL.originalXMLHttpRequest || GLOBAL.XMLHttpRequest
I don't get the headers passed through that way
None of the proposed solutions is working for me, quite amazed that react-native doesn’t have a way to do something as simple as this.
@brunolemos Your solution does work. But there's one issue when doing multi-part file XHR requests. They fail when we use GLOBAL.XMLHttpRequest = GLOBAL.originalXMLHttpRequest || GLOBAL.XMLHttpRequest
Not working with me. I can see the requests on chrome network monitor but they fail and then an error appears on the phone
Seems like there isn't a proper solution so far. Meanwhile, I made @brunolemos's solution just a little bit prettier. My logs are flooded anyway, and I need something like this. Don't mind me. :)
const showApiCalls = () => {
const baseUrl = 'http://www.mocky.io/';
global._fetch = fetch;
global.fetch = async (uri, options, ...args) => {
const response = await global._fetch(uri, options, ...args);
if (uri.includes(baseUrl)) {
console.log(
'🔵 API Call: ',
uri,
{ request: { uri }, response },
);
}
return response;
};
};
Adding GLOBAL.XMLHttpRequest = GLOBAL.originalXMLHttpRequest || GLOBAL.XMLHttpRequest;
works but also introduces other issues which is more severe.
Now network requests will not work at all when react native debugger is turned on with this line in place.
Using react-native 0.47 on macOS
I didn't realise until a few days back how well network calls work in React Native Debugger. You just have to enable them by selecting Enable Network Inspect in the options. Try this. I absolutely love React Native Debugger. ❤️
Most helpful comment
Now I'm using this much better solution:
The requests will appear on Chrome Network tab if the Remote JS Debugging is enabled.
EDIT: If the response body is not appearing to you, use the answer above as a complement.
--
🐦 Twitter: @brunolemos