public void emit(HttpField field) {
    int field_size = field.getName().length() + field.getValue().length();
    size += field_size;
    if (size > maxSize)
      throw new BadMessageException(
          HttpStatus.REQUEST_ENTITY_TOO_LARGE_413, "Header size " + size + ">" + maxSize);

    if (field instanceof StaticTableHttpField) {
      StaticTableHttpField value = (StaticTableHttpField) field;
      switch (field.getHeader()) {
        case C_STATUS:
          status = (Integer) value.getStaticValue();
          break;

        case C_METHOD:
          method = field.getValue();
          break;

        case C_SCHEME:
          scheme = (HttpScheme) value.getStaticValue();
          break;

        default:
          throw new IllegalArgumentException(field.getName());
      }
    } else if (field.getHeader() != null) {
      switch (field.getHeader()) {
        case C_STATUS:
          status = field.getIntValue();
          break;

        case C_METHOD:
          method = field.getValue();
          break;

        case C_SCHEME:
          scheme = HttpScheme.CACHE.get(field.getValue());
          break;

        case C_AUTHORITY:
          authority =
              (field instanceof HostPortHttpField)
                  ? ((HostPortHttpField) field)
                  : new AuthorityHttpField(field.getValue());
          break;

        case HOST:
          // :authority fields must come first. If we have one, ignore the
          // host header as far as authority goes.
          if (authority == null)
            authority =
                (field instanceof HostPortHttpField)
                    ? ((HostPortHttpField) field)
                    : new AuthorityHttpField(field.getValue());
          fields.add(field);
          break;

        case C_PATH:
          path = field.getValue();
          break;

        case CONTENT_LENGTH:
          contentLength = field.getLongValue();
          fields.add(field);
          break;

        default:
          if (field.getName().charAt(0) != ':') fields.add(field);
      }
    } else {
      if (field.getName().charAt(0) != ':') fields.add(field);
    }
  }
示例#2
0
  /*
   * Parse the message headers and return true if the handler has signaled for
   * a return
   */
  protected boolean parseHeaders(ByteBuffer buffer) {
    boolean handle = false;

    // Process headers
    while (_state.ordinal() < State.CONTENT.ordinal() && buffer.hasRemaining() && !handle) {
      // process each character
      byte ch = next(buffer);
      if (ch == 0) break;

      if (_maxHeaderBytes > 0 && ++_headerBytes > _maxHeaderBytes) {
        log.warn("Header is too large > {}", _maxHeaderBytes);
        throw new BadMessageException(HttpStatus.REQUEST_ENTITY_TOO_LARGE_413);
      }

      switch (_state) {
        case HEADER:
          switch (ch) {
            case HttpTokens.COLON:
            case HttpTokens.SPACE:
            case HttpTokens.TAB:
              throw new BadMessageException(HttpStatus.BAD_REQUEST_400, "Bad Continuation");

            case HttpTokens.LINE_FEED:
              {
                _contentPosition = 0;

                // End of headers!

                // Was there a required host header?
                if (!_host && _version == HttpVersion.HTTP_1_1 && _requestHandler != null) {
                  throw new BadMessageException(HttpStatus.BAD_REQUEST_400, "No Host");
                }

                // is it a response that cannot have a body?
                if (_responseHandler != null
                    && // response
                    (_responseStatus == 304
                        || // not-modified response
                        _responseStatus == 204
                        || // no-content
                        // response
                        _responseStatus < 200)) // 1xx response
                _endOfContent = EndOfContent.NO_CONTENT; // ignore any
                // other
                // headers
                // set

                // else if we don't know framing
                else if (_endOfContent == EndOfContent.UNKNOWN_CONTENT) {
                  if (_responseStatus == 0 // request
                      || _responseStatus == 304 // not-modified
                      // response
                      || _responseStatus == 204 // no-content response
                      || _responseStatus < 200) // 1xx response
                  _endOfContent = EndOfContent.NO_CONTENT;
                  else _endOfContent = EndOfContent.EOF_CONTENT;
                }

                // How is the message ended?
                switch (_endOfContent) {
                  case EOF_CONTENT:
                    setState(State.EOF_CONTENT);
                    handle = _handler.headerComplete() || handle;
                    return handle;

                  case CHUNKED_CONTENT:
                    setState(State.CHUNKED_CONTENT);
                    handle = _handler.headerComplete() || handle;
                    return handle;

                  case NO_CONTENT:
                    handle = _handler.headerComplete() || handle;
                    setState(State.END);
                    handle = _handler.messageComplete() || handle;
                    return handle;

                  default:
                    setState(State.CONTENT);
                    handle = _handler.headerComplete() || handle;
                    return handle;
                }
              }

            default:
              {
                // now handle the ch
                if (ch <= HttpTokens.SPACE) throw new BadMessageException();

                if (buffer.hasRemaining()) {
                  // Try a look ahead for the known header name and value.
                  HttpField field =
                      _connectionFields == null
                          ? null
                          : _connectionFields.getBest(buffer, -1, buffer.remaining());
                  if (field == null) field = CACHE.getBest(buffer, -1, buffer.remaining());

                  if (field != null) {
                    final String n;
                    final String v;

                    if (_strict) {
                      // Have to get the fields exactly from the
                      // buffer to match case
                      String fn = field.getName();
                      String fv = field.getValue();
                      n =
                          BufferUtils.toString(
                              buffer,
                              buffer.position() - 1,
                              fn.length(),
                              StandardCharsets.US_ASCII);
                      if (fv == null) v = null;
                      else {
                        v =
                            BufferUtils.toString(
                                buffer,
                                buffer.position() + fn.length() + 1,
                                fv.length(),
                                StandardCharsets.ISO_8859_1);
                        field = new HttpField(field.getHeader(), n, v);
                      }
                    } else {
                      n = field.getName();
                      v = field.getValue();
                    }

                    _header = field.getHeader();
                    _headerString = n;

                    if (v == null) {
                      // Header only
                      setState(State.HEADER_VALUE);
                      _string.setLength(0);
                      _length = 0;
                      buffer.position(buffer.position() + n.length() + 1);
                      break;
                    } else {
                      // Header and value
                      int pos = buffer.position() + n.length() + v.length() + 1;
                      byte b = buffer.get(pos);

                      if (b == HttpTokens.CARRIAGE_RETURN || b == HttpTokens.LINE_FEED) {
                        _field = field;
                        _valueString = v;
                        setState(State.HEADER_IN_VALUE);

                        if (b == HttpTokens.CARRIAGE_RETURN) {
                          _cr = true;
                          buffer.position(pos + 1);
                        } else buffer.position(pos);
                        break;
                      } else {
                        setState(State.HEADER_IN_VALUE);
                        setString(v);
                        buffer.position(pos);
                        break;
                      }
                    }
                  }
                }

                // New header
                setState(State.HEADER_IN_NAME);
                _string.setLength(0);
                _string.append((char) ch);
                _length = 1;
              }
          }
          break;

        case HEADER_IN_NAME:
          if (ch == HttpTokens.COLON) {
            if (_headerString == null) {
              _headerString = takeString();
              _header = HttpHeader.CACHE.get(_headerString);
            }
            _length = -1;

            setState(State.HEADER_VALUE);
            break;
          }

          if (ch > HttpTokens.SPACE) {
            if (_header != null) {
              setString(_header.asString());
              _header = null;
              _headerString = null;
            }

            _string.append((char) ch);
            if (ch > HttpTokens.SPACE) _length = _string.length();
            break;
          }

          throw new IllegalCharacterException(_state, ch, buffer);

        case HEADER_VALUE:
          if (ch > HttpTokens.SPACE || ch < 0) {
            _string.append((char) (0xff & ch));
            _length = _string.length();
            setState(State.HEADER_IN_VALUE);
            break;
          }

          if (ch == HttpTokens.SPACE || ch == HttpTokens.TAB) break;

          if (ch == HttpTokens.LINE_FEED) {
            _value = null;
            _string.setLength(0);
            _valueString = null;
            _length = -1;

            parsedHeader();
            setState(State.HEADER);
            break;
          }
          throw new IllegalCharacterException(_state, ch, buffer);

        case HEADER_IN_VALUE:
          if (ch >= HttpTokens.SPACE || ch < 0 || ch == HttpTokens.TAB) {
            if (_valueString != null) {
              setString(_valueString);
              _valueString = null;
              _field = null;
            }
            _string.append((char) (0xff & ch));
            if (ch > HttpTokens.SPACE || ch < 0) _length = _string.length();
            break;
          }

          if (ch == HttpTokens.LINE_FEED) {
            if (_length > 0) {
              _value = null;
              _valueString = takeString();
              _length = -1;
            }
            parsedHeader();
            setState(State.HEADER);
            break;
          }

          throw new IllegalCharacterException(_state, ch, buffer);

        default:
          throw new IllegalStateException(_state.toString());
      }
    }

    return handle;
  }