HttpURLConnection、HttpClient设置代理Proxy
有如下一种需求,原本A要给C发送请求,但是因为网络原因,需要借助B才能实现,所以由原本的A->C变成了A->B->C。
这种情况,更多的见于内网请求由统一的网关做代理然后转发出去,比如你本地的机器想要对外上网,都是通过运营商给的出口IP也就是公网地址实现的。这种做法就是代理了。
研究了一下针对 HttpURLConnection和HttpClient这两种常见的http请求的代理:
一、HttpURLConnection设置请求代理
贴出一个utils类
具体代码如下:
publicclassProxyUtils{publicstaticfinalStringCONTENT_TYPE="application/x-www-form-urlencoded";publicstaticStringgetResultByHttpConnectionProxy(String url,String content,String proxyHost,int proxyPort){String result ="";OutputStream outputStream =null;InputStream inputStream =null;try{//设置proxyProxy proxy =newProxy(Proxy.Type.HTTP,newInetSocketAddress(proxyHost, proxyPort));URL proxyUrl =newURL(url);//判断是哪种类型的请求if(url.startsWith("https")){HttpsURLConnection httpsURLConnection =(HttpsURLConnection) proxyUrl.openConnection(proxy);
httpsURLConnection.setRequestProperty("Content-Type",CONTENT_TYPE);//允许写入
httpsURLConnection.setDoInput(true);//允许写出
httpsURLConnection.setDoOutput(true);//请求方法的类型 POST/GET
httpsURLConnection.setRequestMethod("POST");//是否使用缓存
httpsURLConnection.setUseCaches(false);//读取超时
httpsURLConnection.setReadTimeout(15000);//连接超时
httpsURLConnection.setConnectTimeout(15000);//设置SSL
httpsURLConnection.setSSLSocketFactory(getSsf());//设置主机验证程序
httpsURLConnection.setHostnameVerifier((s, sslSession)->true);
outputStream = httpsURLConnection.getOutputStream();
outputStream.write(content.getBytes(StandardCharsets.UTF_8));
outputStream.flush();
inputStream = httpsURLConnection.getInputStream();}else{HttpURLConnection httpURLConnection =(HttpURLConnection) proxyUrl.openConnection(proxy);
httpURLConnection.setRequestProperty("Content-Type",CONTENT_TYPE);
httpURLConnection.setDoOutput(true);
httpURLConnection.setDoInput(true);
httpURLConnection.setRequestMethod("POST");
httpURLConnection.setUseCaches(false);
httpURLConnection.setConnectTimeout(15000);
httpURLConnection.setReadTimeout(15000);
outputStream = httpURLConnection.getOutputStream();
outputStream.write(content.getBytes("UTF-8"));
outputStream.flush();
inputStream = httpURLConnection.getInputStream();}byte[] bytes =read(inputStream,1024);
result =(newString(bytes,"UTF-8")).trim();}catch(Exception e){
e.printStackTrace();}finally{try{if(outputStream !=null){
outputStream.close();}if(inputStream !=null){
inputStream.close();}}catch(Exception e){
e.printStackTrace();}}return result;}publicstaticbyte[]read(InputStream inputStream,int bufferSize)throwsIOException{ByteArrayOutputStream baos =newByteArrayOutputStream();byte[] buffer =newbyte[bufferSize];for(int num = inputStream.read(buffer); num !=-1; num = inputStream.read(buffer)){
baos.write(buffer,0, num);}
baos.flush();return baos.toByteArray();}privatestaticSSLSocketFactorygetSsf(){SSLContext ctx =null;try{
ctx =SSLContext.getInstance("TLS");
ctx.init(newKeyManager[0],newTrustManager[]{newProxyUtils.DefaultTrustManager()},newSecureRandom());}catch(Exception e){
e.printStackTrace();}assert ctx !=null;return ctx.getSocketFactory();}privatestaticfinalclassDefaultTrustManagerimplementsX509TrustManager{@OverridepublicvoidcheckClientTrusted(X509Certificate[] chain,String authType)throwsCertificateException{}@OverridepublicvoidcheckServerTrusted(X509Certificate[] chain,String authType)throwsCertificateException{}@OverridepublicX509Certificate[]getAcceptedIssuers(){returnnull;}}}
上面的代码就是对httpsURLConnection设置了Proxy代理,也就是请求先会发到proxyHost:proxyPort,然后由其代理发到url。
二、HttpClient设置请求代理
贴出一个utils类
具体代码如下:
publicclassHttpclientUtils{privatestaticfinalStringCONTENT_TYPE="application/x-www-form-urlencoded";publicstaticStringgetResultByProxy(String url,String request,String proxyHost,int proxyPort)throwsException{String response =null;HttpPost httpPost =null;try{HttpClient httpClient =getHttpClient(url);//设置请求配置类 重点就是在这里添加setProxy 设置代理RequestConfig requestConfig =RequestConfig.custom().setSocketTimeout(15000).setConnectTimeout(15000).setConnectionRequestTimeout(15000).setProxy(newHttpHost(proxyHost, proxyPort)).build();
httpPost =newHttpPost(url);
httpPost.setConfig(requestConfig);
httpPost.addHeader("Content-Type",CONTENT_TYPE);
httpPost.setEntity(newStringEntity(request,"utf-8"));
response =getHttpClientResponse(httpPost, httpClient);}catch(Exception e){
e.printStackTrace();}finally{if(null!= httpPost){
httpPost.releaseConnection();}}return response;}privatestaticStringgetHttpClientResponse(HttpPost httpPost,HttpClient httpClient)throwsException{String result =null;HttpResponse httpResponse = httpClient.execute(httpPost);HttpEntity entity = httpResponse.getEntity();if(null!= entity){try(InputStream inputStream = entity.getContent()){byte[] bytes =read(inputStream,1024);
result =newString(bytes,StandardCharsets.UTF_8);}}return result;}privatestaticHttpClientgetHttpClient(String url)throwsException{HttpClient httpClient;String lowerURL = url.toLowerCase();if(lowerURL.startsWith("https")){
httpClient =createSSLClientDefault();}else{
httpClient =HttpClients.createDefault();}return httpClient;}privatestaticCloseableHttpClientcreateSSLClientDefault()throwsException{SSLContext sslContext =newSSLContextBuilder().loadTrustMaterial(null,(chain, authType)->true).build();SSLConnectionSocketFactory sslsf =newSSLConnectionSocketFactory(sslContext,(s, sslSession)->true);returnHttpClients.custom().setSSLSocketFactory(sslsf).build();}publicstaticbyte[]read(InputStream inputStream,int bufferSize)throwsIOException{ByteArrayOutputStream baos =newByteArrayOutputStream();byte[] buffer =newbyte[bufferSize];for(int num = inputStream.read(buffer); num !=-1; num = inputStream.read(buffer)){
baos.write(buffer,0, num);}
baos.flush();return baos.toByteArray();}}
以上就是针对http、https的代理汇总,其实想想,就是通过 Proxy 对象,添加对应的代理地址和端口,实现了一层转发,可以想到nginx、gateway这种思想。
欢迎大家讨论学习,本人能力有限,也是摸索探究的,有不对的地方欢迎指正。
版权归原作者 几层山下 所有, 如有侵权,请联系我们删除。