I want to use Java 11 HttpClient and send header first, check response and if response is OK then send the body.
How can I send header only?
this is my current code:
HttpClient httpClient = HttpClient.newBuilder()
.version(HttpClient.Version.HTTP_2)
.followRedirects(HttpClient.Redirect.NORMAL)
.connectTimeout(Duration.ofSeconds(10))
.authenticator(Authenticator.getDefault())
.build();
HttpRequest httpRequest = HttpRequest.newBuilder("someEndpoint)
.header(CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.header(AUTHORIZATION, "someApiKey)
.build();
HttpResponse<String> httpResponse = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString());
However with such httpResponse I understand I send the body.
By default, the header comes first in requests.
What you asked is, The first request with header and then with a body are two different requests. A single request can't be broken this way.
If you are talking about, Http HEAD method usage, then
The HEAD method asks for a response identical to that of a GET request, but without the response body.
The HTTP HEAD method requests the headers that would be returned if the HEAD request's URL was instead requested with the HTTP GET method. For example, if a URL might produce a large download, a HEAD request could read its Content-Length header to check the file size without actually downloading the file.
an example to use HEAD method:-
var httpClient: HttpClient = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(10))
.build();
var requestHead = HttpRequest.newBuilder()
.method("HEAD", HttpRequest.BodyPublishers.noBody())
.uri(URI.create("https://www.test.com"))
.build();
val httpResponse = httpClient.send(requestHead, BodyHandlers.discarding());
HttpHeaders headers = response.headers();
headers.map().forEach((key, values) -> {
System.out.printf("%s: %s%n", key, values);
});
Related
I am trying to make a GET request to a certain URL and get some data that I am going to use inside a Java servlet. This is the code I am using:
final HttpClient httpClient = HttpClient.newBuilder()
.version(HttpClient.Version.HTTP_2)
.build();
String httpPath = "http://path/to/the/thirdparty/service";
HttpRequest httpRequest = HttpRequest.newBuilder()
.GET()
.uri(URI.create(httpPath))
.build();
HttpResponse httpResponse = null;
try {
httpResponse = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString());
} catch (InterruptedException e) {
response.getWriter().println(e.getMessage());
}
response.setContentType("application/json");
PrintWriter out = response.getWriter();
out.println(httpResponse.body().toString());
This works perfectly and gives the desired output when I run the code from inside a standalone class inside it's main method. However, when I run this from the servelet, I can't produce the output. The response code is 200, however the content is missing with a curl error:
* transfer closed with outstanding read data remaining
* Closing connection 0
curl: (18) transfer closed with outstanding read data remaining
To see whether the length of the data is the problem, I hardcoded the output that is expected from the third party response (and commented out the call from httpClient), that gets sent out in the response correctly when I make a curl request to the servlet. Any help is much appreciated.
I have below API which returns back the access_token.
POST https://idcs-xxxxxxxxxbf08128c3d93a19c.identity.c9dev2.oc9qadev.com/oauth2/v1/token
in header content-type is application/x-www-form-urlencoded. also in body it contains below parameter.
I send user name and password and it is secured with basic authentication. It provides access_token when I call from postman. also it provides output when I consume using HttpUrlConnection
url = new URL(tokenURL);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
connection.setRequestProperty("Authorization", auth);
connection.setRequestProperty("Accept", "application/json");
OutputStream os = connection.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os, "UTF-8");
osw.write("grant_type=client_credentials&scope=" + scope);
The above code is working properly. But when I use jersey it gives 415 error. I am using below code.
String user="idcs-oda-zzzxxxxxf93560b94eb8a2e2a4c9aac9a3ff-t0_APPID";
String password="xxxxxxx-6f71-4af2-b5cc-9110890d1456";
String scope = "https://idcs-oda-xxxxxxxxxxxxxxxxe2a4c9aac9a3ff-t0.data.digitalassistant.oci.oc-test.com/api/v1";
String tokenURL = "https://idcs-xxxxxxxxxxxxxxxx28c3d93a19c.identity.c9dev2.oc9qadev.com/oauth2/v1/token";
HttpAuthenticationFeature feature= HttpAuthenticationFeature
.basicBuilder()
.nonPreemptive()
.credentials(user,password)
.build();
ClientConfig clientConfig = new ClientConfig();
clientConfig.register(feature);
Client client = ClientBuilder.newClient(clientConfig);
WebTarget webTarget= client.target(tokenURL);
PostDetails post= new PostDetails("client_credentials",scope); //Bean class to assign body parameter
Response response= webTarget.request()
.header("Content-Type", "application/x-www-form-urlencoded")
.post(Entity.json(post));
System.out.println(response);
Can somebody tell me what mistake I am doing in Response line.
You need to set your Accept on the request method:
Response response= webTarget.request(MediaType.APPLICATION_JSON)
.header("Content-Type", "application/x-www-form-urlencoded")
.post(Entity.json(post));
You also need to ensure that if your API accepts application/x-www-form-urlencoded content, that is what you are sending.
Currently, you are sending application/json content based on your usage of Entity.json(post).
I don't know what type is assigned to post, but you need to figure out how to convert it either to a Form or a MultiValuedMap<String,String>, and then use the form method on Entity to submit your content.
Response response= webTarget.request(MediaType.APPLICATION_JSON)
.header("Content-Type", "application/x-www-form-urlencoded")
.post(Entity.form(postForm)); //assuming postForm typed as Form or MultiValuedMap<String,String>
Taking a guess regarding post, creating postForm as a MultiValuedMap<String,String> may be as simple as the following (which you would place prior to your request, of course).
MultiValuedMap<String,String> postForm = new MultiValuedHashMap<>();
postForm.add("client_credentials",scope);
What you need is:
Response response= webTarget.request()
.accept("application/json") // Accept field from header of request
.header("Content-Type", "application/x-www-form-urlencoded") //manually set content-tyoe
.post(Entity.entity(input, MediaType.TEXT_PLAIN)); // request body
The best way to see what is Jersey actually is sending is to register logger, and log network. For example:
clientConfig.register(
new LoggingFeature(
new Slf4jLogger(this.getClass().getName(), null)));
where Slf4jLogger is from org.apache.cxf:cxf-core.
I am try to do POST REQUEST to api, let say the API will return a response header in thailand character 10,000 บาท. after i do the request the response i am getting the header value is 10,000 à¸à¸²à¸.
Here is the code:
RequestSpecification httpRequest = RestAssured.given().header(HeaderKey.appId,header.getAppId());
Response response = httpRequest.post(uri);
String errMessage = response.header("key-to-value-i-want");
System.out.println(errMessage);
what's missing from my code? Thanks you
I'm sending an http get/head request using Apache HttpClient 4.x. I'm sending a request with a url like "http://example.com/getAccessToken". I'm expecting the response to be a redirect url with parameters in the returned url like "http://redirecturl.com/?code=accessTokenStuff". I want to be able to parse the response redirect url parameters, i.e. I want to get "accessTokenStuff". How can I do that?
HttpClient client = new DefaultHttpClient();
HttpHead request = new HttpHead(authUrl);
HttpResponse response = client.execute(request);
System.out.println(response.getStatusLine().getStatusCode());//returns 200
request.releaseConnection();
In a nutshell: what I want is executing an original url and then getting the result which is another url that has a parameter called "code". Then I want to get the value of that parameter.
EDIT:
I also tried this but it returns the same original URL
DefaultHttpClient client = new DefaultHttpClient();
HttpParams params = client.getParams();
HttpClientParams.setRedirecting(params, false);
HttpGet request = new HttpGet(authUrl);
HttpResponse response = client.execute(request);
String location = response.getLastHeader("Location").getValue();//returns same original url
System.out.println(location);
request.releaseConnection();
Setting HttpClientParams.setRedirecting(params, true); return null
Http response do not take a form of a "redirect url". Redirect and response are both different (but related) concepts. Redirect usually means "get your response from this address instead of original one".
Having said this, you can prevent HttpClient from following a redirect, see this answer: How to prevent apache http client from following a redirect
When your HttpClient is not following the redirect, you can inspect the 'Location:' header of its response, eg:
HeaderIterator iterator = httpResponse.headerIterator("Location");
while(iterator.hasNext()) {
Header header = iterator.nextHeader();
String redirectUrl = header.getValue();
}
When communicating with http to http://forecast.weather.gov/zipcity.php I need to obtain the URL that is generated from a request.
I have printed out the headers and their values from the http response message but there is no location header. How can I obtain this URL? (I'm using HttpClient)
It should be similar to:
HttpClient client = new DefaultHttpClient();
HttpParams params = client.getParams();
HttpClientParams.setRedirecting(params, false);
HttpGet method = new HttpGet("http://forecast.weather.gov/zipcity.php?inputstring=90210");
HttpResponse resp = client.execute(method);
String location = resp.getLastHeader("Location").getValue();
EDIT: I had to make a couple minor tweaks, but I tested and the above works.