nginx rewrite(301)重定向之後無法正常請求的解決方案
阿新 • • 發佈:2019-01-08
前言
前面通過騰訊雲ssl證書實現了https的請求,如果想簡單瞭解可參考如何新增SSL證書實現https請求;為了滿足之前http請求不受影響,在nginx上面不僅配置了https的443埠的監聽,同時監聽了80埠。通過瀏覽器測試確實是沒有問題,但是在寫程式碼時,java程式碼發起get,post請求的時候,出現了“301 Moved Permanently”的錯誤;網上也沒有搜尋到好的解決方案,經過一下午的分析,找到了一個突破口,但是總覺得並不是一個好的方式,再此分享一下,如果有人能有更好的方式解決此問題,煩請告知一下。
問題追蹤
獲取HeaderFields
當我們通過一個http的地址得到一個URLConnection連線之後;通過getHeaderFields()獲取這個連線的響應頭,程式碼如下:String urlName = url + "?" + param; URL realUrl = new URL(urlName); // 開啟和URL之間的連線 URLConnection conn = realUrl.openConnection(); Map<String, List<String>> map = conn.
如果是http的請求我們可以看到如下資訊:
這裡給出了新的重定向後的地址;如果是https的請求,就不會出現這個Location欄位;並且能正常請求成功,效果如下:
瀏覽器能正常請求個人認為是在出現錯誤之後,瀏覽器發現存在新地址Location欄位;就取到了新地址重新發起了一次新的請求從而實現了正常的響應。
解決方案
既然上面說道瀏覽器檢測到Location欄位,拿到新的地址重新發起了一次新的請求,那麼程式碼也同樣是可以這麼實現的,因此調整了程式碼,寫了如下工具類:import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.URL; import java.net.URLConnection; import java.util.List; import java.util.Locale; import java.util.Map; import org.apache.commons.httpclient.util.HttpURLConnection; import org.apache.http.ParseException; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpPost; 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; public class HttpClientUtil { /** * 向指定URL傳送GET方法的請求 * * @param url * 傳送請求的URL * @param param * 請求引數,請求引數應該是name1=value1&name2=value2的形式。 * @return URL所代表遠端資源的響應 */ public static String sendGet(String url, String param) { String result = ""; BufferedReader in = null; try { String urlName = url + "?" + param; URL realUrl = new URL(urlName); // 開啟和URL之間的連線 URLConnection conn = realUrl.openConnection(); String newUrl = urlName; Map<String, List<String>> map = conn.getHeaderFields(); // 遍歷所有的響應頭欄位 for (String key : map.keySet()) { //如果發現有重定向了新的地址 if ("Location".equals(key)) { //獲取新地址 newUrl = map.get(key).get(0) + "?" + param; break; } } // 重新例項化url物件 realUrl = new URL(newUrl); // 重新開啟和URL之間的連線 conn = realUrl.openConnection(); // 設定通用的請求屬性 conn.setRequestProperty("accept", "*/*"); conn.setRequestProperty("connection", "Keep-Alive"); conn.setRequestProperty("Accept-Charset", "UTF-8"); conn.setRequestProperty("contentType", "UTF-8"); conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); conn.setRequestProperty("Content-type", "application/x-www-form-urlencoded"); conn.setRequestProperty("Accept-Language", Locale.getDefault().toString()); // 建立實際的連線 conn.connect(); // 定義BufferedReader輸入流來讀取URL的響應 in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8")); String line; while ((line = in.readLine()) != null) { result += line; } } catch (Exception e) { System.out.println("傳送GET請求出現異常!" + e); e.printStackTrace(); } // 使用finally塊來關閉輸入流 finally { try { if (in != null) { in.close(); } } catch (IOException ex) { ex.printStackTrace(); } } return result; } /** * post請求 */ public static String sendPost(String url, String param) { PrintWriter out = null; BufferedReader in = null; String result = ""; try { URL realUrl = new URL(url); // 開啟和URL之間的連 ? URLConnection conn = realUrl.openConnection(); Map<String, List<String>> map = conn.getHeaderFields(); // 遍歷所有的響應頭欄位 String newUrl = url; for (String key : map.keySet()) { //如果發現有重定向了新的地址 if ("Location".equals(key)) { //獲取新地址 newUrl = map.get(key).get(0); break; } } realUrl = new URL(newUrl); // 開啟和URL之間的連線 conn = realUrl.openConnection(); // 設定通用的請求屬 ? conn.setRequestProperty("accept", "*/*"); conn.setRequestProperty("connection", "Keep-Alive"); conn.setRequestProperty("Accept-Charset", "UTF-8"); conn.setRequestProperty("contentType", "UTF-8"); conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); conn.setRequestProperty("Content-type", "application/x-www-form-urlencoded;charset=UTF-8"); conn.setRequestProperty("Accept-Language", Locale.getDefault().toString()); // 發起POST請求必須設定如下兩行 conn.setDoOutput(true); conn.setDoInput(true); // 獲取URLConnection物件對應的輸出流 out = new PrintWriter(new OutputStreamWriter(conn.getOutputStream(), "UTF-8")); // 發 ?請求引數 out.print(param); // flush輸出流的緩衝 out.flush(); // 定義BufferedReader輸入流來讀取URL的響應 in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8")); String line; while ((line = in.readLine()) != null) { result += line; } } catch (Exception e) { e.printStackTrace(); } // 使用finally塊來關閉輸出流 ?輸入 ? finally { try { if (out != null) { out.close(); } if (in != null) { in.close(); } } catch (IOException ex) { ex.printStackTrace(); } } return result; } }
總結
雖說通過調整客戶端請求的時候通過調整,實現重定向的功能,但是我認為這並不是最好的解決方式;個人是希望能通過nginx那塊的配置實現http到https的重定向,從而不必要修改客戶端請求時的程式碼即可完成這塊的動作,如果有那位大牛知道怎麼做,煩請留言告知,萬分感謝!