Im trying to read a text file from AWS S3 via JAVA SDK v2 and send it back to a client via HTTP (using
com.sun.net.httpserver.HttpServer). I want to read the contents as string. But my simple code below doesn't work.
What is the problem? How to fix it?
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
//...
Region region = Region.US_WEST_2;
String bucketName = "file-store";
S3Client s3Client = S3Client.builder().region(region).build();
//...
class GetFileHandlerV2 implements HttpHandler {
@Override
public void handle(HttpExchange he) throws IOException {
GetObjectRequest getObjectRequest = GetObjectRequest.builder()
.bucket(bucketName)
.key(id + "/files/" + id + ".txt")
.build();
OutputStream os = he.getResponseBody();
s3Client.getObject(getObjectRequest, ResponseTransformer.toOutputStream(os));
os.close();
//...
}
}
Here are the errors:
java.io.IOException: response headers not sent yet
at sun.net.httpserver.PlaceholderOutputStream.checkWrap(ExchangeImpl.java:433) ~[jdk.httpserver:?]
at sun.net.httpserver.PlaceholderOutputStream.write(ExchangeImpl.java:448) ~[jdk.httpserver:?]
at java.io.InputStream.transferTo(InputStream.java:772) ~[?:?]
at comcast.labs.objectstore.FileRetriever$GetFileHandlerV2.handle(FileRetriever.java:112) [FileRetriever-1.0.jar:?]
at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:77) [jdk.httpserver:?]
at sun.net.httpserver.AuthFilter.doFilter(AuthFilter.java:82) [jdk.httpserver:?]
at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:80) [jdk.httpserver:?]
at sun.net.httpserver.ServerImpl$Exchange$LinkHandler.handle(ServerImpl.java:692) [jdk.httpserver:?]
at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:77) [jdk.httpserver:?]
at sun.net.httpserver.ServerImpl$Exchange.run(ServerImpl.java:664) [jdk.httpserver:?]
at sun.net.httpserver.ServerImpl$DefaultExecutor.execute(ServerImpl.java:159) [jdk.httpserver:?]
at sun.net.httpserver.ServerImpl$Dispatcher.handle(ServerImpl.java:442) [jdk.httpserver:?]
at sun.net.httpserver.ServerImpl$Dispatcher.run(ServerImpl.java:408) [jdk.httpserver:?]
at java.lang.Thread.run(Thread.java:835) [?:?]
Please, consider reviewing the
HttpExchangedocumentation. It provides the typical sequence of steps in the life-cycle of aHttpExchange.Specifically, it indicates that before writing to the body of the response, using the
OutputStreamreturned bygetResponseBody, the methodsendResponseHeadersmust be invoked in order to actually start sending information to the client. From the javadoc:Following your example, please, try something like this:
You can read the whole information returned by
S3Clientfirst and then wrap it on your handler as well:This second approach will allow you to refactor your code if required, differentiating the logic that has to do with the interaction with S3 from the one related to your HTTP wrapping code.