zoukankan      html  css  js  c++  java
  • HttpURLConnection 设置Host 头部无效

    最近做了一个服务,对外提供http接口,采用nginx反代,使用域名访问
    但是为了容灾,客户端需要指定ip访问该服务,如果该ip坏掉,客户端就切换到另个一ip(靠dns解析太慢)

    nginx上只配置了域名的分发,没有配置ip分发
    于是在http请求上做了点处理,url配置ip,同时配置http头部的Host参数为该域名,
    HttpURLConnection 有setRequestProperty(key,value)方法来设置http头部
    通过ip访问,设置Host头部来让nginx识别,然后分发到相应的处理程序

    代码如下

    HttpURLConnection urlConn = null;
    String url = "http://192.168.1.120/login?platform=xxx&type=account";
    URL destURL = new URL(url);
    urlConn = (HttpURLConnection) destURL.openConnection();
    urlConn.setConnectTimeout(10000);
    urlConn.setReadTimeout(10000);
    urlConn.setRequestProperty("Host", "auth.xxx.com");

    这里我们要访问192.168.1.120这个服务器的一个login服务,配置的域名是 auth.xxx.com
    嗯,本地测试ok,就发布到服务器上了。

    但是神奇的事情出现了,我们有5台服务器,其中2台可以,另外3台死活不行,总报错说404错误

    404说明客户端请求路径不存在,推测估计是Host没有生效。
    对比可以和不可以的两种服务器的环境,可以的jdk是 6U18,不可以的是6U24

    于是怀疑jdk升级的问题,在网上搜了搜,找了HttpURLConnection的sun的源代码

    http://javasourcecode.org/html/open-source/jdk/jdk-6u23/sun/net/www/protocol/http/HttpURLConnection.java.html

    发现里面 有一个 allowRestrictedHeaders 这个参数,原来api在设计的时候,可能为了安全,限制了程序能够使用的Http Header
    如,下面的都是限制的

    private static final String[] restrictedHeaders = {
        /* Restricted by XMLHttpRequest2 */
        //"Accept-Charset",
        //"Accept-Encoding",
        "Access-Control-Request-Headers",
        "Access-Control-Request-Method",
        "Connection", /* close is allowed */
        "Content-Length",
        //"Cookie",
        //"Cookie2",
        "Content-Transfer-Encoding",
        //"Date",
        "Expect",
        "Host",
        "Keep-Alive",
        "Origin",
        // "Referer", 
        // "TE",
        "Trailer",
        "Transfer-Encoding",
        "Upgrade",
        //"User-Agent",
        "Via"
        };
    
        allowRestrictedHeaders = ((Boolean)java.security.AccessController.doPrivileged(
            new sun.security.action.GetBooleanAction(
                "sun.net.http.allowRestrictedHeaders"))).booleanValue();

    里面就有我们要设置的Host,找到原因,就好解决了,只要告诉程序,允许能使用这些限制的头部即可

    System.setProperty("sun.net.http.allowRestrictedHeaders", "true");

    就ok了,搞定,收工。

    【总结】
    1.遇到同一份代码有的服务器可以,有的服务器不行的话,多半是环境问题,常见的环境问题有:
      语言环境,字符集编码(如UTF-8/GB2312,虚拟机版本,环境变量路径等

    2.没有找到6U18的代码,所以没有去找到底是哪个版本开始做了修改了。

  • 相关阅读:
    Windows性能计数器应用
    Azure Oracle Linux VNC 配置
    Azure 配置管理系列 Oracle Linux (PART6)
    Azure 配置管理系列 Oracle Linux (PART5)
    Azure 配置管理系列 Oracle Linux (PART4)
    Azure 配置管理系列 Oracle Linux (PART3)
    Azure 配置管理系列 Oracle Linux (PART2)
    vagrant多节点配置
    docker基本操作
    LINUX开启允许对外访问的网络端口命令
  • 原文地址:https://www.cnblogs.com/skyaccross/p/2828986.html
Copyright © 2011-2022 走看看