Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
package io.vertx.ext.web.impl;
import io.vertx.core.impl.logging.Logger;
import io.vertx.core.impl.logging.LoggerFactory;
import io.vertx.ext.web.ParsedHeaderValue;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
/**
* Build with the intent of following
* rfc7231,section-5.3.1's specification.
*/
public class HeaderParser {
private static final Logger LOG = LoggerFactory.getLogger(HeaderParser.class);
private static final Comparator HEADER_SORTER =
(ParsedHeaderValue left, ParsedHeaderValue right) -> right.weightedOrder() - left.weightedOrder();
/**
* Transforms each header value into the given ParsableHeaderValue
*
* @param unparsedHeaderValue The header to split
* @param objectCreator The type to instantiate for each header
* @return The list of (unparsed) parsable header value
*/
public static List convertToParsedHeaderValues(String unparsedHeaderValue, Function objectCreator) {
return split(unparsedHeaderValue, ',', objectCreator);
}
/**
* In-place sorting of the headers list
*
* @param headers
* @return The same object as inserted
*/
public static List sort(List headers) {
headers.sort(HEADER_SORTER);
return headers;
}
/**
* Parses a header value
*
* @param headerContent
* @param valueCallback
* @param weightCallback
* @param parameterCallback
*/
public static void parseHeaderValue(String headerContent, Consumer valueCallback, Consumer weightCallback, BiConsumer parameterCallback) {
int paramIndex = headerContent.indexOf(';');
if (paramIndex < 0) {
valueCallback.accept(headerContent);
} else {
// the whole value
valueCallback.accept(headerContent.substring(0, paramIndex));
if (paramIndex < headerContent.length()) {
split(headerContent.substring(paramIndex + 1), ';', part -> {
int idx = part.indexOf('=');
if (idx != -1) {
final String key = part.substring(0, idx);
final String val = part.substring(idx + 1);
if ("q".equalsIgnoreCase(key)) {
try {
weightCallback.accept(Float.parseFloat(val));
} catch (NumberFormatException e) {
if (LOG.isTraceEnabled())
LOG.trace("Found a \"q\" parameter with value \""+val+"\" that was unparsable");
}
} else {
parameterCallback.accept(key, unquote(val));
}
} else {
// no value associated with this key
parameterCallback.accept(part, null);
}
return null;
});
}
}
}
public static void parseMIME(
String headerContent,
Consumer componentCallback,
Consumer subcomponentCallback
) {
int slashIndex = headerContent.indexOf('/');
int paramIndex = headerContent.indexOf(';', slashIndex + 1);
if (slashIndex < 0) {
componentCallback.accept("*");
} else {
componentCallback.accept(headerContent.substring(0, slashIndex).toLowerCase());
}
if (paramIndex < 0) {
subcomponentCallback.accept(headerContent.substring(slashIndex + 1));
} else {
subcomponentCallback.accept(headerContent.substring(slashIndex + 1, paramIndex).toLowerCase());
}
}
public static List parseLanguageValue(String value) {
if (value == null || value.length() == 0) {
return Collections.emptyList();
}
final List parts = new LinkedList<>();
// state machine
int start = 0;
for (int i = 0; i < value.length(); i++) {
char ch = value.charAt(i);
// trim initial white space
if (start == i && ch == ' ') {
start++;
continue;
}
// splitting logic uses 2 chars, since java Locales use underscore
if (ch == '-' || ch == '_') {
int end = i;
// trim end white space
for (int j = i - 1; j >= start; j--) {
if (value.charAt(j) == ' ') {
end--;
continue;
}
break;
}
// ignore empty
if (end - start > 0) {
parts.add(value.substring(start, end));
if (parts.size() == 3) {
// force stop, we have country, language and variant
return parts;
}
}
start = i + 1;
}
}
// rest
if (start < value.length()) {
int end = value.length();
// trim end white space
for (int j = value.length() - 1; j >= start; j--) {
if (value.charAt(j) == ' ') {
end--;
continue;
}
break;
}
// ignore empty
if (end - start > 0) {
parts.add(value.substring(start, end));
}
}
return parts;
}
private static List split(String header, char split, Function factory) {
if (header == null || header.length() == 0) {
return Collections.emptyList();
}
final List parts = new LinkedList<>();
// state machine
boolean quote = false;
int start = 0;
char last = 0;
for (int i = 0; i < header.length(); i++) {
char ch = header.charAt(i);
// trim initial white space
if (start == i && ch == ' ') {
start++;
continue;
}
// identify if we're handling quoted strings
if (ch == '\"' && last != '\\') {
quote = !quote;
}
last = ch;
// splitting logic only applies outside quoted strings
if (!quote && ch == split) {
int end = i;
// trim end white space
for (int j = i - 1; j >= start; j--) {
if (header.charAt(j) == ' ') {
end--;
continue;
}
break;
}
// ignore empty
if (end - start > 0) {
parts.add(factory.apply(header.substring(start, end)));
}
start = i + 1;
}
}
// rest
if (start < header.length()) {
int end = header.length();
// trim end white space
for (int j = header.length() - 1; j >= start; j--) {
if (header.charAt(j) == ' ') {
end--;
continue;
}
break;
}
// ignore empty
if (end - start > 0) {
parts.add(factory.apply(header.substring(start, end)));
}
}
return parts;
}
private static String unquote(String value) {
if (value == null || value.length() == 0) {
return value;
}
StringBuilder sb = null;
int start = 0;
int end = value.length();
// adjust start if there is a quote
if (value.charAt(start) == '\"') {
start++;
}
// adjust end if there is a quote
if (value.charAt(end - 1) == '\"') {
end--;
}
// look for extra quotes in the value itself
for (int i = start ; i < end; i++) {
if (value.charAt(i) == '\\') {
if (sb == null) {
sb = new StringBuilder(value.substring(start, i));
}
continue;
}
if (sb != null) {
sb.append(value.charAt(i));
}
}
if (sb != null) {
return sb.toString();
} else {
// the value is quoted
if (end - start != value.length()) {
return value.substring(start, end);
}
return value;
}
}
}