Is there way to override host header in amazon s3 client? - java

I want to override host header in PutObjectRequest request so I have implemented the following code:
PutObjectRequest request = builder
.bucket(bucket).key(objectKey)
.overrideConfiguration(b -> {
b.putHeader("Host", headers.get("Host"));
b.putHeader("Authorization", headers.get("Authorization"));
}).build();
But I intercepted the request and see that host header differs from that value. The same situation with "Authorization" header
P.S.
I want to implement proxy between client application and S3 compatible storage.

Related

how to create client TGT with java cxf

I'm new to the java rest CXF client. I will make various requests to a remote server, but first I need to create a Ticket Granting Ticket (TGT). I looked through various sources but I could not find a solution. The server requests that I will create a TGT are as follows:
Content-Type: text as parameter, application / x-www-form-urlencoded as value
username
password
I create TGT when I make this request with the example URL like below using Postman. (URL is example). But in the code below, I'm sending the request, but the response is null. Could you help me with the solution?
The example URL that I make a request with POST method using Postman: https://test.service.com/v1/tickets?format=text&username=user&password=pass
List<Object> providers = new ArrayList<Object>();
providers.add(new JacksonJsonProvider());
WebClient client = WebClient.create("https://test.service.com/v1/tickets?format=text&username=user&password=pass", providers);
Response response = client.getResponse();
You need to do a POST, yet you did not specify what your payload looks like?
Your RequestDTO and ResponseDTO have to have getters/setters.
An example of using JAX-RS 2.0 Client.
Client client = ClientBuilder.newBuilder().register(new JacksonJsonProvider()).build();
WebTarget target = client.target("https://test.service.com/v1/tickets");
target.queryParam("format", "text");
target.queryParam("username", "username");
target.queryParam("password", "password");
Response response = target.request().accept(MediaType.APPLICATION_FORM_URLENCODED).post(Entity.entity(yourPostDTO,
MediaType.APPLICATION_JSON));
YourResponseDTO responseDTO = response.readEntity(YourResponseDTO.class);
int status = response.getStatus();
Also something else that can help is if you copy the POST request from POSTMAN as cURL request. It might help to see the differences between your request and POSTMAN. Perhaps extra/different headers are added by postman?
Documentation: https://cxf.apache.org/docs/jax-rs-client-api.html#JAX-RSClientAPI-JAX-RS2.0andCXFspecificAPI
Similar Stackoverflow: Is there a way to configure the ClientBuilder POST request that would enable it to receive both a return code AND a JSON object?

Amazon S3 AWS SDK [Java] - MultiPart Upload how to get a custom header in the http response?

how can I access a custom header from a server response when using TransferManager ?
we have a custom header added in the response from our server, from the client side we use multi part upload with default transfer manager
any suggestion how in how i could hook up it ?
so basically i want to pass over the response from the return response.getAwsResponse(); found in the class: AmazonS3Client on the method
private <X, Y extends AmazonWebServiceRequest> X invoke(Request<Y> request,
HttpResponseHandler<AmazonWebServiceResponse<X>> responseHandler,
String bucket, String key, boolean isAdditionalHeadRequestToFindRegion) {
that response will have the HTTP response from the server containing the custom heather which I'm after, basically is a unique Id send back when the file was 100% completed so than i can manipulate it.
I need to pass over this custom header from the response to the very beginning where I use the transfer manager and the upload.waitForCompletion(),
also i don't want to edit the amazon's,
so does anyone know if there is an interface or some other object which provides me access to it ?
After some debug into the framework I strongly believe that there is no way to have access to the http response when using the TransferManager
for what we are trying to do we need to send an unique id from the server to the client when the file upload is completed and assembled
** therefore if you don't mind in do not use the beauty of the TransferManager you could write "your own TransferMananger" than you will have full control, but again on the client side we don't really want to add custom code but have a standard and simple approach (but that is for my scenario), if you decide to do it manually it can be done I have already tried and works !
So as a alternative we though in send from the server via the eTag, which is not great but will do the job and will keep the client side simple and clean
Any suggestion in how to send this value back in a better way ?
Upload up = tm.upload(bucketName, file.getName(), file);
UploadResult result = (UploadResult) ((UploadImpl) up).getMonitor().getFuture().get();
String uniqueIdFromServer = result.getETag();

Returns HTTP 500 code when accessing resource using HTTPS

I wrote a sample Java REST Client application to access a resource, but it gives the 500 error. Here resource can be accessed through HTTPS only.
Client client = ClientBuilder.newClient();
WebTarget target = client.target("https://<location>").path("<path>");
MultivaluedMap<String, String> formData = new MultivaluedHashMap<String, String>();
formData.add("Amount", "100.00");
formData.add("Currency", "NZD");
formData.add("EmailAddress", "test#gmail.com");
Response response = target.request(MediaType.APPLICATION_FORM_URLENCODED_TYPE).post(Entity.form(formData));
When i invoked the request from Web Browser, it works fine.
What is the problem with my code?
Since Protocol "HTTPS" requires some additional configurations?
http://www.bhaveshthaker.com/24/calling-invoking-secure-restful-web-service-over-https-with-jax-rs-in-java-without-keystore-truststore-information/
For your reference..
Yes, HTTP and HTTPS cannot be used interchangeably. You need different client configuration for same if your server code is using SSL certificate/ user created certificate.

Can I access HTTP header this way?

So I've been trying to create token based authentication in Java EE lately and I tried to sent token via HTTP Header, but failed so many times.
My question : If I have for example #POST response method and I set header via return response statement
return Response.ok(entity).header(HttpHeader.AUTHORIZATION, authToken).build()
Then I invoke other method that was binded to ContainerRequestFilter and in this filter I try to access header via ContainerRequestContext.getHeaderString(HttpHeaders.AUTHORIZATION) then should it work?
Will I get the value from that header that was set in response method? If not then what should I do to get value of this header in filter method?
The Authorization header(or any other header) must be included by the client in each request
Your client should get the token from the server response, keep it in a secure storage and set the Authorization header when performs a request. Then, with RequestContextFilter your server will be able to recover it

Resumable upload to GCS from Android client using `upload_id` for auth

This is from the GCS Access Control documentation on signed URLs and it matches my use case exactly (the resumable upload scenario):
Note: If your users are only uploading resources (writing) to an
access-controlled bucket, you can use the resumable uploads
functionality of Google Cloud Storage, and avoid signing URLs or
requiring a Google account. In a resumable upload scenario, your
(server-side) code authenticates and initiates an upload to Google
Cloud Storage without actually uploading any data. The initiation
request returns an upload ID, which can then be used in a client
request to upload the data. The client request does not need to be
signed because the upload ID, in effect, acts as an authentication
token. If you choose this path, be sure to transmit the upload ID over
HTTPS.
I have a GAE instance which successfully authenticates and initiates a resumable upload to GCS. As expected, GCS returns my GAE server a response:
HTTP/1.1 200 OK
Location: https://www.googleapis.com/upload/storage/v1/b/<my-apps-default-bucket>/o?uploadType=resumable&name=<my-file-name>&upload_id=xa298sd_sdlkj2
Content-Length: 0
The GAE server hands the Android client the URL from the above location and the Android client uses this to try to PUT the file to GCS. Here is the basic code snippet used:
HttpClient client = new DefaultHttpClient();
String url = <URL-returned in Location-Header>; // exactly the URL returned in the GCS response above
Log.v("PUT URL", url);
HttpPut put = new HttpPut(url);
put.addHeader("Content-Type", "<my-file-mime-type>");
// Note that HttpPut adds the `Content_Length` based on the entity added. Doing it by hand will throw an Exception
MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create();
entityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
entityBuilder.addBinaryBody("file", new File("<path-to-my-file>"));
HttpEntity entity = entityBuilder.build();
put.setEntity(entity);
HttpResponse response = client.execute(put);
HttpEntity httpEntity = response.getEntity();
responseMsg = EntityUtils.toString(httpEntity);
Log.v("resultMsg", responseMsg);
Logs show the response from GCS for the above PUT is:
{
"error":{
"errors":[
{
"domain":"global",
"reason":"badRequest",
"message":"Invalid Upload Request"
}
],
"code":400,
"message":"Invalid Upload Request"
}
}
My question is to anyone who has gotten the resumable upload scenario to work for this use case: (1) Client asks server to initiate resumable upload, (2) server initiates upload and gets Location with upload_id, (3) server passes these to client, (4) client uses these to upload file to GCS directly with no additional authentication (no signed URL). Is there something I'm missing? According to the documentation it looks like this approach should be working. Does anyone have pointers or experience that could help me out?
Thanks.

Categories