package com.airbnb.airpal.resources; import com.amazonaws.services.s3.AmazonS3; import com.amazonaws.services.s3.model.GetObjectRequest; import com.amazonaws.services.s3.model.ObjectMetadata; import com.google.common.io.ByteStreams; import com.google.inject.Inject; import lombok.val; import javax.inject.Named; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.StreamingOutput; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @Path("/api/s3") public class S3FilesResource { private final AmazonS3 s3Client; private final String outputBucket; @Inject public S3FilesResource( AmazonS3 s3Client, @Named("s3Bucket") String outputBucket) { this.s3Client = s3Client; this.outputBucket = outputBucket; } private String getOutputKey(String fileBaseName) { return "airpal/" + fileBaseName; } @GET @Path("/{filename}") @Produces(MediaType.APPLICATION_OCTET_STREAM) public Response getFile(@PathParam("filename") String filename) { val outputKey = getOutputKey(filename); val getRequest = new GetObjectRequest(outputBucket, outputKey); final val object = s3Client.getObject(getRequest); if (object == null) { return Response.status(Response.Status.NOT_FOUND).build(); } else { ObjectMetadata objectMetadata = object.getObjectMetadata(); Response.ResponseBuilder builder = Response.ok().type(objectMetadata.getContentType()); if (objectMetadata.getContentEncoding() != null) { builder = builder.encoding(objectMetadata.getContentEncoding()); // gzip } return builder.entity(new StreamingOutput() { @Override public void write(OutputStream output) throws IOException, WebApplicationException { try (InputStream objectData = object.getObjectContent()) { ByteStreams.copy(objectData, output); } finally { output.close(); } } }).build(); } } }