I have a set of API calls that go through Azure APIM to reach our backend. All but one of the calls function as they should, given that the subscription key is included. However the function below, despite having the subscription key assigned in the header section, always results in a 401: access denied, missing subscription key
. To keep the post neat, I will exclude the extra types because they will quickly clutter the post, and I don’t believe they are the cause.
export const webApiConfig: WebApiConfig = {
endpointUrl: process.env.REACT_APP_WEBAPI_ENDPOINT as string,
subscriptionKey: process.env.REACT_APP_WEBAPI_GATEWAY_SUBSCRIPTION_KEY as string,
};
export const trainProjectAsync = async (projectName: string): Promise<NluTrainingState> => {
try {
// Build the request url and config
const url: string = `${webApiConfig.endpointUrl}/Nlu/${projectName}/Train`;
const token = await getToken();
const requestConfig: AxiosRequestConfig = {
headers: {
Authorization: token,
"Content-Type": "application/json",
"Ocp-Apim-Subscription-Key": webApiConfig.subscriptionKey,
},
signal: new AbortController().signal,
};
// Perform the POST request
const response = await axios.post<NluTrainingState>(url, requestConfig);
return response.data satisfies NluTrainingState;
} catch (error) {
// check whether the error is an axios error or a stock error.
if (axios.isAxiosError(error)) {
throw new Error(`API call axios malfunction code: ${error.code} ${JSON.stringify(error.response)}`);
} else {
throw new Error(`API call stock malfunction, reason: ${error}`);
}
}
};
This is the function that it’s supposed to hit via the APIM (and testing it via postman or in swagger shows that this function works as it should)
[Authorize]
[HttpPost("{projectName}/Train")]
[Produces("application/json")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public async Task<ActionResult<NluTrainingStateDto>> TrainAsync(string projectName)
{
try
{
// Launch a training job.
NluTrainingStateDto result = await _nluService.TrainAsync(projectName);
// Return the correct status based on whether the request was a success.
if (result != null)
{
return Ok(result);
}
else
{
return NotFound();
}
}
catch (ServiceAccessException serviceEx)
{
// TODO: add logging
IError error = _errorFactory.CreateError(ErrorCode.ControllerNotServiced, _exceptionResourceManager.GetString("ConnectionNotServicedExc")!);
ControllerNotServicedException _controllerEx = new(error, serviceEx);
return StatusCode((int)HttpStatusCode.InternalServerError, $"Internal Server Error: {_controllerEx.Message}");
}
}
I’ve tried to make the request with four different methods, POST
, PATCH
, PUT
and GET
. All of them fail except for GET
, but I believe it breaks convention to use GET
for this request and am saving this as a last resort. I should note that this particular function used to work as a POST
request before