How to set Proxy in HttpPost in java - java

Please consider that I have a Custom Proxy Class with fields,
private final String serverName;
private final int port;
private final String username;
private final String password;
I want to use this Proxy in the below existing code, but I am not sure how to add that. The below code does not support proxy.
public CustomClassForResponse createRequest(CreateCustomRequest request) {
HttpPost httpRequest = new HttpPost();
try {
URIBuilder uriBuilder = new URIBuilder();
uriBuilder.setScheme(URL_SCHEME).setHost(HOST_URL).setPath("/api");
httpRequest.setURI(uriBuilder.build());
httpRequest.setHeader("Authorization", accessToken());
httpRequest.setHeader("Content-Type", "application/json");
httpRequest.setHeader("Accept", "application/json");
RequestConfig requestConfig = RequestConfig.custom()
.setConnectionRequestTimeout(1000 * 60 * 5)
.setSocketTimeout(1000 * 60 * 5)
.build();
httpRequest.setConfig(requestConfig);
httpRequest = (HttpPost) addJsonBody(request, httpRequest);
return sendRequest(httpRequest, CustomClassForResponse.class);
} catch (Exception e) {
throw new CustomException(e);
}
}
private HttpEntityEnclosingRequest addJsonBody(JsonRequest request, HttpEntityEnclosingRequest httpRequest) throws JsonProcessingException {
EntityBuilder builder = EntityBuilder.create();
builder.setContentType(ContentType.APPLICATION_JSON);
builder.setText(ObjectMapperProvider.getInstance().writeValueAsString(request));
HttpEntity httpEntity = builder.build();
httpRequest.setEntity(httpEntity);
return httpRequest;
}
private <T extends JsonResponse> T sendRequest(HttpRequestBase httpRequest, Class<T> responseClass) throws IOException {
CloseableHttpResponse response = createHttpClient().execute(httpRequest, createHttpClientContext());
HttpEntity entity = response.getEntity();
if (isResponseSuccess(response)) {
T jsonResponse = ObjectMapperProvider.getInstance().readValue(entity.getContent(), responseClass);
return jsonResponse;
} else {
throw new CustomException();
}
}
so the createRequest method is called and then it calls the addJsonBody and then the sendRequest method.
Here are the version details:
("org.apache.httpcomponents:httpcore:4.4.6")
("org.apache.httpcomponents:httpclient:4.5.13")
("org.apache.httpcomponents:httpmime:4.5.3")
("commons-logging:commons-logging:1.2")

Set the proxy when you create the client, or set the proxy on the Request.
Since you already refer to a createHttpClient() method :
private ClosableHttpClient createHttpClient() {
HttpClientBuilder builder = HttpClients.custom();
builder.setProxy(HttpHost.create("http://my.proxy"));
return builder.build();
}
or setting it when you create the request :
RequestConfig requestConfig = RequestConfig.custom()
.setConnectionRequestTimeout(1000 * 60 * 5)
.setSocketTimeout(1000 * 60 * 5)
.setProxy("http://my.proxy")
.build();
Since you're implying that it's an authenticated proxy then I guess some credentials are in order.
private ClosableHttpClient createHttpClient() {
CredentialsProvider creds = new BasicCredentialsProvider();
creds.setCredentials(new AuthScope("my.proxy", 80),
new UsernamePasswordCredentials("myuser", "mypassword")));
HttpClientBuilder builder = HttpClients.custom()
.setDefaultCredentialsProvider(creds)
.setProxyAuthenticationStrategy(ProxyAuthenticationStrategy.INSTANCE)
.setProxy(HttpHost.create("http://my.proxy"));
return builder.build();
}

Related

While running test case ClientHttpResponse is throwing 401 error

I have a problem with my unit test. In my unit test I am getting 401 Unauthorised as response status and I don't know how to solve this problem. This is not a Spring project.
My Test class
#RunWith(MockitoJUnitRunner.class)
public class LTest {
#Test
public void test_retrieve() throws Exceptions{
CloseableHttpClient mockHttpClient = mock(CloseableHttpClient.class);
CloseableHttpResponse mockHttpResponse = mock(CloseableHttpResponse.class);
HttpEntity mockEntity = mock(HttpEntity.class);
StatusLine mockStatusLine = mock(StatusLine.class);
when(mockHttpClient.execute(new HttpGet(new URIBuilder(anyString()).build()))).thenReturn(mockHttpResponse);
when(mockHttpResponse.getEntity()).thenReturn(mockEntity);
when(mockHttpResponse.getStatusLine()).thenReturn(mockStatusLine);
when(mockStatusLine.getStatusCode()).thenReturn(HttpStatus.SC_OK);
Map<String, Employee> map = sample.retrieve();
assertNotNull(map);
assertEquals(1,map.size());
}
source code for the above test case
CloseableHttpClient httpClient = HttpClientUtils.setupClient(HttpClientBuilder.create()).build();
String url = "http://someexample.com";
UriBuilder builder = new URIBuilder(url)
.setParameter("limit",5)
.setParameter("centre",centre);
CloseableHttpResponse httpResponse = httpClient.execute(new HttpGet(builder.build()));
if(httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
try{
String entity = EntityUtils.toString(httpResponse.getEntity());
ObjectNode node = new ObjectMapper().readValue(entity,ObjectNode.class);
} catch (IOException e){
e.printStackTrace();
}
}
While running the test case it's showing assertion error because it's going through catch block due below line is throwing 401 instead of 200
CloseableHttpResponse httpResponse = httpClient.execute(new HttpGet(builder.build()));
Can anyone please help me with the above error I am getting?
In the test, HTTPClient is not mocked and that is the reason for the failure.
To mock the HTTPClient we can follow the below strategy
Extract getHttpClient() in the ClassToBeTested as
public class HttpClientToBeTested {
public Map retrieve() throws URISyntaxException, IOException {
CloseableHttpClient httpClient = getHttpClient();
String url = "http://someexample.com";
URIBuilder builder = new URIBuilder(url)
.setParameter("limit","5")
.setParameter("centre","centre");
CloseableHttpResponse httpResponse = httpClient.execute(new HttpGet(builder.build()));
if(httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
try{
String entity = EntityUtils.toString(httpResponse.getEntity());
//ObjectNode node = new ObjectMapper().readValue(entity,ObjectNode.class);
Map node = new ObjectMapper().readValue(entity, Map.class); // Assume ObjectNode is a custom class, so for demo using Map.
return node;
} catch (IOException e){
e.printStackTrace();
throw e;
}
}
return null;
}
// New extracted method that will be mocked in the test case
protected CloseableHttpClient getHttpClient() {
return HttpClientBuilder.create().build();
}
}
Next in the test class, we can inject the mock by subclassing the ClassToBeTested in an anonymous class as follows.
#Test
public void test_retrieve() throws Exception {
CloseableHttpClient mockHttpClient = mock(CloseableHttpClient.class);
CloseableHttpResponse mockHttpResponse = mock(CloseableHttpResponse.class);
//HttpEntity mockEntity = mock(HttpEntity.class); Not required since we will pass actual entity
StatusLine mockStatusLine = mock(StatusLine.class);
when(mockHttpClient.execute(new HttpGet(new URIBuilder(anyString()).build()))).thenReturn(mockHttpResponse);
when(mockHttpResponse.getEntity()).thenReturn(new StringEntity("{\"key\":\"value\"}")); // Important: Pass your actual response as string here.
when(mockHttpResponse.getStatusLine()).thenReturn(mockStatusLine);
when(mockStatusLine.getStatusCode()).thenReturn(HttpStatus.SC_OK);
// Code to mock the http client
HttpClientToBeTested sample = new HttpClientToBeTested() {
#Override
protected CloseableHttpClient getHttpClient() {
return mockHttpClient;
}
};
Map map = sample.retrieve();
assertNotNull(map);
assertEquals(1,map.size());
}
UPDATE: After mocking the httpClient, httpClient.execute() should return SC_OK. However, post that deserializing the response will fail since the mock HttpEntity will return null. To avoid it, we will rather send a StringEntity. Updated the actual and test class with the details.

Retrofit: Making Web Requests to Internal APIs

I want to make a request to my organisation api's. The request contains Headers, UserName, Password, & Cookie for session management.
Below is the actual code (in HttpClient) which I want to rewrite using Retrofit. I have heard that HttpClient libraries have been deprecated or someting so have opted Retrofit. I expect the response with 200 status code.
public static CookieStore cookingStore = new BasicCookieStore();
public static HttpContext context = new BasicHttpContext();
public String getAuth(String login,String password) {
String resp = null;
try {
String url = DOMAIN+"myxyzapi/myanything";
context.setAttribute(HttpClientContext.COOKIE_STORE, cookingStore);
HttpClient client = HttpClientBuilder.create().build();
HttpPost post = new HttpPost(url);
String log = URLEncoder.encode(login, "UTF-8");
String pass = URLEncoder.encode(password, "UTF-8");
String json = "username="+log+"&password="+pass+"&maintain=true&finish=Go";
StringEntity entity = new StringEntity(json);
post.setEntity(entity);
post.addHeader("Content-Type", "application/x-www-form-urlencoded");
HttpResponse response = client.execute(post,context);
resp = EntityUtils.toString(response.getEntity());
accountPoller();
} catch(Exception a) {
log.info("Exception in authentication api:"+a.getMessage().toString());
}
return resp;
}
Below is my code where I can't figure out how to pass the context with request. HttpResponse response = client.execute(post,**context**); using retrofit.
I don't even know if I have made my retrofit request right.
try {
String log = URLEncoder.encode(login, "UTF-8");
String pass = URLEncoder.encode(password, "UTF-8");
RequestBody formBody = new FormBody.Builder()
.add("username=", xyz)
.add("password=", mypass)
.add("&maintain=", "true")
.add("finish=", "Go")
.build();
String url = www.xyz.com+"myxyzapi/myanything";
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(url).post(formBody).addHeader("Content-Type", "application/x-www-form-urlencoded").build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
}
#Override
public void onResponse(Call call, Response response) throws IOException {
if(response.isSuccessful()){
final String myresp = response.body().string();
}
}
});
} catch(Exception a) {
a.getMessage();
}
You have to catch exception and use this class.
retrofit2.HttpException
retrofit2
Class HttpException
int
code()
HTTP status code.
String
message()
HTTP status message.
Response
response()
The full HTTP response.

How to get full json response using httprequest

Simply I am trying to hit URL i.e. www.google.com
and I want to capture whole json responce as output ...
I tried multiple codes which help me to find only response code but I want full json response from which I can filter few information.
above thing I am doing for web..
I used ApacheHttpClient jar (version 4.5.1). You'll also need HttpCore library (I used 4.4.3) and maybe some other apache libraries (like codec).
Here are a GET method and a POST method:
public static String getJsonStringHttpGet(String url,Map<String,String> headers) throws IOException {
BasicCookieStore cookieStore = new BasicCookieStore();
CloseableHttpClient httpClient = HttpClients.custom()
.setDefaultCookieStore(cookieStore)
.build();
HttpCoreContext localContext = new HttpCoreContext();
HttpGet get = new HttpGet(url);
/*
* if you need to specify headers
*/
if (headers != null) {
for (String name : headers.keySet()) {
get.addHeader(name, headers.get(name));
}
}
HttpResponse response = httpClient.execute(get, localContext);
byte [] bytes = EntityUtils.toByteArray(response.getEntity());
return new String(bytes);
}
public static String getJsonStringHttpPost(String url,Map<String,String> postParams,Map<String,String> headers) throws IOException {
BasicCookieStore cookieStore = new BasicCookieStore();
CloseableHttpClient httpClient = HttpClients.custom()
.setDefaultCookieStore(cookieStore)
.build();
HttpCoreContext localContext = new HttpCoreContext();
HttpPost post = new HttpPost(url);
/*
* adding some POST params
*/
if (postParams != null && postParams.size() > 0) {
List<BasicNameValuePair> postParameters = new ArrayList<>();
for (String name : postParams.keySet()) {
postParameters.add(new BasicNameValuePair(name, postParams.get(name)));
}
post.setEntity(new UrlEncodedFormEntity(postParameters));
}
/*
* if you need to specify headers
*/
if (headers != null) {
for (String name : headers.keySet()) {
post.addHeader(name, headers.get(name));
}
}
HttpResponse response = httpClient.execute(post, localContext);
byte [] bytes = EntityUtils.toByteArray(response.getEntity());
return new String(bytes);
}
Then you can parse the json string as you like.
Hope this helps

Is there a way to convert non-ascii chars to unicode and leave ascii as they are?

I've just found out, that apache httpclient returns incorrectly decoded location header, if it contains percent encoded letters.
when the same request in browser returns correct string:
I've written a method for restoring uri. Did I write it right? Is there a simplier way?
import java.net.URLDecoder;
public class Test {
public static void main(String[] args) throws Exception {
String uri = "/search-zero?searchterm=\u00D1\u008C";
String converted = convert(uri);
System.out.println(converted); // /search-zero?searchterm=%D1%8C
System.out.println(URLDecoder.decode(converted, "utf-8")); // /search-zero?searchterm=ь
}
private static String convert(String uri) {
char[] chars = uri.toCharArray();
int i = 0;
StringBuilder result = new StringBuilder();
while (i < chars.length) {
int n = (int) chars[i];
if (n > 127) {
result.append('%');
result.append(String.format("%02X", n));
} else {
result.append(chars[i]);
}
i++;
}
return result.toString();
}
}
UPDATE
My current HttpClient configuration:
#Bean
public CloseableHttpClient getHttpClient() {
ConnectionConfig connectionConfig = ConnectionConfig.custom().setCharset(Consts.UTF_8).build();
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
cm.setMaxTotal(200);
cm.setDefaultMaxPerRoute(20);
return HttpClients.custom()
.setDefaultConnectionConfig(connectionConfig)
.setConnectionManager(cm)
.setRedirectStrategy(new CustomRedirectStrategy())
.build();
}
public class CustomRedirectStrategy extends DefaultRedirectStrategy {
#Override
public URI getLocationURI(HttpRequest request, HttpResponse response, HttpContext context) throws ProtocolException {
System.out.println(response.getFirstHeader("location"));
URI uri = super.getLocationURI(request, response, context);
return uri;
}
}
WORKING CODE (WE NEEDED EITHER CORRECTLY SET UP CUSTOM CONNECTION MANAGER OR JUST DELETE IT) THANKS OLEG!!
#Bean
public CloseableHttpClient getHttpClient() {
ConnectionConfig connectionConfig = ConnectionConfig.custom().setCharset(Consts.UTF_8).build();
// PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
// cm.setMaxTotal(200);
// cm.setDefaultMaxPerRoute(20);
return HttpClients.custom()
.setDefaultConnectionConfig(connectionConfig)
// .setConnectionManager(cm)
.setRedirectStrategy(new CustomRedirectStrategy())
.build();
}
One can force HttpClient to use a non-standard charset for protocol elements, which should improve inter-operability with broken web servers that include unescaped non-ASCII chars in 'Location' headers
ConnectionConfig connectionConfig = ConnectionConfig.custom()
.setCharset(Consts.ISO_8859_1)
.build();
CloseableHttpClient client = HttpClients.custom()
.setDefaultConnectionConfig(connectionConfig)
.build();

Preemptive Basic authentication with Apache HttpClient 4

Is there an easier way to setup the http client for preemptive basic authentication than what described here?
In previous version (3.x) it used to be a simple method call (eg, httpClient.getParams().setAuthenticationPreemptive(true)).
The main thing I want to avoid is adding the BasicHttpContext to each method I execute.
If you are looking to force HttpClient 4 to authenticate with a single request, the following will work:
String username = ...
String password = ...
UsernamePasswordCredentials creds = new UsernamePasswordCredentials(username, password);
HttpRequest request = ...
request.addHeader(new BasicScheme().authenticate(creds, request));
It's difficult to do this without passing a context through every time, but you can probably do it by using a request interceptor. Here is some code that we use (found from their JIRA, iirc):
// Pre-emptive authentication to speed things up
BasicHttpContext localContext = new BasicHttpContext();
BasicScheme basicAuth = new BasicScheme();
localContext.setAttribute("preemptive-auth", basicAuth);
httpClient.addRequestInterceptor(new PreemptiveAuthInterceptor(), 0);
(...)
static class PreemptiveAuthInterceptor implements HttpRequestInterceptor {
public void process(final HttpRequest request, final HttpContext context) throws HttpException, IOException {
AuthState authState = (AuthState) context.getAttribute(ClientContext.TARGET_AUTH_STATE);
// If no auth scheme avaialble 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);
}
}
}
}
This is the same solution as Mat's Mannion's, but you don't have to put localContext to each request. It's simpler, but it adds authentication to ALL requests. Useful, if you don't have control over individual requests, as in my case when using Apache Solr, which uses HttpClient internally.
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.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.HttpClientContext;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.HttpCoreContext;
httpClient.addRequestInterceptor(new PreemptiveAuthInterceptor(), 0);
(...)
static class PreemptiveAuthInterceptor implements HttpRequestInterceptor {
public void process(final HttpRequest request, final HttpContext context) throws HttpException, IOException {
AuthState authState = (AuthState) context.getAttribute(HttpClientContext.TARGET_AUTH_STATE);
// If no auth scheme available yet, try to initialize it
// preemptively
if (authState.getAuthScheme() == null) {
CredentialsProvider credsProvider = (CredentialsProvider) context.getAttribute(HttpClientContext.CREDS_PROVIDER);
HttpHost targetHost = (HttpHost) context.getAttribute(HttpCoreContext.HTTP_TARGET_HOST);
Credentials creds = credsProvider.getCredentials(new AuthScope(targetHost.getHostName(), targetHost.getPort()));
if (creds == null) {
throw new HttpException("No credentials for preemptive authentication");
}
authState.update(new BasicScheme(), creds);
}
}
}
Of course, you have to set the credentials provider:
httpClient.getCredentialsProvider().setCredentials(
new AuthScope(url.getHost(), url.getPort()),
new UsernamePasswordCredentials(username, password))
The AuthScope must not contain realm, as it is not known in advance.
A lot of the answers above use deprecated code. I am using Apache SOLRJ version 5.0.0.
My code consists of
private HttpSolrClient solrClient;
private void initialiseSOLRClient() {
URL solrURL = null;
try {
solrURL = new URL(urlString);
} catch (MalformedURLException e) {
LOG.error("Cannot parse the SOLR URL!!" + urlString);
throw new SystemException("Cannot parse the SOLR URL!! " + urlString, e);
}
String host = solrURL.getHost();
int port = solrURL.getPort();
AuthScope authScope = new AuthScope(host, port);
BasicTextEncryptor textEncryptor = new BasicTextEncryptor();
textEncryptor.setPassword("red bananas in the spring");
String decryptPass = textEncryptor.decrypt(pass);
UsernamePasswordCredentials creds = new UsernamePasswordCredentials(userName, decryptPass);
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(
authScope,
creds);
HttpClientBuilder builder = HttpClientBuilder.create();
builder.addInterceptorFirst(new PreemptiveAuthInterceptor());
builder.setDefaultCredentialsProvider(credsProvider);
CloseableHttpClient httpClient = builder.build();
solrClient = new HttpSolrClient(urlString, httpClient);
}
The PreemptiveAuthInterceptor is now as follows:-
static class PreemptiveAuthInterceptor implements HttpRequestInterceptor {
public void process(final HttpRequest request, final HttpContext context) throws HttpException, IOException {
AuthState authState = (AuthState) context.getAttribute(HttpClientContext.TARGET_AUTH_STATE);
// If no auth scheme available yet, try to initialize it
// preemptively
if (authState.getAuthScheme() == null) {
CredentialsProvider credsProvider = (CredentialsProvider)
context.getAttribute(HttpClientContext.CREDS_PROVIDER);
HttpHost targetHost = (HttpHost) context.getAttribute(HttpCoreContext.HTTP_TARGET_HOST);
AuthScope authScope = new AuthScope(targetHost.getHostName(), targetHost.getPort());
Credentials creds = credsProvider.getCredentials(authScope);
if(creds == null){
}
authState.update(new BasicScheme(), creds);
}
}
}
A little late to the party but I came accross the thread trying to solve this for proxy pre-authorization of a post request. To add to Adam's response, I found the following worked for me:
HttpPost httppost = new HttpPost(url);
UsernamePasswordCredentials creds = new UsernamePasswordCredentials(username, password);
Header bs = new BasicScheme().authenticate(creds, httppost);
httppost.addHeader("Proxy-Authorization", bs.getValue());
Thought that might be helpful for anyone else who runs into this.
I think the best way may be to just do it manually. I added the following function
Classic Java:
import javax.xml.bind.DatatypeConverter;
...
private static void addAuthHeader(HttpRequestBase http, String username, String password) throws UnsupportedEncodingException {
String encoded = DatatypeConverter.printBase64Binary((username + ":" + password).getBytes("UTF-8"));
http.addHeader("AUTHORIZATION", "Basic " + encoded);
}
HTTPRequestBase can be an instance of HttpGet or HttpPost
Android:
import android.util.Base64;
...
private static void addAuthHeader(HttpRequestBase http, String username, String password) throws UnsupportedEncodingException {
String encoded = Base64.encodeToString((username + ":" + password).getBytes("UTF-8"), Base64.NO_WRAP);
http.addHeader("AUTHORIZATION", "Basic " + encoded);
}
I'm using this code, based on my reading of the HTTPClient 4.5 docs:
HttpClientContext ctx = HttpClientContext.create()
ctx.setCredentialsProvider(new BasicCredentialsProvider())
ctx.setAuthCache(new BasicAuthCache())
UsernamePasswordCredentials creds = new UsernamePasswordCredentials(user, pass)
AuthScope authScope = new AuthScope(host, port)
ctx.getCredentialsProvider.setCredentials(authScope, credentials)
// This part makes authentication preemptive:
HttpHost targetHost = new HttpHost(host, port, scheme)
ctx.getAuthCache.put(targetHost, new BasicScheme())
...and make sure you always pass that context to HTTPClient.execute().
I don't quite get your closing comment. It's the HttpClient that has all of that machinery for doing preemptive auth, and you only have to do that once (when you construct and configure your HttpClient). Once you've done that, you construct your method instances the same way as always. You don't "add the BasicHttpContext" to the method.
Your best bet, I'd think, is to have your own object that sets up all of the junk required for preemptive auth, and has a simple method or methods for executing requests on given HTTPMethod objects.
in android,Mat Mannion's answer can't resolve https,still send two requests,you can do like below,the trick is append authHeader with user-agent:
public static DefaultHttpClient createProxyHttpClient() {
try {
final DefaultHttpClient client = createPlaintHttpClient();
client.setRoutePlanner(new HttpRoutePlanner() {
#Override
public HttpRoute determineRoute(HttpHost target, HttpRequest request, HttpContext context) throws HttpException {
boolean isSecure = "https".equalsIgnoreCase(target.getSchemeName());
if (needProxy) {
Header header = isSecure ? ProxyUtils.createHttpsAuthHeader() : ProxyUtils.createAuthHeader();
if (isSecure) {
client.getParams().setParameter(CoreProtocolPNames.USER_AGENT, com.netease.cloudmusic.utils.HttpRequest.USER_AGENT + "\r\n" + header.getName() + ":" + header.getValue());
} else {
client.getParams().setParameter(CoreProtocolPNames.USER_AGENT, com.netease.cloudmusic.utils.HttpRequest.USER_AGENT);
if (request instanceof RequestWrapper) {
request = ((RequestWrapper) request).getOriginal();
}
request.setHeader(header);
}
String host = isSecure ? ProxyUtils.SECURE_HOST : ProxyUtils.HOST;
int port = isSecure ? ProxyUtils.SECURE_PORT : ProxyUtils.PORT;
return new HttpRoute(target, null, new HttpHost(host, port), isSecure);
} else {
client.getParams().setParameter(CoreProtocolPNames.USER_AGENT, com.netease.cloudmusic.utils.HttpRequest.USER_AGENT);
return new HttpRoute(target, null, isSecure);
}
}
});
return client;
} catch (Exception e) {
e.printStackTrace();
return new DefaultHttpClient();
}
}
public static DefaultHttpClient createPlaintHttpClient() {
try {
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(null, null);
PlainSSLSocketFactory socketFactory = new PlainSSLSocketFactory(trustStore);
socketFactory.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
BasicHttpParams params = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(params, 30000);
HttpConnectionParams.setSoTimeout(params, 30000);
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
registry.register(new Scheme("https", socketFactory, 443));
ThreadSafeClientConnManager ccm = new ThreadSafeClientConnManager(params, registry);
HttpClientParams.setCookiePolicy(params, CookiePolicy.BROWSER_COMPATIBILITY);
final DefaultHttpClient client = new DefaultHttpClient(ccm, params);
client.setRoutePlanner(new HttpRoutePlanner() {
#Override
public HttpRoute determineRoute(HttpHost target, HttpRequest arg1, HttpContext arg2) throws HttpException {
client.getParams().setParameter(CoreProtocolPNames.USER_AGENT, com.netease.cloudmusic.utils.HttpRequest.USER_AGENT);
return new HttpRoute(target, null, "https".equalsIgnoreCase(target.getSchemeName()));
}
});
return client;
} catch (Exception e) {
e.printStackTrace();
return new DefaultHttpClient();
}
}
SolrConfig:
#Configuration
public class SolrConfig {
#Value("${solr.http.url}")
private String solrUrl;
#Value("${solr.http.username}")
private String solrUser;
#Value("${solr.http.password}")
private String solrPassword;
#Value("${solr.http.pool.maxTotal}")
private int poolMaxTotal;
#Value("${solr.http.pool.maxPerRoute}")
private int pollMaxPerRoute;
#Bean
public SolrClient solrClient() {
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
connectionManager.setMaxTotal(poolMaxTotal);
connectionManager.setDefaultMaxPerRoute(pollMaxPerRoute);
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(solrUser, solrPassword));
CloseableHttpClient httpClient = HttpClientBuilder.create()
.addInterceptorFirst(new PreemptiveAuthInterceptor())
.setConnectionManager(connectionManager)
.setDefaultCredentialsProvider(credentialsProvider)
.build();
return new HttpSolrClient.Builder(solrUrl).withHttpClient(httpClient).build();
}
}
PreemptiveAuthInterceptor:
public class PreemptiveAuthInterceptor implements HttpRequestInterceptor {
public void process(final HttpRequest request, final HttpContext context)
throws HttpException {
AuthState authState = (AuthState) context
.getAttribute(HttpClientContext.TARGET_AUTH_STATE);
// If no auth scheme available yet, try to initialize it
// preemptively
if (authState.getAuthScheme() == null) {
CredentialsProvider credentialsProvider = (CredentialsProvider) context
.getAttribute(HttpClientContext.CREDS_PROVIDER);
HttpHost targetHost = (HttpHost) context
.getAttribute(HttpCoreContext.HTTP_TARGET_HOST);
Credentials credentials = credentialsProvider.getCredentials(new AuthScope(
targetHost.getHostName(), targetHost.getPort()));
if (credentials == null) {
throw new HttpException(
"No credentials for preemptive authentication");
}
authState.update(new BasicScheme(), credentials);
}
}
}

Categories