“(403) Forbidden” when trying to send an image to

2019-08-18 16:25发布

I am having issues with implementing a custom AutoML model in a .NET web app that allows sending images via the REST API to be recognized. I keep getting errors.

The remote server returned an error: (403) Forbidden.

I have an image and converted it into a string of bytes called imageBytesString and have created the jsonRequest object like this:

string jsonRequest = "{\"payload\":{\"image\":{\"imageBytes\":\"" + imageBytesString + "\"},}}";`

Then I'm doing a POST request like follows:

WebRequest request = WebRequest.Create(@"https://automl.googleapis.com/v1beta1/projects/PROJECT_ID/locations/us-central1/models/MODEL_ID:predict");
request.Method = "POST";
request.ContentType = "application/json";
request.Headers.Add("Authorization", "Bearer GCLOUD_ACCESS_TOKEN");

using (var streamWriter = new StreamWriter(request.GetRequestStream()))
{
    streamWriter.Write(jsonRequest);
}

Then when it hits request.GetResponse(); if gives me the above error with no other information.

For reference, these are the snippets taken from the bottom of the PREDICT page on my custom AutoML model:

request.json:

{
  "payload": {
    "image": {
      "imageBytes": "YOUR_IMAGE_BYTE"
    },
  }
}

Execute the request:

curl -X POST -H "Content-Type: application/json" \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  https://automl.googleapis.com/v1beta1/projects/PROJECT_ID/locations/us-central1/models/MODEL_ID:predict -d @request.json

Thanks

3条回答
女痞
2楼-- · 2019-08-18 17:01

A better solution is to access the Auto ML endpoint only from within the same project (then you won't need access tokens).

To access the endpoint from outside of the project, use an API gateway such as APIGEE or AppEngine -- those give you much better controls

查看更多
【Aperson】
3楼-- · 2019-08-18 17:03

I was finally able to get it working.

There were 2 issues that needed to be fixed for it to work.

Firstly; for some reason, when I initially created the service account and entered the command gcloud auth activate-service-account --key-file="[/PATH/TO/KEY/FILE.json], it told me that it worked and the service account was added to the gcloud auth list list. But upon checking again, it wasn't there so I ran it again.

Secondly; I was getting the access token with the following command:

gcloud auth application-default print-access-token

Instead, I tried using the access token received with the following command:

gcloud auth print-access-token

(Without application-default) in there.

After I had done both those things, I am now able to successfully send an image request and receive the prediction response.

But it seems I still have to get a new access token every hour though... But that's another issue I suppose.

查看更多
smile是对你的礼貌
4楼-- · 2019-08-18 17:12

The curl request you reference passes an access token in the header using the gcloud auth application-default print-access-token command. This produces a new token every time it is ran. The token has an expiration time, typically 3600 seconds. You can check that yourself by running: curl https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=GCLOUD_ACCESS_TOKEN. This will return a payload including a "expires_in" field. So, passing the token as a GCLOUD_ACCESS_TOKEN environment variable will result in a 403 error after it expires. What you should do instead is create a service account with the correct permissions, download a json with its credentials and set GOOGLE_APPLICATION_CREDENTIALS to the json's path. Check here under Download credentials for an example in .NET.

查看更多
登录 后发表回答