Skip to content

Commit fc88158

Browse files
committed
work on signURL
1 parent dd33dd7 commit fc88158

6 files changed

Lines changed: 197 additions & 16 deletions

File tree

src/main/java/com/google/gcloud/AuthCredentials.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ private Object readResolve() throws ObjectStreamException {
6262
}
6363
}
6464

65-
private static class ServiceAccountAuthCredentials extends AuthCredentials {
65+
public static class ServiceAccountAuthCredentials extends AuthCredentials {
6666

6767
private static final long serialVersionUID = 8007708734318445901L;
6868
private final String account;
@@ -94,6 +94,14 @@ protected HttpRequestInitializer httpRequestInitializer(
9494
return builder.build();
9595
}
9696

97+
public String account() {
98+
return account;
99+
}
100+
101+
public PrivateKey privateKey() {
102+
return privateKey;
103+
}
104+
97105
@Override
98106
public int hashCode() {
99107
return Objects.hash(account, privateKey);
@@ -187,7 +195,7 @@ public static AuthCredentials createApplicationDefaults() throws IOException {
187195
return new ApplicationDefaultAuthCredentials();
188196
}
189197

190-
public static AuthCredentials createFor(String account, PrivateKey privateKey) {
198+
public static ServiceAccountAuthCredentials createFor(String account, PrivateKey privateKey) {
191199
return new ServiceAccountAuthCredentials(account, privateKey);
192200
}
193201

src/main/java/com/google/gcloud/storage/Cors.java

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -53,14 +53,10 @@ public Bucket.Cors apply(Cors cors) {
5353
};
5454

5555
private final Integer maxAgeSeconds;
56-
private final ImmutableList<Method> methods;
56+
private final ImmutableList<HttpMethod> methods;
5757
private final ImmutableList<Origin> origins;
5858
private final ImmutableList<String> responseHeaders;
5959

60-
public enum Method {
61-
ANY, GET, HEAD, PUT, POST, DELETE
62-
}
63-
6460
public static final class Origin implements Serializable {
6561

6662
private static final long serialVersionUID = -4447958124895577993L;
@@ -118,7 +114,7 @@ public String value() {
118114
public static final class Builder {
119115

120116
private Integer maxAgeSeconds;
121-
private ImmutableList<Method> methods;
117+
private ImmutableList<HttpMethod> methods;
122118
private ImmutableList<Origin> origins;
123119
private ImmutableList<String> responseHeaders;
124120

@@ -129,7 +125,7 @@ public Builder maxAgeSeconds(Integer maxAgeSeconds) {
129125
return this;
130126
}
131127

132-
public Builder methods(Iterable<Method> methods) {
128+
public Builder methods(Iterable<HttpMethod> methods) {
133129
this.methods = methods != null ? ImmutableList.copyOf(methods) : null;
134130
return this;
135131
}
@@ -160,7 +156,7 @@ public Integer maxAgeSeconds() {
160156
return maxAgeSeconds;
161157
}
162158

163-
public List<Method> methods() {
159+
public List<HttpMethod> methods() {
164160
return methods;
165161
}
166162

@@ -217,10 +213,10 @@ Bucket.Cors toPb() {
217213
static Cors fromPb(Bucket.Cors cors) {
218214
Builder builder = builder().maxAgeSeconds(cors.getMaxAgeSeconds());
219215
if (cors.getMethod() != null) {
220-
builder.methods(transform(cors.getMethod(), new Function<String, Method>() {
216+
builder.methods(transform(cors.getMethod(), new Function<String, HttpMethod>() {
221217
@Override
222-
public Method apply(String name) {
223-
return Method.valueOf(name.toUpperCase());
218+
public HttpMethod apply(String name) {
219+
return HttpMethod.valueOf(name.toUpperCase());
224220
}
225221
}));
226222
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
* Copyright 2015 Google Inc. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.gcloud.storage;
18+
19+
/**
20+
*
21+
*/
22+
public enum HttpMethod {
23+
GET, HEAD, PUT, POST, DELETE
24+
}

src/main/java/com/google/gcloud/storage/StorageService.java

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,19 @@
1616

1717
package com.google.gcloud.storage;
1818

19+
import static com.google.common.base.MoreObjects.firstNonNull;
1920
import static com.google.common.base.Preconditions.checkArgument;
2021
import static com.google.common.base.Preconditions.checkNotNull;
2122

2223
import com.google.common.collect.ImmutableList;
24+
import com.google.gcloud.AuthCredentials.ServiceAccountAuthCredentials;
2325
import com.google.gcloud.Service;
2426
import com.google.gcloud.spi.StorageRpc;
2527

28+
import org.joda.time.DateTime;
29+
2630
import java.io.Serializable;
31+
import java.net.URL;
2732
import java.util.Arrays;
2833
import java.util.Collections;
2934
import java.util.LinkedHashSet;
@@ -407,6 +412,139 @@ public static Builder builder() {
407412
}
408413
}
409414

415+
/**
416+
* A request for signing a URL.
417+
*/
418+
class SignUrlRequest implements Serializable {
419+
420+
private final Blob blob;
421+
private final HttpMethod httpMethod;
422+
private final Long expiration;
423+
private final boolean includeContentType;
424+
private final boolean includeMd5;
425+
private final String headers;
426+
private final ServiceAccountAuthCredentials authCredentials;
427+
428+
public static class Builder {
429+
430+
private Blob blob;
431+
private HttpMethod httpMethod;
432+
private long expiration;
433+
private boolean includeContentType;
434+
private boolean includeMd5;
435+
private String headers;
436+
private ServiceAccountAuthCredentials authCredentials;
437+
438+
private Builder() {}
439+
440+
public Builder blob(Blob blob) {
441+
this.blob = blob;
442+
return this;
443+
}
444+
445+
/**
446+
* The HTTP method to be used with the signed URL.
447+
*/
448+
public Builder httpMethod(HttpMethod httpMethod) {
449+
this.httpMethod = httpMethod;
450+
return this;
451+
}
452+
453+
/**
454+
* Sets expiration time for the URL.
455+
* Defaults to one day.
456+
*/
457+
public Builder expiration(long expiration) {
458+
this.expiration = expiration;
459+
return this;
460+
}
461+
462+
/**
463+
* Indicate if signature should include the blob's content-type.
464+
* If {@code true} users of the signed URL should include
465+
* the same content-type with their request.
466+
*/
467+
public Builder includeContentType(boolean includeContentType) {
468+
this.includeContentType = includeContentType;
469+
return this;
470+
}
471+
472+
/**
473+
* Indicate if signature should include the blob's md5.
474+
* If {@code true} users of the signed URL should include it with their requests.
475+
*/
476+
public Builder includeMd5(boolean includeMd5) {
477+
this.includeMd5 = includeMd5;
478+
return this;
479+
}
480+
481+
/**
482+
* If headers are provided, the server will check to make sure that the client
483+
* provides matching values.
484+
* For information about how to create canonical headers for signing,
485+
* see <a href="https://cloud.google.com/storage/docs/access-control#About-CanonicalExtensionHeaders">About Canonical Extension Headers</a>.
486+
*/
487+
public Builder canonicalizedExtensionHeaders(String headers) {
488+
this.headers = headers;
489+
return this;
490+
}
491+
492+
/**
493+
* The service account credentials for signing the URL.
494+
*/
495+
public Builder serviceAccountAuthCredentials(ServiceAccountAuthCredentials authCredentials) {
496+
this.authCredentials = authCredentials;
497+
return this;
498+
}
499+
500+
public SignUrlRequest build() {
501+
return new SignUrlRequest(this);
502+
}
503+
}
504+
505+
private SignUrlRequest(Builder builder) {
506+
blob = checkNotNull(builder.blob);
507+
httpMethod = builder.httpMethod;
508+
expiration = firstNonNull(builder.expiration, new DateTime().plusDays(1).getMillis());
509+
includeContentType = builder.includeContentType; // verify blob has content-type
510+
includeMd5 = builder.includeMd5; // verify blob has md5
511+
authCredentials = builder.authCredentials; // default if null
512+
headers = builder.headers;
513+
}
514+
515+
public Blob blob() {
516+
return blob;
517+
}
518+
519+
public HttpMethod httpMethod() {
520+
return httpMethod;
521+
}
522+
523+
public String canonicalizedExtensionHeaders() {
524+
return headers;
525+
}
526+
527+
public long expiration() {
528+
return expiration;
529+
}
530+
531+
public ServiceAccountAuthCredentials authCredentials() {
532+
return authCredentials;
533+
}
534+
535+
public boolean includeContentType() {
536+
return includeContentType;
537+
}
538+
539+
public boolean includeMd5() {
540+
return includeMd5;
541+
}
542+
543+
public static Builder builder() {
544+
return new Builder();
545+
}
546+
}
547+
410548
/**
411549
* Create a new bucket.
412550
*
@@ -528,4 +666,14 @@ public static Builder builder() {
528666
* @throws StorageServiceException upon failure
529667
*/
530668
BlobWriteChannel writer(Blob blob, BlobTargetOption... options);
669+
670+
/**
671+
* Generates a signed URL for a blob.
672+
* If you have a blob that you want to allow access to for a set
673+
* amount of time, you can use this method to generate a URL that
674+
* is only valid within a certain time period.
675+
* This is particularly useful if you don't want publicly
676+
* accessible blobs, but don't want to require users to explicitly log in.
677+
*/
678+
URL signUrl(SignUrlRequest request);
531679
}

src/main/java/com/google/gcloud/storage/StorageServiceImpl.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
import static com.google.gcloud.spi.StorageRpc.Option.IF_SOURCE_METAGENERATION_MATCH;
3030
import static com.google.gcloud.spi.StorageRpc.Option.IF_SOURCE_METAGENERATION_NOT_MATCH;
3131
import static java.net.HttpURLConnection.HTTP_NOT_FOUND;
32-
import static java.util.concurrent.Executors.callable;
3332

3433
import com.google.api.services.storage.model.StorageObject;
3534
import com.google.common.base.Function;
@@ -47,6 +46,7 @@
4746
import com.google.gcloud.spi.StorageRpc.Tuple;
4847

4948
import java.io.Serializable;
49+
import java.net.URL;
5050
import java.util.Arrays;
5151
import java.util.List;
5252
import java.util.Map;
@@ -429,6 +429,12 @@ public BlobWriteChannel writer(Blob blob, BlobTargetOption... options) {
429429
return new BlobWriterChannelImpl(options(), blob, optionsMap);
430430
}
431431

432+
@Override
433+
public URL signUrl(SignUrlRequest request) {
434+
// todo: implement and add test
435+
return null;
436+
}
437+
432438
private Map<StorageRpc.Option, ?> optionMap(Long generation, Long metaGeneration,
433439
Iterable<? extends Option> options) {
434440
return optionMap(generation, metaGeneration, options, false);

src/test/java/com/google/gcloud/storage/CorsTest.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
import static org.junit.Assert.assertEquals;
2020

2121
import com.google.common.collect.ImmutableList;
22-
import com.google.gcloud.storage.Cors.Method;
2322
import com.google.gcloud.storage.Cors.Origin;
2423

2524
import org.junit.Test;
@@ -39,7 +38,7 @@ public void testOrigin() {
3938
public void corsTest() {
4039
List<Origin> origins = ImmutableList.of(Origin.any(), Origin.of("o"));
4140
List<String> headers = ImmutableList.of("h1", "h2");
42-
List<Method> methods = ImmutableList.of(Method.ANY);
41+
List<HttpMethod> methods = ImmutableList.of(HttpMethod.ANY);
4342
Cors cors = Cors.builder()
4443
.maxAgeSeconds(100)
4544
.origins(origins)

0 commit comments

Comments
 (0)