Skip to content

[Help Wanted]: Native-level handling of terminal HTTP response status codes #2651

Description

@suresh-mojro

Required Reading

  • Confirmed

Plugin Version

5.4.0

Mobile operating-system(s)

  • iOS
  • Android

Device Manufacturer(s) and Model(s)

All

Device operating-systems(s)

All

React Native / Expo version

React Native 0.79.6

What do you require assistance about?

Feature Request: Native-level handling of terminal HTTP response status codes
Summary
We need a way to stop location tracking / uploads at the native SDK level when our backend responds to a location POST with a status code indicating the tracking session is no longer valid (e.g. 401, 403, 404).
Background
Our backend can return specific HTTP status codes to signal that the current tracking session/trip is no longer valid, and that the app should stop sending further location traces.
Location HTTP requests are handled by the plugin's native HTTP service. This matters most when the app is backgrounded or the React Native JS process is not running — situations where we cannot reliably depend on:

  • React Native JS events
  • onHttp callbacks handled in JS
  • Android Headless JS
    Desired Flow
    Location

    Native BGLocation HTTP service

    POST location to backend

    Backend returns 401 / 404

    Native-level handling

    Stop location tracking / prevent further uploads
    Questions
  1. Does the SDK currently provide any configuration or native callback that exposes specific HTTP response status codes received by the native HTTP service?
  2. Is there an existing mechanism to stop location tracking automatically when the backend returns a specific status code such as 401, 403, or 404?
  3. Can the HTTP response status code be surfaced to a native-level callback/action that works even when:
    • the app is running in the background,
    • the React Native JS process is not running, and
    • Android Headless JS is unavailable?
  4. If this isn't currently supported, would you consider adding a configurable option such as: stopTrackingOnHttpStatus: [401, 404]
  5. so the native HTTP service can stop tracking itself when one of the configured status codes is received?
  6. How does the SDK currently handle non-2xx responses in general — are failed locations retained and retried? Is there a supported way to prevent retries for terminal responses like 404 (as opposed to transient errors)?

Why Native-Level Handling Is Necessary
The native HTTP service can continue processing and uploading locations even when the React Native JS layer is unavailable. Handling this purely in JS or via Headless JS therefore does not guarantee that we can react to a terminal backend response — there are windows where JS simply isn't running to catch it.
We need the SDK to react to the backend response at the native level and stop further tracking/uploading when the backend explicitly indicates the current session is no longer valid.
Please let us know whether this is currently supported and, if not, what the recommended approach would be.

[Optional] Plugin Code and/or Config

{
  desiredOdometerAccuracy: 30,
  speedJumpFilter: 50,

  logger: {
    debug: false,
    logLevel: BackgroundGeolocation.LogLevel.Verbose,
  },

  geolocation: {
    desiredAccuracy: BackgroundGeolocation.DesiredAccuracy.Navigation,
    elasticityMultiplier: 1.5,
    distanceFilter: 7,
    allowIdenticalLocations: false,
    disableStopDetection: false,
    pausesLocationUpdatesAutomatically: false,
    stopTimeout: 3,
    stopOnStationary: false,
    locationAuthorizationRequest: "Always",
    geofenceModeHighAccuracy: true,
  },

  activity: {
    disableStopDetection: false,
    motionTriggerDelay: 2000,
  },

  app: {
    heartbeatInterval: 60,
    enableHeadless: true,
    stopOnTerminate: false,
    startOnBoot: true,
    preventSuspend: false,

    notification: {
      title: "Mojro Partner",
      text: "Location tracking active...",
      priority: BackgroundGeolocation.NotificationPriority.High,
    },
  },

  http: {
    autoSync: true,
    autoSyncThreshold: 2,
    batchSync: true,
    maxBatchSize: 5,
    rootProperty: ".",
  },

  persistence: {
    maxDaysToPersist: 3,
    maxRecordsToPersist: 3000,
  },
}


this.#eventSubscriptions.push(
  BackgroundGeolocation.onHttp(async (response) => {
    if (response.status >= 200 && response.status < 300) {
      this.#recordBgPluginActivityForTraces();
    }

    if (response.status === 401 || response.status === 403) {
      try {
        const isAppActive =
          (this.#appState || AppState.currentState) === "active";

        if (isAppActive) {
          const {
            triggerLoggedOutWithImmediateSessionClear,
          } = require("./forceLogout");
          await triggerLoggedOutWithImmediateSessionClear({
            reason: LOGOUT_REASONS.ACCESS_ISSUE,
            resourceName: ACCESS_RESOURCES.TRIP_ACTION,
          });
        } else {
          const { performImmediateLogout } = require("./forceLogout");
          await performImmediateLogout();
        }
      } catch (error) {
        this.#addLog(
          `Immediate logout after HTTP ${response.status} failed`
        );
        await this.stopTracking();
      }
    }

    if (this.#onHttpCallback) this.#onHttpCallback(response);
  })
);


const BackgroundGeolocationHeadlessTask = async (event) => {
  const params = event.params;

  try {
    switch (event.name) {
      case "http":
        if (params?.status == 401 || params?.status == 403) {
          try {
            await getBGGeolocation().stopTracking();
            await require("./src/utils/forceLogout").performImmediateLogout();
          } catch (error) {
            logError({
              action:
                "[HeadlessTask] Immediate logout on HTTP unauthorized failed",
              errMessage: JSON.stringify(error.message),
              errData: JSON.stringify(error),
            });
          }
        }
        break;
    }
  } catch (error) {
    // ...
  }
};

[Optional] Relevant log output

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions