I would like to ADD a ACL to a Google Storage object using the Json API from appengine. I have tried the following code, however I get a 400 response with no details. I am not using the java-client-libraries, however I am willing to try. Below is my code:
public static void updateACL(String bucket, String object,
List<String> emails) {
try {
ArrayList scopes = new ArrayList();
scopes.add("https://www.googleapis.com/auth/devstorage.full_control");
AppIdentityService appIdentity = AppIdentityServiceFactory
.getAppIdentityService();
AppIdentityService.GetAccessTokenResult accessToken = appIdentity
.getAccessToken(scopes);
// The token asserts the identity reported by
// appIdentity.getServiceAccountName()
logger.log(Level.WARNING, "bucket: "+bucket+" object: "+object+ " email: "+emails.get(0));
JSONObject request = new JSONObject();
request.put("entity", "user-" + emails.get(0));
request.put("roles", "READER");
URL url = new URL("https://www.googleapis.com/storage/v1beta1/b/"
+ bucket + "/o/"+object+"/acl?key=" + API_KEY);
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.addRequestProperty("Content-Type", "application/json");
connection.addRequestProperty("Authorization", "OAuth "
+ accessToken.getAccessToken());
String urlParameters = "bucket=" + bucket + "&object=" + object;
OutputStreamWriter writer = new OutputStreamWriter(
connection.getOutputStream());
request.write(writer);
writer.close();
logger.log(Level.WARNING, connection.getResponseMessage());
logger.log(Level.WARNING,
String.valueOf(connection.getResponseCode()));
if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
// Note: Should check the content-encoding.
// JSONTokener response_tokens = new
// JSONTokener(connection.getInputStream());
// JSONObject response = new JSONObject(response_tokens);
// return (String) response.get("id");
return;
} else {
Scanner s;
s = new Scanner(connection.getErrorStream());
s.useDelimiter("\\Z");
String response = s.next();
s.close();
throw new Exception(connection.getResponseCode()+" "+connection.getResponseMessage()+
response);
}
} catch (Exception e) {
logger.log(Level.WARNING, "exception: "+e.getMessage());
}
}
The response I get is a 400, but the details are not helpful at all.
“error”: {
“errors”: [
{
“domain”: “global”,
“reason”: “required”,
“message”: “Required”
}
],
“code”: 400,
“message”: “Required”
}
}
I suspect there’s a tiny bug or two in your code. In this particular instance it looks like you are sending roles when the JSON api expects role.
One thing I find helpful for debugging is to compare what my code is sending over the wire with the HTTP request the Google APIs explorer generates.
Authorize requests using OAuth 2.0button.bucket,object,entityandrolefields.You should see the resulting HTTP request and response.
Request:
Response:
Now make sure the request you are sending over the wire looks the same as this one.