fix(tracker): fix react-native network tracking issues
This commit is contained in:
parent
c0d4088120
commit
405d33aa2f
4 changed files with 59 additions and 118 deletions
|
|
@ -1,79 +1,3 @@
|
|||
This is a new [**React Native**](https://reactnative.dev) project, bootstrapped using [`@react-native-community/cli`](https://github.com/react-native-community/cli).
|
||||
> [SDK Docs](https://docs.openreplay.com/en/rn-sdk/)
|
||||
|
||||
# Getting Started
|
||||
|
||||
>**Note**: Make sure you have completed the [React Native - Environment Setup](https://reactnative.dev/docs/environment-setup) instructions till "Creating a new application" step, before proceeding.
|
||||
|
||||
## Step 1: Start the Metro Server
|
||||
|
||||
First, you will need to start **Metro**, the JavaScript _bundler_ that ships _with_ React Native.
|
||||
|
||||
To start Metro, run the following command from the _root_ of your React Native project:
|
||||
|
||||
```bash
|
||||
# using npm
|
||||
npm start
|
||||
|
||||
# OR using Yarn
|
||||
yarn start
|
||||
```
|
||||
|
||||
## Step 2: Start your Application
|
||||
|
||||
Let Metro Bundler run in its _own_ terminal. Open a _new_ terminal from the _root_ of your React Native project. Run the following command to start your _Android_ or _iOS_ app:
|
||||
|
||||
### For Android
|
||||
|
||||
```bash
|
||||
# using npm
|
||||
npm run android
|
||||
|
||||
# OR using Yarn
|
||||
yarn android
|
||||
```
|
||||
|
||||
### For iOS
|
||||
|
||||
```bash
|
||||
# using npm
|
||||
npm run ios
|
||||
|
||||
# OR using Yarn
|
||||
yarn ios
|
||||
```
|
||||
|
||||
If everything is set up _correctly_, you should see your new app running in your _Android Emulator_ or _iOS Simulator_ shortly provided you have set up your emulator/simulator correctly.
|
||||
|
||||
This is one way to run your app — you can also run it directly from within Android Studio and Xcode respectively.
|
||||
|
||||
## Step 3: Modifying your App
|
||||
|
||||
Now that you have successfully run the app, let's modify it.
|
||||
|
||||
1. Open `App.tsx` in your text editor of choice and edit some lines.
|
||||
2. For **Android**: Press the <kbd>R</kbd> key twice or select **"Reload"** from the **Developer Menu** (<kbd>Ctrl</kbd> + <kbd>M</kbd> (on Window and Linux) or <kbd>Cmd ⌘</kbd> + <kbd>M</kbd> (on macOS)) to see your changes!
|
||||
|
||||
For **iOS**: Hit <kbd>Cmd ⌘</kbd> + <kbd>R</kbd> in your iOS Simulator to reload the app and see your changes!
|
||||
|
||||
## Congratulations! :tada:
|
||||
|
||||
You've successfully run and modified your React Native App. :partying_face:
|
||||
|
||||
### Now what?
|
||||
|
||||
- If you want to add this new React Native code to an existing application, check out the [Integration guide](https://reactnative.dev/docs/integration-with-existing-apps).
|
||||
- If you're curious to learn more about React Native, check out the [Introduction to React Native](https://reactnative.dev/docs/getting-started).
|
||||
|
||||
# Troubleshooting
|
||||
|
||||
If you can't get this to work, see the [Troubleshooting](https://reactnative.dev/docs/troubleshooting) page.
|
||||
|
||||
# Learn More
|
||||
|
||||
To learn more about React Native, take a look at the following resources:
|
||||
|
||||
- [React Native Website](https://reactnative.dev) - learn more about React Native.
|
||||
- [Getting Started](https://reactnative.dev/docs/environment-setup) - an **overview** of React Native and how setup your environment.
|
||||
- [Learn the Basics](https://reactnative.dev/docs/getting-started) - a **guided tour** of the React Native **basics**.
|
||||
- [Blog](https://reactnative.dev/blog) - read the latest official React Native **Blog** posts.
|
||||
- [`@facebook/react-native`](https://github.com/facebook/react-native) - the Open Source; GitHub **repository** for React Native.
|
||||
React-native library for OpenReplay. Read [main README](../../README.md) for more information.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import FetchProxy from './fetchProxy'
|
||||
import XHRProxy from './xhrProxy'
|
||||
import type { RequestResponseData } from './types'
|
||||
import FetchProxy from './fetchProxy';
|
||||
import XHRProxy from './xhrProxy';
|
||||
import type { RequestResponseData } from './types';
|
||||
|
||||
export default function setProxy(
|
||||
context: typeof globalThis,
|
||||
|
|
@ -9,23 +9,24 @@ export default function setProxy(
|
|||
sendMessage: (message: any) => void,
|
||||
isServiceUrl: (url: string) => boolean,
|
||||
tokenUrlMatcher?: (url: string) => boolean,
|
||||
mode: 'fetch' | 'xhr' | 'all' = 'fetch'
|
||||
) {
|
||||
if (context.XMLHttpRequest) {
|
||||
if (context.XMLHttpRequest && mode !== 'fetch') {
|
||||
context.XMLHttpRequest = XHRProxy.create(
|
||||
ignoredHeaders,
|
||||
sanitize,
|
||||
sendMessage,
|
||||
isServiceUrl,
|
||||
tokenUrlMatcher,
|
||||
)
|
||||
tokenUrlMatcher
|
||||
);
|
||||
}
|
||||
if (context.fetch) {
|
||||
if (context.fetch && mode !== 'xhr') {
|
||||
context.fetch = FetchProxy.create(
|
||||
ignoredHeaders,
|
||||
sanitize,
|
||||
sendMessage,
|
||||
isServiceUrl,
|
||||
tokenUrlMatcher,
|
||||
)
|
||||
tokenUrlMatcher
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ import {
|
|||
TextInput,
|
||||
} from 'react-native';
|
||||
import type { ViewProps, TextInputProps } from 'react-native';
|
||||
import network from './network'
|
||||
import type { Options as NetworkOptions } from './network'
|
||||
import network from './network';
|
||||
import type { Options as NetworkOptions } from './network';
|
||||
|
||||
const { ORTrackerConnector } = NativeModules;
|
||||
|
||||
|
|
@ -90,9 +90,17 @@ const emptyShell = {
|
|||
networkRequest: () => null,
|
||||
};
|
||||
|
||||
const patchNetwork = (ctx = global, isServiceUrl = () => false, opts: Partial<NetworkOptions>) => {
|
||||
network(ctx, ORTrackerConnector.networkRequest, isServiceUrl, opts)
|
||||
}
|
||||
let patched = false;
|
||||
const patchNetwork = (
|
||||
ctx = global,
|
||||
isServiceUrl = () => false,
|
||||
opts: Partial<NetworkOptions>
|
||||
) => {
|
||||
if (!patched) {
|
||||
network(ctx, ORTrackerConnector.networkRequest, isServiceUrl, opts);
|
||||
patched = true;
|
||||
}
|
||||
};
|
||||
|
||||
export default {
|
||||
tracker:
|
||||
|
|
|
|||
|
|
@ -1,34 +1,40 @@
|
|||
import setProxy from './Network/index'
|
||||
import setProxy from './Network/index';
|
||||
|
||||
interface RequestData {
|
||||
body: string | null
|
||||
headers: Record<string, string>
|
||||
body: string | null;
|
||||
headers: Record<string, string>;
|
||||
}
|
||||
|
||||
interface ResponseData {
|
||||
body: any
|
||||
headers: Record<string, string>
|
||||
body: any;
|
||||
headers: Record<string, string>;
|
||||
}
|
||||
|
||||
export interface RequestResponseData {
|
||||
readonly status: number
|
||||
readonly method: string
|
||||
url: string
|
||||
request: RequestData
|
||||
response: ResponseData
|
||||
readonly status: number;
|
||||
readonly method: string;
|
||||
url: string;
|
||||
request: RequestData;
|
||||
response: ResponseData;
|
||||
}
|
||||
|
||||
type Sanitizer = (data: RequestResponseData) => RequestResponseData
|
||||
type Sanitizer = (data: RequestResponseData) => RequestResponseData;
|
||||
|
||||
export interface Options {
|
||||
ignoreHeaders: Array<string> | boolean
|
||||
capturePayload: boolean
|
||||
captureInIframes: boolean
|
||||
sanitizer?: Sanitizer
|
||||
tokenUrlMatcher?: (url: string) => boolean
|
||||
ignoreHeaders: Array<string> | boolean;
|
||||
capturePayload: boolean;
|
||||
captureInIframes: boolean;
|
||||
sanitizer?: Sanitizer;
|
||||
tokenUrlMatcher?: (url: string) => boolean;
|
||||
mode: 'fetch' | 'xhr' | 'all';
|
||||
}
|
||||
|
||||
export default function (context = global, sendMessage: (args: any[]) => void, isServiceUrl: (url: string) => boolean, opts: Partial<Options> = {}) {
|
||||
export default function (
|
||||
context = global,
|
||||
sendMessage: (args: any[]) => void,
|
||||
isServiceUrl: (url: string) => boolean,
|
||||
opts: Partial<Options> = {}
|
||||
) {
|
||||
const options: Options = Object.assign(
|
||||
{
|
||||
failuresOnly: false,
|
||||
|
|
@ -37,27 +43,28 @@ export default function (context = global, sendMessage: (args: any[]) => void, i
|
|||
captureInIframes: true,
|
||||
axiosInstances: undefined,
|
||||
useProxy: true,
|
||||
mode: 'fetch',
|
||||
},
|
||||
opts,
|
||||
)
|
||||
opts
|
||||
);
|
||||
|
||||
function sanitize(reqResInfo: RequestResponseData) {
|
||||
if (!options.capturePayload) {
|
||||
// @ts-ignore
|
||||
delete reqResInfo.request.body
|
||||
delete reqResInfo.response.body
|
||||
delete reqResInfo.request.body;
|
||||
delete reqResInfo.response.body;
|
||||
}
|
||||
if (options.sanitizer) {
|
||||
const resBody = reqResInfo.response.body
|
||||
const resBody = reqResInfo.response.body;
|
||||
if (typeof resBody === 'string') {
|
||||
// Parse response in order to have handy view in sanitization function
|
||||
try {
|
||||
reqResInfo.response.body = JSON.parse(resBody)
|
||||
reqResInfo.response.body = JSON.parse(resBody);
|
||||
} catch {}
|
||||
}
|
||||
return options.sanitizer(reqResInfo)
|
||||
return options.sanitizer(reqResInfo);
|
||||
}
|
||||
return reqResInfo
|
||||
return reqResInfo;
|
||||
}
|
||||
|
||||
return setProxy(
|
||||
|
|
@ -67,5 +74,6 @@ export default function (context = global, sendMessage: (args: any[]) => void, i
|
|||
sendMessage,
|
||||
(url) => isServiceUrl(url),
|
||||
options.tokenUrlMatcher,
|
||||
)
|
||||
options.mode
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue