Skip to content

body is JSON stringified on product projections search with POST #1039

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
benoitvidis opened this issue Apr 15, 2025 · 4 comments
Open

body is JSON stringified on product projections search with POST #1039

benoitvidis opened this issue Apr 15, 2025 · 4 comments
Assignees
Labels
bug Something isn't working Customer issue

Comments

@benoitvidis
Copy link

The POST variant of the product projection search expects the body to be an application/x-www-form-urlencoded string.

By default, providing a valid body leads to errors and / or parameters being omitted, because of the body being stringified by the http middleware.

An simple workaround is to set the headersWithStringBody options:

const client = new ClientBuilder()
  .withProjectKey(projectKey)
  .withMiddleware(createAuthForClientCredentialsFlow(authMiddlewareOptions))
  .withMiddleware(createHttpClient({
    ...httpMiddlewareOptions,
    headersWithStringBody: ['application/x-www-form-urlencoded'],
  }))
  .withUserAgentMiddleware()
  .build()

I suppose this content-type could be added by default.

Also, the documentation refers to a JSON string, which seems to be incorrect.

As a nice to have, is there any chance the sdk could provide a POST search accepting a body as a POJO object with the same type as its GET counterpart rather than having to manually url-encode the body?

@ajimae ajimae self-assigned this Apr 15, 2025
@ajimae ajimae added Customer issue bug Something isn't working labels Apr 15, 2025
@ajimae
Copy link
Contributor

ajimae commented Apr 15, 2025

Hi @benoitvidis

Thanks for reporting this issue, I will take a look right away.

@ajimae
Copy link
Contributor

ajimae commented Apr 15, 2025

This is the intended behaviour. For any string body that needs to be passed on to the platform using the SDK we need to specify the appropriate header using the headersWithStringBody option, it is a feature and not a workaround also.

For the documentation, we will look at it and update it, thanks for pointing it out.

As for the feature request on mapping the a JSON/JS Object to a URL encoded string. I would say I don't know how feasible this request will be, however, we can look into it and see if it's a feature worth implementing in the SDK.

In the mean time you can adapt the below code to match your use case.

const { ClientBuilder } = require('@commercetools/ts-client')

const projectKey = process.env.CTP_PROJECT_KEY
const authMiddlewareOptions = {
  host: 'https://auth.europe-west1.gcp.commercetools.com',
  projectKey,
  credentials: {
    clientId: process.env.CTP_CLIENT_ID,
    clientSecret: process.env.CTP_CLIENT_SECRET,
  },
  fetch,
}

const api = new ClientBuilder()
  .withClientCredentialsFlow(authMiddlewareOptions)
  .withHttpMiddleware({
    host: 'https://api.europe-west1.gcp.commercetools.com',
    httpClient: fetch
  })
  .build()

async function run() {
  return api.execute({
      method: 'POST',
      uri: `/${process.env.CTP_PROJECT_KEY}/product-projections/search`,
      body: new URLSearchParams({
        /**
         * pass your POJO here
         */
        searchParam1: 'value1',
        searchParam2: 'value2',
        searchParam3: 'value3',
      }).toString(),
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
      },
    })
}

const response = await run();
// response will be the result of the search.

Thank you once again.

@benoitvidis
Copy link
Author

Ok, thank you.
I did not think of skipping the request builder and call execute directly.

Still, this is very confusing for the user, as application/json or graphql content types do not need to be specified and I do not see anywhere in the documentation anything related to this feature, nor that it should specifically apply to one particular method of the sdk.

@ajimae
Copy link
Contributor

ajimae commented Apr 16, 2025

I did not think of skipping the request builder and call execute directly.

This is more or less a workaround and not necessarily how the SDK is intended to be used. This is suitable for a one-off action such as search.

Still, this is very confusing for the user, as application/json or graphql content types do not need to be specified

We allow for graphql query as a string and in this case we need to let the SDK know not to stringify it further using this headers. Take a look at this issue.

I do not see anywhere in the documentation anything related to this feature

You are right, in the new (v3) client we haven't added this feature yet to allow for custom headers that accepts string body. Once we get this feature implemented, we will definitely include a docs for it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working Customer issue
Projects
None yet
Development

No branches or pull requests

2 participants