All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.firefly.codec.http2.hpack.MetaDataBuilder Maven / Gradle / Ivy

There is a newer version: 4.0.3.2
Show newest version
package com.firefly.codec.http2.hpack;

import com.firefly.codec.http2.model.BadMessageException;
import com.firefly.codec.http2.model.HostPortHttpField;
import com.firefly.codec.http2.model.HttpField;
import com.firefly.codec.http2.model.HttpFields;
import com.firefly.codec.http2.model.HttpScheme;
import com.firefly.codec.http2.model.HttpStatus;
import com.firefly.codec.http2.model.HttpVersion;
import com.firefly.codec.http2.model.MetaData;
import com.firefly.codec.http2.model.StaticTableHttpField;

public class MetaDataBuilder {
	private final int maxSize;
	private int size;
	private int status;
	private String method;
	private HttpScheme scheme;
	private HostPortHttpField authority;
	private String path;
	private long contentLength = Long.MIN_VALUE;

	private HttpFields fields = new HttpFields(10);

	/**
	 * @param maxHeadersSize
	 *            The maximum size of the headers, expressed as total name and
	 *            value characters.
	 */
	MetaDataBuilder(int maxHeadersSize) {
		maxSize = maxHeadersSize;
	}

	/**
	 * Get the maxSize.
	 * 
	 * @return the maxSize
	 */
	public int getMaxSize() {
		return maxSize;
	}

	/**
	 * Get the size.
	 * 
	 * @return the current size in bytes
	 */
	public int getSize() {
		return size;
	}

	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);
		}
	}

	public MetaData build() {
		try {
			HttpFields fields = this.fields;
			this.fields = new HttpFields(Math.max(10, fields.size() + 5));

			if (method != null)
				return new MetaData.Request(method, scheme, authority, path, HttpVersion.HTTP_2, fields, contentLength);
			if (status != 0)
				return new MetaData.Response(HttpVersion.HTTP_2, status, fields, contentLength);
			return new MetaData(HttpVersion.HTTP_2, fields, contentLength);
		} finally {
			status = 0;
			method = null;
			scheme = null;
			authority = null;
			path = null;
			size = 0;
			contentLength = Long.MIN_VALUE;
		}
	}

	/**
	 * Check that the max size will not be exceeded.
	 * 
	 * @param length
	 *            the length
	 * @param huffman
	 *            the huffman name
	 */
	public void checkSize(int length, boolean huffman) {
		// Apply a huffman fudge factor
		if (huffman)
			length = (length * 4) / 3;
		if ((size + length) > maxSize)
			throw new BadMessageException(HttpStatus.REQUEST_ENTITY_TOO_LARGE_413,
					"Header size " + (size + length) + ">" + maxSize);
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy