diff --git a/packages/core/android/src/main/java/com/segment/analytics/reactnative/core/RNAnalyticsModule.kt b/packages/core/android/src/main/java/com/segment/analytics/reactnative/core/RNAnalyticsModule.kt
index d43d3a7d7..bc6b90241 100644
--- a/packages/core/android/src/main/java/com/segment/analytics/reactnative/core/RNAnalyticsModule.kt
+++ b/packages/core/android/src/main/java/com/segment/analytics/reactnative/core/RNAnalyticsModule.kt
@@ -26,15 +26,14 @@ package com.segment.analytics.reactnative.core
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
+import android.net.Uri
import com.facebook.react.bridge.*
-import com.segment.analytics.Analytics
-import com.segment.analytics.Properties
-import com.segment.analytics.Options
-import com.segment.analytics.Traits
-import com.segment.analytics.ValueMap
import com.segment.analytics.internal.Utils.getSegmentSharedPreferences
import java.util.concurrent.TimeUnit
import com.facebook.react.bridge.ReadableMap
+import com.segment.analytics.*
+import java.io.IOException
+import java.net.HttpURLConnection
@@ -155,6 +154,37 @@ class RNAnalyticsModule(context: ReactApplicationContext): ReactContextBaseJavaM
builder.trackApplicationLifecycleEvents()
}
+ if(options.hasKey("proxy") && options.getType("proxy") == ReadableType.Map) {
+ val proxyOptions = options.getMap("proxy")!!
+
+ builder.connectionFactory(object:ConnectionFactory() {
+ override fun openConnection(url:String): HttpURLConnection {
+ val uri = Uri.parse(url)
+ val uriBuilder = uri.buildUpon();
+
+ if (proxyOptions.hasKey("scheme")) {
+ uriBuilder.scheme(proxyOptions.getString("scheme"))
+ }
+
+ if (proxyOptions.hasKey("host")) {
+ var host = proxyOptions.getString("host");
+
+ if (proxyOptions.hasKey("port")) {
+ host = host + ":" + proxyOptions.getInt("port");
+ }
+
+ uriBuilder.encodedAuthority(host)
+ }
+
+ if (proxyOptions.hasKey("path")) {
+ uriBuilder.path(proxyOptions.getString("path") + uri.path)
+ }
+
+ return super.openConnection(uriBuilder.toString())
+ }
+ })
+ }
+
try {
Analytics.setSingletonInstance(
RNAnalytics.buildWithIntegrations(builder)
diff --git a/packages/core/docs/README.md b/packages/core/docs/README.md
index 658447474..0551e089c 100644
--- a/packages/core/docs/README.md
+++ b/packages/core/docs/README.md
@@ -24,7 +24,7 @@
**Ƭ Integration**: *`function` \| `object`*
-*Defined in [analytics.ts:8](https://github.com/segmentio/analytics-react-native/blob/master/packages/core/src/analytics.ts#L8)*
+*Defined in [analytics.ts:8](https://github.com/adkenyon/analytics-react-native/blob/master/packages/core/src/analytics.ts#L8)*
___
diff --git a/packages/core/docs/classes/analytics.client.md b/packages/core/docs/classes/analytics.client.md
index 0b67d6eac..ae51bb114 100644
--- a/packages/core/docs/classes/analytics.client.md
+++ b/packages/core/docs/classes/analytics.client.md
@@ -39,7 +39,7 @@
**● ready**: *`false`* = false
-*Defined in [analytics.ts:104](https://github.com/segmentio/analytics-react-native/blob/master/packages/core/src/analytics.ts#L104)*
+*Defined in [analytics.ts:147](https://github.com/adkenyon/analytics-react-native/blob/master/packages/core/src/analytics.ts#L147)*
Whether the client is ready to send events to Segment.
@@ -55,7 +55,7 @@ ___
▸ **alias**(newId: *`string`*, options?: *[Options]()*): `Promise`<`void`>
-*Defined in [analytics.ts:274](https://github.com/segmentio/analytics-react-native/blob/master/packages/core/src/analytics.ts#L274)*
+*Defined in [analytics.ts:317](https://github.com/adkenyon/analytics-react-native/blob/master/packages/core/src/analytics.ts#L317)*
Merge two user identities, effectively connecting two sets of user data as one. This may not be supported by all integrations.
@@ -77,7 +77,7 @@ ___
▸ **catch**(handler: *[ErrorHandler]()*): `this`
-*Defined in [analytics.ts:119](https://github.com/segmentio/analytics-react-native/blob/master/packages/core/src/analytics.ts#L119)*
+*Defined in [analytics.ts:162](https://github.com/adkenyon/analytics-react-native/blob/master/packages/core/src/analytics.ts#L162)*
Catch React-Native bridge errors
@@ -98,7 +98,7 @@ ___
▸ **disable**(): `Promise`<`void`>
-*Defined in [analytics.ts:313](https://github.com/segmentio/analytics-react-native/blob/master/packages/core/src/analytics.ts#L313)*
+*Defined in [analytics.ts:356](https://github.com/adkenyon/analytics-react-native/blob/master/packages/core/src/analytics.ts#L356)*
Completely disable the sending of any analytics data.
@@ -113,7 +113,7 @@ ___
▸ **enable**(): `Promise`<`void`>
-*Defined in [analytics.ts:303](https://github.com/segmentio/analytics-react-native/blob/master/packages/core/src/analytics.ts#L303)*
+*Defined in [analytics.ts:346](https://github.com/adkenyon/analytics-react-native/blob/master/packages/core/src/analytics.ts#L346)*
Enable the sending of analytics data. Enabled by default.
@@ -128,7 +128,7 @@ ___
▸ **flush**(): `Promise`<`void`>
-*Defined in [analytics.ts:294](https://github.com/segmentio/analytics-react-native/blob/master/packages/core/src/analytics.ts#L294)*
+*Defined in [analytics.ts:337](https://github.com/adkenyon/analytics-react-native/blob/master/packages/core/src/analytics.ts#L337)*
Trigger an upload of all queued events.
@@ -143,7 +143,7 @@ ___
▸ **getAnonymousId**(): `Promise`<`string`>
-*Defined in [analytics.ts:318](https://github.com/segmentio/analytics-react-native/blob/master/packages/core/src/analytics.ts#L318)*
+*Defined in [analytics.ts:361](https://github.com/adkenyon/analytics-react-native/blob/master/packages/core/src/analytics.ts#L361)*
Retrieve the anonymousId.
@@ -156,7 +156,7 @@ ___
▸ **group**(groupId: *`string`*, traits?: *[JsonMap]()*, options?: *[Options]()*): `Promise`<`void`>
-*Defined in [analytics.ts:261](https://github.com/segmentio/analytics-react-native/blob/master/packages/core/src/analytics.ts#L261)*
+*Defined in [analytics.ts:304](https://github.com/adkenyon/analytics-react-native/blob/master/packages/core/src/analytics.ts#L304)*
Associate a user with a group, organization, company, project, or w/e _you_ call them.
@@ -179,7 +179,7 @@ ___
▸ **identify**(user: *`string`*, traits?: *[JsonMap]()*, options?: *[Options]()*): `Promise`<`void`>
-*Defined in [analytics.ts:248](https://github.com/segmentio/analytics-react-native/blob/master/packages/core/src/analytics.ts#L248)*
+*Defined in [analytics.ts:291](https://github.com/adkenyon/analytics-react-native/blob/master/packages/core/src/analytics.ts#L291)*
Associate a user with their unique ID and record traits about them.
@@ -202,7 +202,7 @@ ___
▸ **middleware**(middleware: *[Middleware]()*): `this`
-*Defined in [analytics.ts:157](https://github.com/segmentio/analytics-react-native/blob/master/packages/core/src/analytics.ts#L157)*
+*Defined in [analytics.ts:200](https://github.com/adkenyon/analytics-react-native/blob/master/packages/core/src/analytics.ts#L200)*
Append a new middleware to the middleware chain.
@@ -240,7 +240,7 @@ ___
▸ **reset**(): `Promise`<`void`>
-*Defined in [analytics.ts:284](https://github.com/segmentio/analytics-react-native/blob/master/packages/core/src/analytics.ts#L284)*
+*Defined in [analytics.ts:327](https://github.com/adkenyon/analytics-react-native/blob/master/packages/core/src/analytics.ts#L327)*
Reset any user state that is cached on the device.
@@ -255,7 +255,7 @@ ___
▸ **screen**(name: *`string`*, properties?: *[JsonMap]()*, options?: *[Options]()*): `Promise`<`void`>
-*Defined in [analytics.ts:233](https://github.com/segmentio/analytics-react-native/blob/master/packages/core/src/analytics.ts#L233)*
+*Defined in [analytics.ts:276](https://github.com/adkenyon/analytics-react-native/blob/master/packages/core/src/analytics.ts#L276)*
Record the screens or views your users see.
@@ -278,7 +278,7 @@ ___
▸ **setup**(writeKey: *`string`*, configuration?: *[Configuration](../interfaces/analytics.configuration.md)*): `Promise`<`void`>
-*Defined in [analytics.ts:196](https://github.com/segmentio/analytics-react-native/blob/master/packages/core/src/analytics.ts#L196)*
+*Defined in [analytics.ts:239](https://github.com/adkenyon/analytics-react-native/blob/master/packages/core/src/analytics.ts#L239)*
Setup the Analytics module. All calls made before are queued and only executed if the configuration was successful.
@@ -308,7 +308,7 @@ ___
▸ **track**(event: *`string`*, properties?: *[JsonMap]()*, options?: *[Options]()*): `Promise`<`void`>
-*Defined in [analytics.ts:215](https://github.com/segmentio/analytics-react-native/blob/master/packages/core/src/analytics.ts#L215)*
+*Defined in [analytics.ts:258](https://github.com/adkenyon/analytics-react-native/blob/master/packages/core/src/analytics.ts#L258)*
Record the actions your users perform.
@@ -331,7 +331,7 @@ ___
▸ **useNativeConfiguration**(): `this`
-*Defined in [analytics.ts:169](https://github.com/segmentio/analytics-react-native/blob/master/packages/core/src/analytics.ts#L169)*
+*Defined in [analytics.ts:212](https://github.com/adkenyon/analytics-react-native/blob/master/packages/core/src/analytics.ts#L212)*
Use the native configuration.
diff --git a/packages/core/docs/interfaces/analytics.configuration.md b/packages/core/docs/interfaces/analytics.configuration.md
index bc3b2bb54..a6f3b3fdf 100644
--- a/packages/core/docs/interfaces/analytics.configuration.md
+++ b/packages/core/docs/interfaces/analytics.configuration.md
@@ -15,6 +15,7 @@
* [defaultProjectSettings](analytics.configuration.md#defaultprojectsettings)
* [flushAt](analytics.configuration.md#flushat)
* [ios](analytics.configuration.md#ios)
+* [proxy](analytics.configuration.md#proxy)
* [recordScreenViews](analytics.configuration.md#recordscreenviews)
* [trackAppLifecycleEvents](analytics.configuration.md#trackapplifecycleevents)
* [trackAttributionData](analytics.configuration.md#trackattributiondata)
@@ -30,7 +31,7 @@
**● android**: *`undefined` \| `object`*
-*Defined in [analytics.ts:77](https://github.com/segmentio/analytics-react-native/blob/master/packages/core/src/analytics.ts#L77)*
+*Defined in [analytics.ts:120](https://github.com/adkenyon/analytics-react-native/blob/master/packages/core/src/analytics.ts#L120)*
Android specific settings.
@@ -41,7 +42,7 @@ ___
**● debug**: *`undefined` \| `false` \| `true`*
-*Defined in [analytics.ts:38](https://github.com/segmentio/analytics-react-native/blob/master/packages/core/src/analytics.ts#L38)*
+*Defined in [analytics.ts:38](https://github.com/adkenyon/analytics-react-native/blob/master/packages/core/src/analytics.ts#L38)*
___
@@ -50,7 +51,7 @@ ___
**● defaultProjectSettings**: *`undefined` \| `object`*
-*Defined in [analytics.ts:46](https://github.com/segmentio/analytics-react-native/blob/master/packages/core/src/analytics.ts#L46)*
+*Defined in [analytics.ts:46](https://github.com/adkenyon/analytics-react-native/blob/master/packages/core/src/analytics.ts#L46)*
Default project settings to use, if Segment.com cannot be reached. An example configuration can be found here, using your write key: [](https://cdn-settings.segment.com/v1/projects/YOUR_WRITE_KEY/settings)[https://cdn-settings.segment.com/v1/projects/YOUR\_WRITE\_KEY/settings](https://cdn-settings.segment.com/v1/projects/YOUR_WRITE_KEY/settings)
@@ -61,7 +62,7 @@ ___
**● flushAt**: *`undefined` \| `number`*
-*Defined in [analytics.ts:54](https://github.com/segmentio/analytics-react-native/blob/master/packages/core/src/analytics.ts#L54)*
+*Defined in [analytics.ts:54](https://github.com/adkenyon/analytics-react-native/blob/master/packages/core/src/analytics.ts#L54)*
The number of queued events that the analytics client should flush at. Setting this to `1` will not queue any events and will use more battery.
@@ -74,10 +75,23 @@ ___
**● ios**: *`undefined` \| `object`*
-*Defined in [analytics.ts:59](https://github.com/segmentio/analytics-react-native/blob/master/packages/core/src/analytics.ts#L59)*
+*Defined in [analytics.ts:102](https://github.com/adkenyon/analytics-react-native/blob/master/packages/core/src/analytics.ts#L102)*
iOS specific settings.
+___
+
+
+### `` proxy
+
+**● proxy**: *`undefined` \| `object`*
+
+*Defined in [analytics.ts:72](https://github.com/adkenyon/analytics-react-native/blob/master/packages/core/src/analytics.ts#L72)*
+
+Whether the analytics client should send all requests through your own hosted proxy rather than directly to Segment. See: iOS: [https://segment.com/docs/connections/sources/catalog/libraries/mobile/ios/#proxy-http-calls](https://segment.com/docs/connections/sources/catalog/libraries/mobile/ios/#proxy-http-calls) android: [https://segment.com/docs/connections/sources/catalog/libraries/mobile/android/#proxy-http-calls](https://segment.com/docs/connections/sources/catalog/libraries/mobile/android/#proxy-http-calls)
+
+Ex. For a desired proxy through `http://localhost:64000/segment` the configuration would look like such { scheme: 'http', host: 'localhost', port: 64000, path: '/segment' }
+
___
@@ -85,7 +99,7 @@ ___
**● recordScreenViews**: *`undefined` \| `false` \| `true`*
-*Defined in [analytics.ts:19](https://github.com/segmentio/analytics-react-native/blob/master/packages/core/src/analytics.ts#L19)*
+*Defined in [analytics.ts:19](https://github.com/adkenyon/analytics-react-native/blob/master/packages/core/src/analytics.ts#L19)*
Whether the analytics client should automatically make a screen call when a view controller is added to a view hierarchy. Because the iOS underlying implementation uses method swizzling, we recommend initializing the analytics client as early as possible.
@@ -98,7 +112,7 @@ ___
**● trackAppLifecycleEvents**: *`undefined` \| `false` \| `true`*
-*Defined in [analytics.ts:26](https://github.com/segmentio/analytics-react-native/blob/master/packages/core/src/analytics.ts#L26)*
+*Defined in [analytics.ts:26](https://github.com/adkenyon/analytics-react-native/blob/master/packages/core/src/analytics.ts#L26)*
Whether the analytics client should automatically track application lifecycle events, such as "Application Installed", "Application Updated" and "Application Opened".
@@ -111,7 +125,7 @@ ___
**● trackAttributionData**: *`undefined` \| `false` \| `true`*
-*Defined in [analytics.ts:32](https://github.com/segmentio/analytics-react-native/blob/master/packages/core/src/analytics.ts#L32)*
+*Defined in [analytics.ts:32](https://github.com/adkenyon/analytics-react-native/blob/master/packages/core/src/analytics.ts#L32)*
Whether the analytics client should automatically track attribution data from enabled providers using the mobile service.
@@ -124,7 +138,7 @@ ___
**● using**: *[Integration](../#integration)[]*
-*Defined in [analytics.ts:37](https://github.com/segmentio/analytics-react-native/blob/master/packages/core/src/analytics.ts#L37)*
+*Defined in [analytics.ts:37](https://github.com/adkenyon/analytics-react-native/blob/master/packages/core/src/analytics.ts#L37)*
Register a set of integrations to be used with this Analytics instance.
diff --git a/packages/core/ios/RNAnalytics/RNAnalytics.m b/packages/core/ios/RNAnalytics/RNAnalytics.m
index 9428b4d86..d4cd2079b 100644
--- a/packages/core/ios/RNAnalytics/RNAnalytics.m
+++ b/packages/core/ios/RNAnalytics/RNAnalytics.m
@@ -63,6 +63,33 @@ +(void)initialize {
config.enableAdvertisingTracking = [options[@"ios"][@"trackAdvertising"] boolValue];
config.defaultSettings = options[@"defaultProjectSettings"];
+ if ([options valueForKey:@"proxy"]) {
+ NSDictionary *proxyOptions = (NSDictionary *)[options valueForKey:@"proxy"];
+
+ config.requestFactory = ^(NSURL *url) {
+ NSURLComponents *components = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:NO];
+
+ if ([proxyOptions valueForKey:@"scheme"]) {
+ components.scheme = [proxyOptions[@"scheme"] stringValue];
+ }
+
+ if ([proxyOptions valueForKey:@"host"]) {
+ components.host = [proxyOptions[@"host"] stringValue];
+ }
+
+ if ([proxyOptions valueForKey:@"port"]) {
+ components.port = [NSNumber numberWithInt:[proxyOptions[@"port"] intValue]];
+ }
+
+ if ([proxyOptions valueForKey:@"path"]) {
+ components.path = [[proxyOptions[@"path"] stringValue] stringByAppendingString:components.path];
+ }
+
+ NSURL *transformedURL = components.URL;
+ return [NSMutableURLRequest requestWithURL:transformedURL];
+ };
+ }
+
for(id factory in RNAnalyticsIntegrations) {
[config use:factory];
}
diff --git a/packages/core/src/analytics.ts b/packages/core/src/analytics.ts
index acb303e65..b8a1ec405 100644
--- a/packages/core/src/analytics.ts
+++ b/packages/core/src/analytics.ts
@@ -53,6 +53,49 @@ export module Analytics {
*/
flushAt?: number
+ /**
+ * Whether the analytics client should send all requests through your own hosted
+ * proxy rather than directly to Segment.
+ * See:
+ * iOS: https://segment.com/docs/connections/sources/catalog/libraries/mobile/ios/#proxy-http-calls
+ * android: https://segment.com/docs/connections/sources/catalog/libraries/mobile/android/#proxy-http-calls
+ *
+ * Ex. For a desired proxy through `http://localhost:64000/segment` the configuration would look like such
+ * {
+ * scheme: 'http',
+ * host: 'localhost',
+ * port: 64000,
+ * path: '/segment'
+ * }
+ *
+ */
+ proxy?: {
+
+ /**
+ * The proxy scheme, ex: http, https
+ *
+ * `https` by default.
+ */
+ scheme?: string,
+
+ /**
+ * The proxy host name, ex: api.segment.io, cdn.segment.io
+ *
+ * Note: When using localhost with an Android device or simulator use `adb reverse tcp: tcp:`
+ */
+ host?: string,
+
+ /**
+ * The proxy port number, ex: 80
+ */
+ port?: number,
+
+ /**
+ * The proxy path, ex: /path/to/proxy
+ */
+ path?: string,
+ },
+
/**
* iOS specific settings.
*/
diff --git a/packages/core/src/bridge.ts b/packages/core/src/bridge.ts
index 7f8c4eff7..64244983b 100644
--- a/packages/core/src/bridge.ts
+++ b/packages/core/src/bridge.ts
@@ -9,6 +9,12 @@ export interface Configuration {
flushAt: number
json: string
defaultProjectSettings: { [key: string]: any }
+ proxy?: {
+ scheme?: string
+ host?: string
+ port?: number
+ path?: string
+ }
android: {
flushInterval?: number
diff --git a/packages/core/src/configuration.ts b/packages/core/src/configuration.ts
index f40ba9e66..af3485666 100644
--- a/packages/core/src/configuration.ts
+++ b/packages/core/src/configuration.ts
@@ -28,6 +28,7 @@ export const configure = async (
trackAttributionData = false,
using = [],
defaultProjectSettings = {},
+ proxy = undefined,
ios = {},
android = {}
@@ -47,6 +48,7 @@ export const configure = async (
trackAppLifecycleEvents,
trackAttributionData,
writeKey,
+ proxy,
android: defaults.android(android),
ios: defaults.ios(ios)