Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 180|回复: 0

[默认分类] Error parsing HTTP request header Note: further occurrences of HTTP header parsing errors

[复制链接]
  • TA的每日心情
    开心
    2021-12-13 21:45
  • 签到天数: 15 天

    [LV.4]偶尔看看III

    发表于 2018-6-11 11:02:45 | 显示全部楼层 |阅读模式


      tomcat进行http request解析的时候报错,并将错误返回给客户端了,具体的错误如下:
    1. org.apache.coyote.http11.AbstractHttp11Processor.process Error parsing HTTP request header
    2. Note: further occurrences of HTTP header parsing errors will be logged at DEBUG level.
    复制代码

      查看对应的类代码,其中涉及的方法如下:
    1. public SocketState process(SocketWrapper<S> socketWrapper)
    2.     throws IOException {
    3.     RequestInfo rp = request.getRequestProcessor();
    4.     rp.setStage(org.apache.coyote.Constants.STAGE_PARSE);
    5.     // Setting up the I/O
    6.     setSocketWrapper(socketWrapper);
    7.     getInputBuffer().init(socketWrapper, endpoint);
    8.     getOutputBuffer().init(socketWrapper, endpoint);
    9.     // Flags
    10.     keepAlive = true;
    11.     comet = false;
    12.     openSocket = false;
    13.     sendfileInProgress = false;
    14.     readComplete = true;
    15.     if (endpoint.getUsePolling()) {
    16.       keptAlive = false;
    17.     } else {
    18.       keptAlive = socketWrapper.isKeptAlive();
    19.     }
    20.     if (disableKeepAlive()) {
    21.       socketWrapper.setKeepAliveLeft(0);
    22.     }
    23.     while (!getErrorState().isError() && keepAlive && !comet && !isAsync() &&
    24.         httpUpgradeHandler == null && !endpoint.isPaused()) {
    25.       // Parsing the request header
    26.       try {
    27.         setRequestLineReadTimeout();
    28.         if (!getInputBuffer().parseRequestLine(keptAlive)) {
    29.           if (handleIncompleteRequestLineRead()) {
    30.             break;
    31.           }
    32.         }
    33.         if (endpoint.isPaused()) {
    34.           // 503 - Service unavailable
    35.           response.setStatus(503);
    36.           setErrorState(ErrorState.CLOSE_CLEAN, null);
    37.         } else {
    38.           keptAlive = true;
    39.           // Set this every time in case limit has been changed via JMX
    40.           request.getMimeHeaders().setLimit(endpoint.getMaxHeaderCount());
    41.           // Currently only NIO will ever return false here
    42.           if (!getInputBuffer().parseHeaders()) {
    43.             // We"ve read part of the request, don"t recycle it
    44.             // instead associate it with the socket
    45.             openSocket = true;
    46.             readComplete = false;
    47.             break;
    48.           }
    49.           if (!disableUploadTimeout) {
    50.             setSocketTimeout(connectionUploadTimeout);
    51.           }
    52.         }
    53.       } catch (IOException e) {
    54.         if (getLog().isDebugEnabled()) {
    55.           getLog().debug(
    56.               sm.getString("http11processor.header.parse"), e);
    57.         }
    58.         setErrorState(ErrorState.CLOSE_NOW, e);
    59.         break;
    60.       } catch (Throwable t) {
    61.         ExceptionUtils.handleThrowable(t);
    62.         UserDataHelper.Mode logMode = userDataHelper.getNextMode();
    63.         if (logMode != null) {
    64.           String message = sm.getString(
    65.               "http11processor.header.parse");
    66.           switch (logMode) {
    67.             case INFO_THEN_DEBUG:
    68.               message += sm.getString(
    69.                   "http11processor.fallToDebug");
    70.               //$FALL-THROUGH$
    71.             case INFO:
    72.               getLog().info(message);
    73.               break;
    74.             case DEBUG:
    75.               getLog().debug(message);
    76.           }
    77.         }
    78.         // 400 - Bad Request
    79.         response.setStatus(400);
    80.         setErrorState(ErrorState.CLOSE_CLEAN, t);
    81.         getAdapter().log(request, response, 0);
    82.       }
    83.       if (!getErrorState().isError()) {
    84.         // Setting up filters, and parse some request headers
    85.         rp.setStage(org.apache.coyote.Constants.STAGE_PREPARE);
    86.         try {
    87.           prepareRequest();
    88.         } catch (Throwable t) {
    89.           ExceptionUtils.handleThrowable(t);
    90.           if (getLog().isDebugEnabled()) {
    91.             getLog().debug(sm.getString(
    92.                 "http11processor.request.prepare"), t);
    93.           }
    94.           // 500 - Internal Server Error
    95.           response.setStatus(500);
    96.           setErrorState(ErrorState.CLOSE_CLEAN, t);
    97.           getAdapter().log(request, response, 0);
    98.         }
    99.       }
    100.       if (maxKeepAliveRequests == 1) {
    101.         keepAlive = false;
    102.       } else if (maxKeepAliveRequests > 0 &&
    103.           socketWrapper.decrementKeepAlive() <= 0) {
    104.         keepAlive = false;
    105.       }
    106.       // Process the request in the adapter
    107.       if (!getErrorState().isError()) {
    108.         try {
    109.           rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);
    110.           getAdapter().service(request, response);
    111.           // Handle when the response was committed before a serious
    112.           // error occurred.  Throwing a ServletException should both
    113.           // set the status to 500 and set the errorException.
    114.           // If we fail here, then the response is likely already
    115.           // committed, so we can"t try and set headers.
    116.           if(keepAlive && !getErrorState().isError() && (
    117.               response.getErrorException() != null ||
    118.                   (!isAsync() &&
    119.                   statusDropsConnection(response.getStatus())))) {
    120.             setErrorState(ErrorState.CLOSE_CLEAN, null);
    121.           }
    122.           setCometTimeouts(socketWrapper);
    123.         } catch (InterruptedIOException e) {
    124.           setErrorState(ErrorState.CLOSE_NOW, e);
    125.         } catch (HeadersTooLargeException e) {
    126.           // The response should not have been committed but check it
    127.           // anyway to be safe
    128.           if (response.isCommitted()) {
    129.             setErrorState(ErrorState.CLOSE_NOW, e);
    130.           } else {
    131.             response.reset();
    132.             response.setStatus(500);
    133.             setErrorState(ErrorState.CLOSE_CLEAN, e);
    134.             response.setHeader("Connection", "close"); // TODO: Remove
    135.           }
    136.         } catch (Throwable t) {
    137.           ExceptionUtils.handleThrowable(t);
    138.           getLog().error(sm.getString(
    139.               "http11processor.request.process"), t);
    140.           // 500 - Internal Server Error
    141.           response.setStatus(500);
    142.           setErrorState(ErrorState.CLOSE_CLEAN, t);
    143.           getAdapter().log(request, response, 0);
    144.         }
    145.       }
    146.       // Finish the handling of the request
    147.       rp.setStage(org.apache.coyote.Constants.STAGE_ENDINPUT);
    148.       if (!isAsync() && !comet) {
    149.         if (getErrorState().isError()) {
    150.           // If we know we are closing the connection, don"t drain
    151.           // input. This way uploading a 100GB file doesn"t tie up the
    152.           // thread if the servlet has rejected it.
    153.           getInputBuffer().setSwallowInput(false);
    154.         } else if (expectation &&
    155.             (response.getStatus() < 200 || response.getStatus() > 299)) {
    156.           // Client sent Expect: 100-continue but received a
    157.           // non-2xx final response. Disable keep-alive (if enabled)
    158.           // to ensure that the connection is closed. Some clients may
    159.           // still send the body, some may send the next request.
    160.           // No way to differentiate, so close the connection to
    161.           // force the client to send the next request.
    162.           getInputBuffer().setSwallowInput(false);
    163.           keepAlive = false;
    164.         }
    165.         endRequest();
    166.       }
    167.       rp.setStage(org.apache.coyote.Constants.STAGE_ENDOUTPUT);
    168.       // If there was an error, make sure the request is counted as
    169.       // and error, and update the statistics counter
    170.       if (getErrorState().isError()) {
    171.         response.setStatus(500);
    172.       }
    173.       request.updateCounters();
    174.       if (!isAsync() && !comet || getErrorState().isError()) {
    175.         if (getErrorState().isIoAllowed()) {
    176.           getInputBuffer().nextRequest();
    177.           getOutputBuffer().nextRequest();
    178.         }
    179.       }
    180.       if (!disableUploadTimeout) {
    181.         if(endpoint.getSoTimeout() > 0) {
    182.           setSocketTimeout(endpoint.getSoTimeout());
    183.         } else {
    184.           setSocketTimeout(0);
    185.         }
    186.       }
    187.       rp.setStage(org.apache.coyote.Constants.STAGE_KEEPALIVE);
    188.       if (breakKeepAliveLoop(socketWrapper)) {
    189.         break;
    190.       }
    191.     }
    192.     rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);
    193.     if (getErrorState().isError() || endpoint.isPaused()) {
    194.       return SocketState.CLOSED;
    195.     } else if (isAsync() || comet) {
    196.       return SocketState.LONG;
    197.     } else if (isUpgrade()) {
    198.       return SocketState.UPGRADING;
    199.     } else {
    200.       if (sendfileInProgress) {
    201.         return SocketState.SENDFILE;
    202.       } else {
    203.         if (openSocket) {
    204.           if (readComplete) {
    205.             return SocketState.OPEN;
    206.           } else {
    207.             return SocketState.LONG;
    208.           }
    209.         } else {
    210.           return SocketState.CLOSED;
    211.         }
    212.       }
    213.     }
    214.   }
    复制代码

      而报错的地方则是在:
    1. // Currently only NIO will ever return false here
    2.           if (!getInputBuffer().parseHeaders()) {
    3.             // We"ve read part of the request, don"t recycle it
    4.             // instead associate it with the socket
    5.             openSocket = true;
    6.             readComplete = false;
    7.             break;
    8.           }
    9.           if (!disableUploadTimeout) {
    10.             setSocketTimeout(connectionUploadTimeout);
    11.           }
    12. 的时候抛出了异常,对应的catch块代码如下:
    13. catch (Throwable t) {
    14.         ExceptionUtils.handleThrowable(t);
    15.         UserDataHelper.Mode logMode = userDataHelper.getNextMode();
    16.         if (logMode != null) {
    17.           String message = sm.getString(
    18.               "http11processor.header.parse");
    19.           switch (logMode) {
    20.             case INFO_THEN_DEBUG:
    21.               message += sm.getString(
    22.                   "http11processor.fallToDebug");
    23.               //$FALL-THROUGH$
    24.             case INFO:
    25.               getLog().info(message);
    26.               break;
    27.             case DEBUG:
    28.               getLog().debug(message);
    29.           }
    30.         }
    31.         // 400 - Bad Request
    32.         response.setStatus(400);
    33.         setErrorState(ErrorState.CLOSE_CLEAN, t);
    34.         getAdapter().log(request, response, 0);
    35.       }
    复制代码

      错误日志的输出,是配置在LocalStrings.properties中的,相关的两个属性:
    1. http11processor.fallToDebug=\n Note\: further occurrences of HTTP header parsing errors will be logged at DEBUG level.
    2. http11processor.header.parse=Error parsing HTTP request header
    复制代码

      找到对应的 getInputBuffer().parseHeaders()
    1. public boolean parseHeaders()
    2.     throws IOException {
    3.     if (!parsingHeader) {
    4.       throw new IllegalStateException(
    5.           sm.getString("iib.parseheaders.ise.error"));
    6.     }
    7.     HeaderParseStatus status = HeaderParseStatus.HAVE_MORE_HEADERS;
    8.     do {
    9.       status = parseHeader();
    10.       // Checking that
    11.       // (1) Headers plus request line size does not exceed its limit
    12.       // (2) There are enough bytes to avoid expanding the buffer when
    13.       // reading body
    14.       // Technically, (2) is technical limitation, (1) is logical
    15.       // limitation to enforce the meaning of headerBufferSize
    16.       // From the way how buf is allocated and how blank lines are being
    17.       // read, it should be enough to check (1) only.
    18.       if (pos > headerBufferSize
    19.           || buf.length - pos < socketReadBufferSize) {
    20.         throw new IllegalArgumentException(
    21.             sm.getString("iib.requestheadertoolarge.error"));
    22.       }
    23.     } while ( status == HeaderParseStatus.HAVE_MORE_HEADERS );
    24.     if (status == HeaderParseStatus.DONE) {
    25.       parsingHeader = false;
    26.       end = pos;
    27.       return true;
    28.     } else {
    29.       return false;
    30.     }
    31.   }
    复制代码

    1. 可知此处涉及了两个缓冲区大小,headerBufferSize和socketReadBufferSize,如果读取时数据的长度大于这两个值,就会报iib.requestheadertoolarge.error即Request header is too large,在网上搜索时,有的是因为这个设置导致的400,解决方法就是修改Tomcat的server.xml,
    2. 在<Connector port="8080" protocol="HTTP/1.1"
    3. connectionTimeout="20000"    redirectPort="8443" />的配置中增加maxHttpHeaderSize的配置
    复制代码

      在org.apache.coyote.http11.AbstractHttp11Protocol类中定义了其默认值:
    1. /**
    2. Maximum size of the HTTP message header.  */
    3. private int maxHttpHeaderSize = 8 * 1024;
    4. /**
    5. Maximum size of the post which will be saved when processing certain  requests, such as a POST. */
    6. private int maxSavePostSize = 4 * 1024;
    7. /**
    8. * Specifies a different (usually  longer) connection timeout during data  upload. */
    9. private int connectionUploadTimeout = 300000;
    10. /**
    11. Maximum size of trailing headers in bytes */
    12. private int maxTrailerSize = 8192;
    13. /**
    14. Maximum size of extension information in chunked encoding */
    15. private int maxExtensionSize = 8192;
    16. /**Maximum amount of request body to swallow.*/
    17. private int maxSwallowSize = 2 * 1024 * 1024;
    复制代码

      其他参数设置介绍: http://tomcat.apache.org/tomcat-8.0-doc/config/ajp.html
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-2-24 10:09 , Processed in 0.481279 second(s), 35 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表