Cannot custom headers in webpage when call external API (outside HubSpot)

I created a webpage in HubSpot and used Fetch to call external API (outside HubSpot).

Unfortunately, I discovered the below problems:

1. The custom headers (e.g. adding ‘Authorization’ variable) cannot be passed to external API

2. Even the ‘mode’ property in “Fetch” is set to ‘no-cors’, but it still returned CORS error. It looks like the ‘mode’ property is still ‘cors’.

The coding is as follows:

fetch(“https://external_domain/api”, {

method: ‘GET’,

mode: ‘no-cors’,

headers: {

‘Content-Type’: ‘application/x-www-form-urlencoded’,

‘Authorization’: ‘abc’

},

})

.then(response => {

console.log(response.data);

})

Do you know how to solve these problems in HubSpot page? Thanks

Hi @team_mc,

I think because you’re using application/x-www-form-urlencoded (as opposed to application/json; are you sure you don’t want json?) your request is a simple request and therefore doesn’t trigger a preflight check. You don’t need an authorisation header or mode to make a simple request so you can remove them.

With application/x-www-form-urlencoded form data is sent as a long query string so you can use query parameters like so: https://external_domain/api?name=ferret&color=purple

Hi @piersg

Thank you for your reply. Actually, I tried to using application/json before but also fail.

Btw, the external AP requires ‘authorisation’ (token) in the request header and it is not allowed to use query parameters to pass the authorization (token). Thanks!

Can you link to the documentation of the API you’re trying to access please?

Sorry, I cannot share the link because you need to login to get token to access. Thanks!

@WendyGoh @piersg

I shared the coding in the post. What other information you needed? Error Message?

If yes, the return message is as follows:

  1. Request Method: GET
  2. Status Code: 401
  3. Remote Address: <external_api_IP>:443
  4. Referrer Policy: no-referrer-when-downgrade

I don’t know why no CORS error today (I have NOT updated my coding). But the custom request headers are still cannot pass to external API. I am sure that my login information is correct.

I think we need to know what kind of authorization the API is asking for. I imagine it’s an API key, not Bearer authentication, so try the x-api-key first (delete the other one):

fetch("https://external_domain/api", {
 method: 'GET',
 credentials: 'include',
 headers: {
 'Content-Type': 'application/x-www-form-urlencoded',
 // if bearer token
 'Authorization': 'Bearer ' + [your token]
 // else if X-API-KEY
 'X-API-KEY': [your key]
 },
})
.then(response => {
 console.log(response.data);
})

mode: "no-cors" only allows a limited set of headers in the request: Accept, Accept-Language, Content-Language, and Content-Type. Hopefully the above works.

Thank you for your reply! I use Bearer authentication. After testing by your coding, the result is as follows:

If set mode: “no-cors”, return below error:

GET’https://external_domain/api’ net::ERR_ABORTED 401

Response header:

  1. Request Method: GET
  2. Status Code: 401
  3. Remote Address: <external_api_IP>:443
  4. Referrer Policy: no-referrer-when-downgrade

If set mode: “cors”, return below error:

“Access to fetch at ‘https://external_domain/api’ from origin ‘https://hubspot-demo.mydomain.com’ has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: The value of the ‘Access-Control-Allow-Origin’ header in the response must not be the wildcard ‘*’ when the request’s credentials mode is ‘include’.”

No returen response header.

Thanks!

And what do you get if you use “credentials” instead of “mode”?

I updated the coding as follows:

fetch(“https://external_domain/api”, {
method: ‘GET’,
mode: ‘include’,
headers: {
‘Content-Type’: ‘application/x-www-form-urlencoded’,
// if bearer token
Authorization’: 'Bearer ’ + [my token]
},
})
.then(response => {
console.log(response.data);
})

And returned the below errors:

Uncaught (in promise) TypeError: Failed to execute ‘fetch’ on ‘Window’: The provided value ‘include’ is not a valid enum value of type RequestMode.

Thanks!

Because it has to be credentials: 'include’ not “mode”

@piersg From your reply - “And what do you get if you use “credentials” instead of “mode”?” , you suggested to change “credentials” to “mode”, right? If not, what do you mean? Could you post the whole coding? Thanks!

I meant change the property ‘mode’ for the property ‘credentials’.

fetch("https://external_domain/api", {
 method: 'GET',
 credentials: 'include',
 headers: {
 'Content-Type': 'application/x-www-form-urlencoded',
 'Authorization': 'Bearer ' + [your token]
 }
})
.then(response => {
 console.log(response.data);
})

@piersg

Updated the coding as your coding, and return the below error:

Access to fetch at “https://external_domain/api” from origin ‘https://hubspot-demo.mydomain.com’ has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: The value of the ‘Access-Control-Allow-Origin’ header in the response must not be the wildcard ‘*’ when the request’s credentials mode is ‘include’.

Thanks!

Ok, that would suggest the Access-Control-Allow-Origin is set to wildcard (*) i.e. code from any origin can access the API. As it states, you can’t have credentials when that is set to wildcard. What do you get if you remove credentials?

fetch("https://external_domain/api", {
 method: 'GET',
 headers: {
 'Content-Type': 'application/x-www-form-urlencoded',
 'Authorization': 'Bearer ' + [your token]
 }
})
.then(response => {
 console.log(response.data);
})

@piersg

Updated the coding as your coding, and return the below error in
Header General:

  1. Request URL: https://external_domain/api
  2. Request Method: OPTIONS
  3. Status Code: 204

And no response data

Thanks!

Well 204 error is saying that the server has successfully fulfilled the request and that there is no content to send in the response payload body. So your code works, but there’s nothing being returned from the API.

Hi @piersg I did not update my coding but it works today. Anyways, thank you for your help!

No worries, glad we got there in the end! Could you mark one of the comments as the solution please? Whichever helped the most (maybe this one)?