typesense / typesense-js

JavaScript / TypeScript client for Typesense
https://typesense.org/docs/api
Apache License 2.0
393 stars 74 forks source link

Typesense search is double encoding square brackets "[" in bare react-native projects #193

Closed harrisrobin closed 6 months ago

harrisrobin commented 6 months ago

Description

Trying to search using filter_by that have square brackets [ fails due to it getting double encoded. After my discussion with @jasonbosco this seems to be an issue with Axios.

Steps to reproduce

Here is a repo that reproduces the issue: https://github.com/SolidStartsLLC/typesense-axios-double-encoding-issue

Expected Behavior

I expect to not get my query params double encoded when i add a filter with a square bracket []

Actual Behavior

The square brackets are getting double encoded by axios, causing the query to be invalid, therefore returning no data.

Metadata

Typesense Version: 1.7.2

OS: MacOS 14.2.1

Workaround

One solution to solve this is to use multi_search when will send the filter in the body as a POST request, therefore avoiding the double encoding issue.

jasonbosco commented 6 months ago

Thanks @harrisrobin!

Documenting this for other users who might stumble on this:

The issue seems to be deep down in axios' internals when it runs on react native. It seems to double-encode get parameters.

To sidestep the whole issue, you want to use multi_search (even with a single search), then we send the query parameters in the post body and that doesn't have this issue.

Kit-p commented 2 months ago

As of typesense@1.9.0-4, there is another workaround that does not require switching to multi_search. You may reference this commit for details. Thank you @jasonbosco.

Usage example:

import qs from "qs";
import { Platform } from "react-native";
import Typesense from "typesense";

const client = new Typesense.Client({
    ...your_other_configs,
    // * Add the following to your client initialization
    ...(Platform.OS === "ios" && parseInt(Platform.Version, 10) >= 17 && {
        paramsSerializer: (params) =>
            qs.stringify(params, { format: "RFC3986" }),
    }),
})

For those interested, this issue is caused by Apple replacing RFC 1738/1808 with RFC 3986 for url encoding since iOS 17, and axios (internally used by this SDK) not using RFC 3986. axios issue link.

jasonbosco commented 2 months ago

@Kit-p Thank you for documenting this, and thank you for helping find the axios-side fix for this.