spring HeadersRequestCondition 源码
spring HeadersRequestCondition 代码
文件路径:/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/condition/HeadersRequestCondition.java
/*
* Copyright 2002-2021 the original author or authors.
*
* 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
*
* https://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 org.springframework.web.servlet.mvc.condition;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.lang.Nullable;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.cors.CorsUtils;
/**
* A logical conjunction ({@code ' && '}) request condition that matches a request against
* a set of header expressions with syntax defined in {@link RequestMapping#headers()}.
*
* <p>Expressions passed to the constructor with header names 'Accept' or
* 'Content-Type' are ignored. See {@link ConsumesRequestCondition} and
* {@link ProducesRequestCondition} for those.
*
* @author Arjen Poutsma
* @author Rossen Stoyanchev
* @since 3.1
*/
public final class HeadersRequestCondition extends AbstractRequestCondition<HeadersRequestCondition> {
private static final HeadersRequestCondition PRE_FLIGHT_MATCH = new HeadersRequestCondition();
private final Set<HeaderExpression> expressions;
/**
* Create a new instance from the given header expressions. Expressions with
* header names 'Accept' or 'Content-Type' are ignored. See {@link ConsumesRequestCondition}
* and {@link ProducesRequestCondition} for those.
* @param headers media type expressions with syntax defined in {@link RequestMapping#headers()};
* if 0, the condition will match to every request
*/
public HeadersRequestCondition(String... headers) {
this.expressions = parseExpressions(headers);
}
private static Set<HeaderExpression> parseExpressions(String... headers) {
Set<HeaderExpression> result = null;
if (!ObjectUtils.isEmpty(headers)) {
for (String header : headers) {
HeaderExpression expr = new HeaderExpression(header);
if ("Accept".equalsIgnoreCase(expr.name) || "Content-Type".equalsIgnoreCase(expr.name)) {
continue;
}
result = (result != null ? result : new LinkedHashSet<>(headers.length));
result.add(expr);
}
}
return (result != null ? result : Collections.emptySet());
}
private HeadersRequestCondition(Set<HeaderExpression> conditions) {
this.expressions = conditions;
}
/**
* Return the contained request header expressions.
*/
public Set<NameValueExpression<String>> getExpressions() {
return new LinkedHashSet<>(this.expressions);
}
@Override
protected Collection<HeaderExpression> getContent() {
return this.expressions;
}
@Override
protected String getToStringInfix() {
return " && ";
}
/**
* Returns a new instance with the union of the header expressions
* from "this" and the "other" instance.
*/
@Override
public HeadersRequestCondition combine(HeadersRequestCondition other) {
if (isEmpty() && other.isEmpty()) {
return this;
}
else if (other.isEmpty()) {
return this;
}
else if (isEmpty()) {
return other;
}
Set<HeaderExpression> set = new LinkedHashSet<>(this.expressions);
set.addAll(other.expressions);
return new HeadersRequestCondition(set);
}
/**
* Returns "this" instance if the request matches all expressions;
* or {@code null} otherwise.
*/
@Override
@Nullable
public HeadersRequestCondition getMatchingCondition(HttpServletRequest request) {
if (CorsUtils.isPreFlightRequest(request)) {
return PRE_FLIGHT_MATCH;
}
for (HeaderExpression expression : this.expressions) {
if (!expression.match(request)) {
return null;
}
}
return this;
}
/**
* Compare to another condition based on header expressions. A condition
* is considered to be a more specific match, if it has:
* <ol>
* <li>A greater number of expressions.
* <li>A greater number of non-negated expressions with a concrete value.
* </ol>
* <p>It is assumed that both instances have been obtained via
* {@link #getMatchingCondition(HttpServletRequest)} and each instance
* contains the matching header expression only or is otherwise empty.
*/
@Override
public int compareTo(HeadersRequestCondition other, HttpServletRequest request) {
int result = other.expressions.size() - this.expressions.size();
if (result != 0) {
return result;
}
return (int) (getValueMatchCount(other.expressions) - getValueMatchCount(this.expressions));
}
private long getValueMatchCount(Set<HeaderExpression> expressions) {
long count = 0;
for (HeaderExpression e : expressions) {
if (e.getValue() != null && !e.isNegated()) {
count++;
}
}
return count;
}
/**
* Parses and matches a single header expression to a request.
*/
static class HeaderExpression extends AbstractNameValueExpression<String> {
HeaderExpression(String expression) {
super(expression);
}
@Override
protected boolean isCaseSensitiveName() {
return false;
}
@Override
protected String parseValue(String valueExpression) {
return valueExpression;
}
@Override
protected boolean matchName(HttpServletRequest request) {
return (request.getHeader(this.name) != null);
}
@Override
protected boolean matchValue(HttpServletRequest request) {
return ObjectUtils.nullSafeEquals(this.value, request.getHeader(this.name));
}
}
}
相关信息
相关文章
spring AbstractMediaTypeExpression 源码
spring AbstractNameValueExpression 源码
spring AbstractRequestCondition 源码
spring CompositeRequestCondition 源码
spring ConsumesRequestCondition 源码
spring ParamsRequestCondition 源码
0
赞
热门推荐
-
2、 - 优质文章
-
3、 gate.io
-
8、 golang
-
9、 openharmony
-
10、 Vue中input框自动聚焦