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

io.datakernel.http.HttpHeaderValue Maven / Gradle / Ivy

/*
 * Copyright (C) 2015-2018 SoftIndex LLC.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.datakernel.http;

import io.datakernel.bytebuf.ByteBuf;
import io.datakernel.bytebuf.ByteBufPool;
import io.datakernel.bytebuf.ByteBufStrings;
import io.datakernel.exception.ParseException;
import org.jetbrains.annotations.NotNull;

import java.time.Instant;
import java.util.List;

import static io.datakernel.bytebuf.ByteBufStrings.*;
import static io.datakernel.http.HttpUtils.trimAndDecodePositiveInt;
import static java.util.Arrays.asList;

@SuppressWarnings("WeakerAccess")
public abstract class HttpHeaderValue {
	abstract int estimateSize();

	abstract void writeTo(@NotNull ByteBuf buf);

	@Override
	@NotNull
	public abstract String toString();

	@NotNull
	public static HttpHeaderValue of(@NotNull String string) {
		return new HttpHeaderValueOfString(string);
	}

	@NotNull
	public static HttpHeaderValue ofBytes(@NotNull byte[] array, int offset, int size) {
		return new HttpHeaderValueOfBytes(array, offset, size);
	}

	@NotNull
	public static HttpHeaderValue ofBytes(@NotNull byte[] array) {
		return ofBytes(array, 0, array.length);
	}

	@NotNull
	public static HttpHeaderValue ofDecimal(int value) {
		return new HttpHeaderValueOfUnsignedDecimal(value);
	}

	@NotNull
	public static HttpHeaderValue ofAcceptCharsets(@NotNull List charsets) {
		return new HttpHeaderValueOfCharsets(charsets);
	}

	@NotNull
	public static HttpHeaderValue ofAcceptCharsets(@NotNull AcceptCharset... charsets) {
		return ofAcceptCharsets(asList(charsets));
	}

	@NotNull
	public static HttpHeaderValue ofInstant(@NotNull Instant date) {
		return new HttpHeaderValueOfDate(date.getEpochSecond());
	}

	@NotNull
	public static HttpHeaderValue ofTimestamp(long timestamp) {
		return new HttpHeaderValueOfDate(timestamp / 1000L);
	}

	@NotNull
	public static HttpHeaderValue ofAcceptMediaTypes(@NotNull List type) {
		return new HttpHeaderValueOfAcceptMediaTypes(type);
	}

	@NotNull
	public static HttpHeaderValue ofAcceptMediaTypes(@NotNull AcceptMediaType... types) {
		return ofAcceptMediaTypes(asList(types));
	}

	@NotNull
	public static HttpHeaderValue ofContentType(@NotNull ContentType type) {
		return new HttpHeaderValueOfContentType(type);
	}

	public static int toPositiveInt(@NotNull ByteBuf buf) throws ParseException {
		return trimAndDecodePositiveInt(buf.array(), buf.head(), buf.readRemaining());
	}

	@NotNull
	public static ContentType toContentType(@NotNull ByteBuf buf) throws ParseException {
		return ContentType.parse(buf.array(), buf.head(), buf.readRemaining());
	}

	@NotNull
	public static Instant toInstant(@NotNull ByteBuf buf) throws ParseException {
		return Instant.ofEpochSecond(HttpDate.parse(buf.array(), buf.head()));
	}

	@NotNull
	public ByteBuf getBuf() {
		int estimatedSize = estimateSize();
		ByteBuf buf = ByteBuf.wrapForWriting(new byte[estimatedSize]);
		writeTo(buf);
		return buf;
	}

	@FunctionalInterface
	public interface ParserIntoList {
		void parse(@NotNull ByteBuf buf, @NotNull List into) throws ParseException;
	}

	public static void toAcceptContentTypes(@NotNull ByteBuf buf, @NotNull List into) throws ParseException {
		AcceptMediaType.parse(buf.array(), buf.head(), buf.readRemaining(), into);
	}

	public static void toAcceptCharsets(@NotNull ByteBuf buf, @NotNull List into) throws ParseException {
		AcceptCharset.parse(buf.array(), buf.head(), buf.readRemaining(), into);
	}

	static void toSimpleCookies(@NotNull ByteBuf buf, @NotNull List into) throws ParseException {
		HttpCookie.parseSimple(buf.array(), buf.head(), buf.tail(), into);
	}

	static void toFullCookies(@NotNull ByteBuf buf, @NotNull List into) throws ParseException {
		HttpCookie.parseFull(buf.array(), buf.head(), buf.tail(), into);
	}

	static final class HttpHeaderValueOfContentType extends HttpHeaderValue {
		@NotNull
		private ContentType type;

		HttpHeaderValueOfContentType(@NotNull ContentType type) {
			this.type = type;
		}

		@Override
		public int estimateSize() {
			return type.size();
		}

		@Override
		public void writeTo(@NotNull ByteBuf buf) {
			ContentType.render(type, buf);
		}

		@NotNull
		@Override
		public String toString() {
			ByteBuf buf = ByteBufPool.allocate(estimateSize());
			ContentType.render(type, buf);
			return ByteBufStrings.asAscii(buf);
		}
	}

	static final class HttpHeaderValueOfAcceptMediaTypes extends HttpHeaderValue {
		@NotNull
		private final List types;

		HttpHeaderValueOfAcceptMediaTypes(@NotNull List types) {
			this.types = types;
		}

		@Override
		public int estimateSize() {
			int size = 0;
			for (AcceptMediaType type : types) {
				size += type.estimateSize() + 2;
			}
			return size;
		}

		@Override
		public void writeTo(@NotNull ByteBuf buf) {
			AcceptMediaType.render(types, buf);
		}

		@NotNull
		@Override
		public String toString() {
			ByteBuf buf = ByteBufPool.allocate(estimateSize());
			AcceptMediaType.render(types, buf);
			return ByteBufStrings.asAscii(buf);
		}
	}

	static final class HttpHeaderValueOfSimpleCookies extends HttpHeaderValue {
		@NotNull
		final List cookies;

		HttpHeaderValueOfSimpleCookies(@NotNull List cookies) {
			this.cookies = cookies;
		}

		@Override
		int estimateSize() {
			int size = 0;
			for (HttpCookie cookie : cookies) {
				size += cookie.getName().length();
				size += cookie.getValue() == null ? 0 : cookie.getValue().length() + 1;
			}
			size += (cookies.size() - 1) * 2; // semicolons and spaces
			return size;
		}

		@Override
		void writeTo(@NotNull ByteBuf buf) {
			HttpCookie.renderSimple(cookies, buf);
		}

		@NotNull
		@Override
		public String toString() {
			ByteBuf buf = ByteBufPool.allocate(estimateSize());
			HttpCookie.renderSimple(cookies, buf);
			return ByteBufStrings.asAscii(buf);
		}
	}

	static final class HttpHeaderValueOfSetCookies extends HttpHeaderValue {
		@NotNull
		final HttpCookie cookie;

		HttpHeaderValueOfSetCookies(@NotNull HttpCookie cookie) {
			this.cookie = cookie;
		}

		@Override
		int estimateSize() {
			int size = 0;
			size += cookie.getName().length();
			size += cookie.getValue() == null ? 0 : cookie.getValue().length() + 1;
			size += cookie.getDomain() == null ? 0 : cookie.getDomain().length() + 10;
			size += cookie.getPath() == null ? 0 : cookie.getPath().length() + 6;
			size += cookie.getExtension() == null ? 0 : cookie.getExtension().length();
			size += 102;
			return size;
		}

		@Override
		void writeTo(@NotNull ByteBuf buf) {
			cookie.renderFull(buf);
		}

		@NotNull
		@Override
		public String toString() {
			ByteBuf buf = ByteBufPool.allocate(estimateSize());
			cookie.renderFull(buf);
			return ByteBufStrings.asAscii(buf);
		}
	}

	static final class HttpHeaderValueOfCharsets extends HttpHeaderValue {
		@NotNull
		private final List charsets;

		HttpHeaderValueOfCharsets(@NotNull List charsets) {
			this.charsets = charsets;
		}

		@Override
		int estimateSize() {
			int size = 0;
			for (AcceptCharset charset : charsets) {
				size += charset.estimateSize() + 2;
			}
			return size;
		}

		@Override
		void writeTo(@NotNull ByteBuf buf) {
			AcceptCharset.render(charsets, buf);
		}

		@NotNull
		@Override
		public String toString() {
			ByteBuf buf = ByteBufPool.allocate(estimateSize());
			AcceptCharset.render(charsets, buf);
			return ByteBufStrings.asAscii(buf);
		}
	}

	static final class HttpHeaderValueOfDate extends HttpHeaderValue {
		private final long epochSeconds;

		HttpHeaderValueOfDate(long epochSeconds) {
			this.epochSeconds = epochSeconds;
		}

		@Override
		int estimateSize() {
			return 29;
		}

		@Override
		void writeTo(@NotNull ByteBuf buf) {
			HttpDate.render(epochSeconds, buf);
		}

		@NotNull
		@Override
		public String toString() {
			ByteBuf buf = ByteBufPool.allocate(estimateSize());
			HttpDate.render(epochSeconds, buf);
			return ByteBufStrings.asAscii(buf);
		}
	}

	static final class HttpHeaderValueOfUnsignedDecimal extends HttpHeaderValue {
		private final int value;

		HttpHeaderValueOfUnsignedDecimal(int value) {
			this.value = value;
		}

		@Override
		int estimateSize() {
			return 10; // Integer.toString(Integer.MAX_VALUE).length();
		}

		@Override
		void writeTo(@NotNull ByteBuf buf) {
			putPositiveInt(buf, value);
		}

		@NotNull
		@Override
		public String toString() {
			return Integer.toString(value);
		}
	}

	static final class HttpHeaderValueOfString extends HttpHeaderValue {
		@NotNull
		private final String string;

		HttpHeaderValueOfString(@NotNull String string) {
			this.string = string;
		}

		@Override
		int estimateSize() {
			return string.length();
		}

		@Override
		void writeTo(@NotNull ByteBuf buf) {
			putAscii(buf, string);
		}

		@NotNull
		@Override
		public String toString() {
			return string;
		}
	}

	static final class HttpHeaderValueOfBytes extends HttpHeaderValue {
		@NotNull
		private final byte[] array;
		private final int offset;
		private final int size;

		HttpHeaderValueOfBytes(@NotNull byte[] array, int offset, int size) {
			this.array = array;
			this.offset = offset;
			this.size = size;
		}

		@Override
		int estimateSize() {
			return size;
		}

		@Override
		void writeTo(@NotNull ByteBuf buf) {
			buf.put(array, offset, size);
		}

		@NotNull
		@Override
		public ByteBuf getBuf() {
			return ByteBuf.wrap(array, offset, offset + size);
		}

		@NotNull
		@Override
		public String toString() {
			return decodeAscii(array, offset, size);
		}
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy