cc.shacocloud.mirage.web.http.HttpHeaderMap Maven / Gradle / Ivy
package cc.shacocloud.mirage.web.http;
import cc.shacocloud.mirage.utils.HttpMethodUtils;
import cc.shacocloud.mirage.web.exception.HttpMediaTypeNotAcceptableException;
import cc.shacocloud.mirage.web.exception.InvalidMediaTypeException;
import io.vertx.core.MultiMap;
import io.vertx.core.http.HttpMethod;
import org.jetbrains.annotations.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.util.*;
import static io.vertx.core.http.HttpHeaders.*;
public class HttpHeaderMap implements MultiMap {
private final MultiMap headerMap;
public static final List MEDIA_TYPE_ALL_LIST = Collections.singletonList(MediaType.ALL);
public HttpHeaderMap(MultiMap headerMap) {
this.headerMap = headerMap;
}
/**
* 返回媒体类型的身体,由指定 {@code Content-Type}首部
*/
public MediaType getContentType() {
String value = get(CONTENT_TYPE);
return (StringUtils.hasLength(value) ? MediaType.parseMediaType(value) : null);
}
/**
* 设置主体的{@linkplain MediaType},由{@code Content-Type}头指定。
*/
public void setContentType(@Nullable MediaType mediaType) {
if (mediaType != null) {
Assert.isTrue(!mediaType.isWildcardType(), "内容类型不能包含通配符类型 '*'");
Assert.isTrue(!mediaType.isWildcardSubtype(), "内容类型不能包含通配符子类型 '*'");
set(CONTENT_TYPE, mediaType.toString());
} else {
remove(CONTENT_TYPE);
}
}
/**
* 返回主体的长度(以字节为单位),由{@code Content-Length}头指定。
*
* 当内容长度未知时返回-1。
*/
public long getContentLength() {
String value = get(CONTENT_LENGTH);
return (value != null ? Long.parseLong(value) : -1);
}
/**
* 设置主体的长度(以字节为单位),由{@code Content-Length}头指定。
*/
public void setContentLength(long contentLength) {
set(CONTENT_LENGTH, Long.toString(contentLength));
}
/**
* 获取可接受的媒体类型
*
* @throws HttpMediaTypeNotAcceptableException 如果无法解析请求的媒体类型则抛出该例外
*/
public List getAcceptableMediaTypes() throws HttpMediaTypeNotAcceptableException {
List headerValues = getAll(ACCEPT);
if (headerValues == null || headerValues.isEmpty()) {
return MEDIA_TYPE_ALL_LIST;
}
try {
List mediaTypes = MediaType.parseMediaTypes(headerValues);
MediaType.sortBySpecificityAndQuality(mediaTypes);
return !CollectionUtils.isEmpty(mediaTypes) ? mediaTypes : MEDIA_TYPE_ALL_LIST;
} catch (InvalidMediaTypeException ex) {
throw new HttpMediaTypeNotAcceptableException(
"不能解析'Accept'头" + headerValues + ": " + ex.getMessage());
}
}
/**
* 设置{@code Origin}头的(新)值。
*/
public void setOrigin(@Nullable String origin) {
setOrRemove(ORIGIN, origin);
}
/**
* 返回{@code Origin}头的值。
*/
@Nullable
public String getOrigin() {
return get(ORIGIN);
}
/**
* 返回{@code Access-Control-Request-Method}请求头的值。
*/
@Nullable
public HttpMethod getAccessControlRequestMethod() {
return HttpMethodUtils.resolve(get(ACCESS_CONTROL_REQUEST_METHOD));
}
/**
* 返回{@code Access-Control-Request-Headers}请求头的值。
*/
public List getAccessControlRequestHeaders() {
return getAll(ACCESS_CONTROL_REQUEST_HEADERS);
}
/**
* 设置响应头{@code Access-Control-Allow-Origin}的(新)值。
*/
public void setAccessControlAllowOrigin(@Nullable String allowedOrigin) {
setOrRemove(ACCESS_CONTROL_ALLOW_ORIGIN, allowedOrigin);
}
/**
* 设置响应头{@code Access-Control-Allow-Methods}的(新)值。
*/
public void setAccessControlAllowMethods(List allowedMethods) {
set(ACCESS_CONTROL_ALLOW_METHODS, StringUtils.collectionToCommaDelimitedString(allowedMethods));
}
/**
* 设置响应头{@code Access-Control-Allow-Headers}的(新)值。
*/
public void setAccessControlAllowHeaders(List allowedHeaders) {
set(ACCESS_CONTROL_ALLOW_HEADERS, String.join(",", allowedHeaders));
}
/**
* 设置响应头{@code Access-Control-Expose-Headers}的(新)值。
*/
public void setAccessControlExposeHeaders(List exposedHeaders) {
set(ACCESS_CONTROL_EXPOSE_HEADERS, String.join(",", exposedHeaders));
}
/**
* 设置响应头{@code Access-Control-Allow-Credentials}的(新)值。
*/
public void setAccessControlAllowCredentials(boolean allowCredentials) {
set(ACCESS_CONTROL_ALLOW_CREDENTIALS, Boolean.toString(allowCredentials));
}
/**
* 设置响应头{@code Access-Control-Max-Age}的(新)值。
*/
public void setAccessControlMaxAge(long maxAge) {
set(ACCESS_CONTROL_MAX_AGE, Long.toString(maxAge));
}
/**
* 当前连接是否 keep-alive
*/
public boolean isKeepAlive() {
return KEEP_ALIVE.equals(get(CONNECTION));
}
// ---------------- 工具方法------------------------------------
/**
* 返回包含的键的集合视图
*/
public Set keySet() {
Set res = new HashSet<>();
this.iterator().forEachRemaining(entry -> res.add(entry.getKey()));
return Collections.unmodifiableSet(res);
}
/**
* 设置给定的头值,或删除头如果{@code null}。
*
* @param headerName 标题名称
* @param headerValue 头值,或{@code null}表示none
*/
private void setOrRemove(CharSequence headerName, @Nullable CharSequence headerValue) {
if (headerValue != null) {
set(headerName, headerValue);
} else {
remove(headerName);
}
}
// ------------------ MultiMap ---------------------------------------------------
@Override
public String get(CharSequence name) {
return headerMap.get(name);
}
@Override
public String get(String name) {
return headerMap.get(name);
}
@Override
public List getAll(String name) {
return headerMap.getAll(name);
}
@Override
public List getAll(CharSequence name) {
return headerMap.getAll(name);
}
@Override
public boolean contains(String name) {
return headerMap.contains(name);
}
@Override
public boolean contains(CharSequence name) {
return headerMap.contains(name);
}
@Override
public boolean isEmpty() {
return headerMap.isEmpty();
}
@Override
public Set names() {
return headerMap.names();
}
@Override
public MultiMap add(String name, String value) {
return headerMap.add(name, value);
}
@Override
public MultiMap add(CharSequence name, CharSequence value) {
return headerMap.add(name, value);
}
@Override
public MultiMap add(String name, Iterable values) {
return headerMap.add(name, values);
}
@Override
public MultiMap add(CharSequence name, Iterable values) {
return headerMap.add(name, values);
}
@Override
public MultiMap addAll(MultiMap map) {
return headerMap.addAll(map);
}
@Override
public MultiMap addAll(Map headers) {
return headerMap.addAll(headers);
}
@Override
public MultiMap set(String name, String value) {
return headerMap.set(name, value);
}
@Override
public MultiMap set(CharSequence name, CharSequence value) {
return headerMap.set(name, value);
}
@Override
public MultiMap set(String name, Iterable values) {
return headerMap.set(name, values);
}
@Override
public MultiMap set(CharSequence name, Iterable values) {
return headerMap.set(name, values);
}
@Override
public MultiMap setAll(MultiMap map) {
return headerMap.setAll(map);
}
@Override
public MultiMap setAll(Map headers) {
return headerMap.setAll(headers);
}
@Override
public MultiMap remove(String name) {
return headerMap.remove(name);
}
@Override
public MultiMap remove(CharSequence name) {
return headerMap.remove(name);
}
@Override
public MultiMap clear() {
return headerMap.clear();
}
@Override
public int size() {
return headerMap.size();
}
@Override
public Iterator> iterator() {
return headerMap.iterator();
}
@Override
public String toString() {
return "{\n" +
headerMap +
"}";
}
}