Code refactor: CloseableHttpResponse to Resttemplate - java

I tried refactoring my code. After refactoring I am getting null response. Here is my older version of code:
import java.io.IOException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
#Component
public class GenericRestClientImpl implements GenericRestClient {
#Value("${auth.string}")
private String authString;
private static Logger logger = LogManager.getLogger(GenericRestClientImpl.class);
#Override
public String httpPostData(String jsonstr, String posturl) throws IOException {
String result = "";
HttpPost httpPost = new HttpPost(posturl);
httpPost.setEntity(new StringEntity(jsonstr, ContentType.APPLICATION_JSON));
httpPost.addHeader("Content-Type", "application/json");
httpPost.addHeader("Authorization", authString);
System.out.println("JSON to send: " + jsonstr);
logger.info("JSON to send: " + jsonstr);
try (CloseableHttpClient closeableHttpClient = HttpClients.createDefault();
CloseableHttpResponse closeableHttpResponse = closeableHttpClient.execute(httpPost);) {
logger.info("response status code :" + closeableHttpResponse.getStatusLine().getStatusCode());
logger.info("response status line :" + closeableHttpResponse.getStatusLine());
result = EntityUtils.toString(closeableHttpResponse.getEntity());
logger.info("response data :" + result);
return result;
}
}
}
I want to refactor this to the Resttemplate. I have URL as String and JSON as String. How to refactor this? I tried several times but it didn't work. Is it not working because of variable type String?

Related

Apache HTTPClient DigestAuth authorization doesn't work

At the first access to the server, my authorization is successful (although this is not correct). I don’t understand why digest authorization in this code occurs so early.
I'm using the following solution:
import java.io.Serializable;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.*;
import java.util.stream.Collectors;
import org.apache.commons.io.IOUtils;
import org.apache.http.*;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.*;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.conn.ssl.AllowAllHostnameVerifier;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.auth.DigestScheme;
import org.apache.http.impl.client.*;
import org.apache.http.ssl.SSLContextBuilder;
import org.testng.Assert;
import javax.net.ssl.*;
public class SOAPClientApache {
private static final String URL = "https://httpbin.org/digest-auth/auth/user/passwd";
private static final String PASSWORD = "passwd"; //passwd
private static final String USER = "user"; //user
public void run() throws Exception {
HttpGet httpget = new HttpGet(URL);
HttpHost target = new HttpHost(httpget.getURI().getHost(), 443, "https");
CredentialsProvider credsProvider = new BasicCredentialsProvider();
UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(USER, PASSWORD);
credsProvider.setCredentials(
new AuthScope(target.getHostName(), target.getPort()),
credentials);
CookieStore cookieStore = new BasicCookieStore();
//SSL solution
CloseableHttpClient httpclient
= HttpClients.custom().setDefaultCookieStore(cookieStore)
.setDefaultCredentialsProvider(credsProvider).build();
try {
DigestScheme digestAuth = new DigestScheme();
digestAuth.overrideParamter("qop", "auth");
digestAuth.overrideParamter("nc", "0");
digestAuth.overrideParamter("cnonce", DigestScheme.createCnonce());
AuthCache authCache = new BasicAuthCache();
authCache.put(target, digestAuth);
HttpClientContext localContext = HttpClientContext.create();
localContext.setAuthCache(authCache);
CloseableHttpResponse response;
response = httpclient.execute(target, httpget, localContext);
//Массив headers (для тестов)
Header[] headers = response.getAllHeaders();
for (Header header : headers) {
System.out.println(header);
}
System.out.println();
Map<String, String> wwwAuth = Arrays
.stream(response.getHeaders("WWW-Authenticate")[0]
.getElements())
.collect(Collectors.toMap(HeaderElement::getName,
HeaderElement::getValue));
//Выведем наш массивчик чтобы лицезреть
for(Map.Entry<String, String> pair : wwwAuth.entrySet()){
System.out.println(pair.getKey() + " = " + pair.getValue());
}
// the first call ALWAYS fails with a 401
Assert.assertEquals(response.getStatusLine().getStatusCode(), 401);
digestAuth.overrideParamter("opaque", wwwAuth.get("opaque"));
digestAuth.overrideParamter("nonce", wwwAuth.get("nonce"));
digestAuth.overrideParamter("realm", wwwAuth.get("Digest realm"));
Header authenticate = digestAuth.authenticate(credentials, httpget, localContext);
httpget.addHeader(authenticate);
response = httpclient.execute(target, httpget, localContext);
// the 2nd call is the real deal
Assert.assertEquals(response.getStatusLine().getStatusCode(), 200);
System.out.println(IOUtils
.toString(response.getEntity().getContent(), "utf-8"));
} finally {
httpclient.close();
}
}
}
When the program reaches this step:
Map<String, String> wwwAuth = Arrays
.stream(response.getHeaders("WWW-Authenticate")[0]
.getElements())
.collect(Collectors.toMap(HeaderElement::getName,
HeaderElement::getValue));
then "response: HTTP / 1.1 200 OK" and the program exits to exception

Able to hit in postman but not in java

I am not able to get a response from eclipse when integrated in java code. I am able to retrieve the response from postman/insomnia, but not from eclipse. I masked the token and the URL in this image.
My current code is:
public class Test{
public static void main(String[] args) throws ParseException, IOException {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("https://xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
httppost.addHeader("Authorization", "Bearer xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
httppost.addHeader("Accept", "*/*");
httppost.addHeader("Content-type", "multipart/form-data; boundary=X-INSOMNIA-BOUNDARY");
httppost.addHeader("Host","process-workorders-mti64mke4a-uc.a.run.app");
File fileToUse = new File("D:\\firstImage.jpg"); // this is the image I am uoploadin
FileBody data = new FileBody(fileToUse);
MultipartEntity reqEntity = new MultipartEntity();
reqEntity.addPart("mode", new StringBody("api"));
reqEntity.addPart("file", data);
*// seems there is issue here in passing form parameters*
httppost.setEntity(reqEntity);
HttpResponse response = httpclient.execute(httppost);
System.out.println( response ) ;
HttpEntity resEntity = response.getEntity();
System.out.println( resEntity ) ;
System.out.println( EntityUtils.toString(resEntity) );
EntityUtils.consume(resEntity);
httpclient.getConnectionManager().shutdown();
}
}
Below are the imports:
import java.io.File;
import java.io.IOException;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.ParseException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
Tried OKHTTPClient and it worked

How to avoid URIBuilder to encode comma to "%2C" or other characters in query params

I would like to create a URI using apache class org.apache.http.client.utils.URIBuilder and I need to not encode query params to percent-encoding.
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
RequestConfig config = RequestConfig.custom().build();
HttpClientBuilder builder = HttpClientBuilder.create().setDefaultRequestConfig(config);
// URI url = new URI("http://some-website.com/?range=10,20");
// If url is created with the line above the comma "," is not encoded when sending the request
// When you use URIBuilder the comma "," is converted to "%2C"
URIBuilder uribuilder = new URIBuilder("http://some-website.com/");
uribuilder.addParameter("range", "10,20");
URI url = uribuilder.build();
System.out.println("URL => " + url.toString());
HttpHost targetHost = new HttpHost(url.getHost(), url.getPort(), url.getScheme());
HttpClient client = builder.build();
HttpRequestBase req = new HttpPost(url);
HttpResponse httpResponse = client.execute(targetHost, req);
HttpEntity entity = httpResponse.getEntity();
String responseString = EntityUtils.toString(entity, "UTF-8");
System.out.println(responseString);
System.out.println("Finished");
}
}
Is there a way to do that using the URIBuilder class like some flag I don't know?
I would appreciate other suggests (maybe better ways than my code) to accomplish this. But I can't send the characters in query string encoded.
Thanks in advance.

Apache HTTP Client 400 Error

I was Trying to Automate a Web Service and I am passing the XML in the form of a String and later converting it to String Entity and Setting the Entity. But I don't know why it is throwing 400 Error. I am new to WebServices Automation could any please help me on this.
Below is my Code:
package com.WebServices.Automation;
import java.io.IOException;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.junit.Assert;
import org.junit.Test;
public class HTTPClientA {
static String url = "http://www.dneonline.com/calculator.asmx?wsdl";
String xml = "\"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"+
"<soap:Envelope xmlns:soap=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:tem=\"http://tempuri.org/\">\r\n" +
" <soap:Header/>\r\n" +
" <soap:Body>\r\n" +
" <tem:Add>\r\n" +
" <tem:intA>10</tem:intA>\r\n" +
" <tem:intB>20</tem:intB>\r\n" +
" </tem:Add>\r\n" +
" </soap:Body>\r\n" +
"</soap:Envelope>";
#Test
public void main() throws ClientProtocolException, IOException
{
StringEntity stringEntity = new StringEntity(xml);
HttpPost post = new HttpPost(url);
post.setEntity(stringEntity);
HttpClient client = HttpClientBuilder.create().build();
post.setHeader("Content-Type", "text/xml; charset=utf-8");
post.setHeader("SOAPAction", "http://tempuri.org/Add");
HttpResponse res = client.execute(post);
int actualresponse = res.getStatusLine().getStatusCode();
System.out.println(actualresponse);
try
{
Assert.assertEquals(actualresponse, 200);
}
catch (Exception e) {
// TODO: handle exception
}
HttpEntity entity = res.getEntity();
String strResponse = null;
if (entity != null) {
strResponse = EntityUtils.toString(entity);
System.out.println(strResponse);
}
}
}
Your XML is invalid, it start with double quote instead of <?xml, change your assignment to start with:
String xml = "<?xml version ... –

How to POST an authenticated Jenkins job using Java

All:
I need to be able to POST a job to Jenkins using the Jenkins REST API but have not been able to get past authentication. I have been attempting to do this for a few days now and have researched answers on both this site and on the Jenkins site. I have been trying to use the Apache HttpClient with no success (even with preemptive validation). I keep getting error code 403 - forbidden. Has anyone been able to do this successfully? Here is the code that I am working with:
package stackoverflow.question;
import gsafame.sample;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.NameValuePair;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.AuthCache;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.client.BasicAuthCache;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
public class PreEmptiveAuth {
final Logger log = Logger.getLogger(sample.class.getCanonicalName());
private JobData jd;
private CredentialsProvider credpro;
private AuthScope as;
private UsernamePasswordCredentials upc;
private String url;
public PreEmptiveAuth(JobData jd) {
this.jd = jd;
credpro = new BasicCredentialsProvider();
as = new AuthScope(jd.getServer(), 443);
upc = new UsernamePasswordCredentials(jd.getUsername(), jd.getPassword());
credpro.setCredentials(as, upc);
url = String.format("%s:8080/jenkins/job/%s/buildWithParameters", jd.getServer(), jd.getJob());
}
public void runTagJob() throws ClientProtocolException, IOException {
log.entering(this.getClass().getCanonicalName(), "runTagJob");
log.info("Entering runTagJob");
CloseableHttpClient httpclient = HttpClients.custom()
.setDefaultCredentialsProvider(credpro).build();
HttpPost httpPost = new HttpPost(url);
List <NameValuePair> nvps = new ArrayList <NameValuePair>();
nvps.add(new BasicNameValuePair("username", jd.getUsername()));
nvps.add(new BasicNameValuePair("password", jd.getPassword()));
nvps.add(new BasicNameValuePair("apiToken", jd.getToken()));
httpPost.setEntity(new UrlEncodedFormEntity(nvps));
CloseableHttpResponse response2 = httpclient.execute(httpPost);
try {
System.out.println(response2.getStatusLine());
HttpEntity entity2 = response2.getEntity();
// do something useful with the response body
// and ensure it is fully consumed
EntityUtils.consume(entity2);
} finally {
response2.close();
}
log.info("Exiting runTagJob");
log.exiting(this.getClass().getCanonicalName(), "runTagJob");
}
public void runPreTagJob() throws ClientProtocolException, IOException {
log.entering(this.getClass().getCanonicalName(), "runPreTagJob");
log.info("Entering runPreTagJob");
HttpHost targetHost = new HttpHost(jd.getServer(), 8080, "http");
CloseableHttpClient httpclient = HttpClients.custom()
.setDefaultCredentialsProvider(credpro).build();
try {
// Create AuthCache instance
AuthCache authCache = new BasicAuthCache();
// Generate BASIC scheme object and add it to the local auth cache
BasicScheme basicAuth = new BasicScheme();
authCache.put(targetHost, basicAuth);
// Add AuthCache to the execution context
HttpClientContext localContext = HttpClientContext.create();
localContext.setAuthCache(authCache);
HttpPost httpPost = new HttpPost(url);
List <NameValuePair> nvps = new ArrayList <NameValuePair>();
nvps.add(new BasicNameValuePair("username", jd.getUsername()));
nvps.add(new BasicNameValuePair("password", jd.getPassword()));
nvps.add(new BasicNameValuePair("apiToken", jd.getToken()));
httpPost.setEntity(new UrlEncodedFormEntity(nvps));
CloseableHttpResponse response2 = httpclient.execute(targetHost, httpPost, localContext);
try {
System.out.println(response2.getStatusLine());
HttpEntity entity2 = response2.getEntity();
// do something useful with the response body
// and ensure it is fully consumed
EntityUtils.consume(entity2);
} finally {
response2.close();
}
} finally {
httpclient.close();
}
log.info("Exiting runPreTagJob");
log.exiting(this.getClass().getCanonicalName(), "runPreTagJob");
}
}
The JobData object that gets passed into this class contains information like username, password, server, and job information. I hope this helps!
After researching on several sites, I managed to piece enough information together to come up with a solution. I am using older HTTP authentication code that is in some instances deprecated - but it works when nothing else would. If anyone has a better solution, I would be interested in seeing it. Anyway, here it is:
Main Class:
package stackoverflow.answer;
import java.util.List;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
public class sample {
public static void main(String[] args) throws Exception {
final Logger log = Logger.getLogger(sample.class.getCanonicalName());
JobData jd = new JobData();
Scanner input = new Scanner(System.in);
try {
System.out.print("What is your user name? ");
jd.setUsername(input.next());
System.out.print("What is your password? ");
jd.setPassword(input.next());
} catch (Exception e) {
log.log(Level.SEVERE, "The system encountered an exception while attempting to login");
} finally {
input.close();
}
jd.setJob("TestREST");
jd.setServer("http://YOUR-SERVER");
jd.setPort("YOUR-PORT");
// set the parameters
List<NameValuePair> parameters = jd.getParameters();
parameters.add(new BasicNameValuePair("SONAR-TARGET", "true"));
parameters.add(new BasicNameValuePair("RELEASE", "1311.1.1"));
parameters.add(new BasicNameValuePair("REVISION", "HEAD"));
// run the job
JenkinsPoster jp = new JenkinsPoster(jd);
log.info("executing postJenkinsJob");
jp.postJenkinsJob();
log.info("executed postJenkinsJob");
}
}
The JobData class (holds information about the job you need to run)
package stackoverflow.answer;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.NameValuePair;
public class JobData {
private String username;
private String password;
private String token;
private String server;
private String port;
private String job;
private List<NameValuePair> parameters;
public JobData() {
parameters = new ArrayList<NameValuePair>();
}
public String getUsername() {return username;}
public void setUsername(String username) {this.username = username;}
public String getPassword() {return password;}
public void setPassword(String password) {this.password = password;}
public String getToken() {return token;}
public void setToken(String token) {this.token = token;}
public String getServer() {return server;}
public void setServer(String server) {this.server = server;}
public String getPort() {return port;}
public void setPort(String port) {this.port = port;}
public String getJob() {return job;}
public void setJob(String job) {this.job = job;}
public List<NameValuePair> getParameters() {return parameters;}
}
The JenkinsPoster class (contains the business logic to connect to Jenkins and POST the job)
package stackoverflow.answer;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.List;
import java.util.logging.Logger;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.util.EntityUtils;
public class JenkinsPoster {
final Logger log = Logger.getLogger(getClass().getCanonicalName());
private JobData jd;
public JenkinsPoster(JobData jobData) {
this.jd = jobData;
}
#SuppressWarnings("deprecation")
public void postJenkinsJob() throws UnsupportedEncodingException {
log.entering(getClass().getCanonicalName(), "JenkinsPoster");
// Jenkins url
String jenkinsUrl = String.format("%s:%s/jenkins", jd.getServer(), jd.getPort());
log.info("url = " + jenkinsUrl);
// Create your httpclient
DefaultHttpClient client = new DefaultHttpClient();
// Then provide the right credentials
client.getCredentialsProvider().setCredentials(new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT),
new UsernamePasswordCredentials(jd.getUsername(), jd.getPassword()));
// Generate BASIC scheme object and stick it to the execution context
BasicScheme basicAuth = new BasicScheme();
BasicHttpContext context = new BasicHttpContext();
context.setAttribute("preemptive-auth", basicAuth);
// Add as the first (because of the zero) request interceptor
// It will first intercept the request and preemptively initialize the authentication scheme if there is not
client.addRequestInterceptor(new PreemptiveAuth(), 0);
// Post the request to start the build
List<NameValuePair> parameters = jd.getParameters();
UrlEncodedFormEntity uefe = null;
String buildUrl = "";
if (parameters.isEmpty()) {
buildUrl = jenkinsUrl + "/job/" + jd.getJob() + "/build";
}
else {
buildUrl = jenkinsUrl + "/job/" + jd.getJob() + "/buildWithParameters";
uefe = new UrlEncodedFormEntity(parameters);
}
HttpPost post = new HttpPost(buildUrl);
post.setHeader("User-Agent", "Mozilla/5.0");
if (uefe != null) {
post.setEntity(uefe);
}
try {
// Execute your request with the given context
HttpResponse response = client.execute(post, context);
HttpEntity entity = response.getEntity();
log.info(EntityUtils.toString(entity));
EntityUtils.consume(entity);
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally {
client.close();
}
log.exiting(getClass().getCanonicalName(), "JenkinsPoster");
}
}
... and finally, the PreemptiveAuth class that the previous class uses to preemptively login to Jenkins.
package stackoverflow.answer;
import java.io.IOException;
import org.apache.http.HttpException;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.HttpRequestInterceptor;
import org.apache.http.auth.AuthScheme;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.AuthState;
import org.apache.http.auth.Credentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.protocol.ClientContext;
import org.apache.http.protocol.ExecutionContext;
import org.apache.http.protocol.HttpContext;
public class PreemptiveAuth implements HttpRequestInterceptor {
public void process(HttpRequest request, HttpContext context)
throws HttpException, IOException {
// Get the AuthState
AuthState authState = (AuthState) context.getAttribute(ClientContext.TARGET_AUTH_STATE);
// If no auth scheme available yet, try to initialize it preemptively
if (authState.getAuthScheme() == null) {
AuthScheme authScheme = (AuthScheme) context.getAttribute("preemptive-auth");
CredentialsProvider credsProvider = (CredentialsProvider) context
.getAttribute(ClientContext.CREDS_PROVIDER);
HttpHost targetHost = (HttpHost) context.getAttribute(ExecutionContext.HTTP_TARGET_HOST);
if (authScheme != null) {
Credentials creds = credsProvider.getCredentials(new AuthScope(targetHost.getHostName(), targetHost
.getPort()));
if (creds == null) {
throw new HttpException("No credentials for preemptive authentication");
}
authState.setAuthScheme(authScheme);
authState.setCredentials(creds);
}
}
}
}
Documentation on handling Jenkins' REST API authentication can be found here:
https://wiki.jenkins-ci.org/display/JENKINS/Authenticating+scripted+clients

Categories