blob: 3f12ecf4667da218d148bc3e8c70f769c06f1762 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.dubbo.metadata.extension.rest.api;
import org.apache.dubbo.common.utils.CollectionUtils;
import java.io.Serializable;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import static java.util.Collections.unmodifiableMap;
import static org.apache.dubbo.common.utils.PathUtils.normalize;
import static org.apache.dubbo.common.utils.StringUtils.SLASH;
import static org.apache.dubbo.common.utils.StringUtils.isBlank;
/**
* The metadata class for REST request
*
* @since 2.7.6
*/
public class RequestMetadata implements Serializable {
private static final long serialVersionUID = -240099840085329958L;
private String method;
private String path;
private Map<String, List<String>> params = new LinkedHashMap<>();
private Map<String, List<String>> headers = new LinkedHashMap<>();
private Set<String> consumes = new LinkedHashSet<>();
private Set<String> produces = new LinkedHashSet<>();
/**
* Default Constructor
*/
public RequestMetadata() {}
public String getMethod() {
return method;
}
public void setMethod(String method) {
this.method = method == null ? null : method.toUpperCase();
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = normalize(path);
if (!path.startsWith(SLASH)) {
this.path = SLASH + path;
}
}
public Map<String, List<String>> getParams() {
return unmodifiableMap(params);
}
public void setParams(Map<String, List<String>> params) {
params(params);
}
private static void add(Map<String, List<String>> multiValueMap, String key, String value) {
if (isBlank(key)) {
return;
}
List<String> values = get(multiValueMap, key, true);
values.add(value);
}
private static <T extends Collection<String>> void addAll(
Map<String, List<String>> multiValueMap, Map<String, T> source) {
for (Map.Entry<String, T> entry : source.entrySet()) {
String key = entry.getKey();
for (String value : entry.getValue()) {
add(multiValueMap, key, value);
}
}
}
private static String getFirst(Map<String, List<String>> multiValueMap, String key) {
List<String> values = get(multiValueMap, key);
return CollectionUtils.isNotEmpty(values) ? values.get(0) : null;
}
private static List<String> get(Map<String, List<String>> multiValueMap, String key) {
return get(multiValueMap, key, false);
}
private static List<String> get(Map<String, List<String>> multiValueMap, String key, boolean createIfAbsent) {
return createIfAbsent ? multiValueMap.computeIfAbsent(key, k -> new LinkedList<>()) : multiValueMap.get(key);
}
public Map<String, List<String>> getHeaders() {
return unmodifiableMap(headers);
}
public void setHeaders(Map<String, List<String>> headers) {
headers(headers);
}
public Set<String> getConsumes() {
return consumes;
}
public void setConsumes(Set<String> consumes) {
this.consumes = consumes;
}
public Set<String> getProduces() {
return produces;
}
public void setProduces(Set<String> produces) {
this.produces = produces;
}
public Set<String> getParamNames() {
return new HashSet<>(params.keySet());
}
public Set<String> getHeaderNames() {
return new HashSet<>(headers.keySet());
}
// public List<MediaType> getConsumeMediaTypes() {
// return toMediaTypes(consumes);
// }
//
// public List<MediaType> getProduceMediaTypes() {
// return toMediaTypes(produces);
// }
public String getParameter(String name) {
return getFirst(params, name);
}
public String getHeader(String name) {
return getFirst(headers, name);
}
public RequestMetadata addParam(String name, String value) {
add(params, name, value);
return this;
}
public RequestMetadata addHeader(String name, String value) {
add(headers, name, value);
return this;
}
private <T extends Collection<String>> RequestMetadata params(Map<String, T> params) {
addAll(this.params, params);
return this;
}
private <T extends Collection<String>> RequestMetadata headers(Map<String, List<String>> headers) {
if (headers != null && !headers.isEmpty()) {
Map<String, List<String>> httpHeaders = new LinkedHashMap<>();
// Add all headers
addAll(httpHeaders, headers);
// Handles "Content-Type" and "Accept" headers if present
// mediaTypes(httpHeaders, HttpHeaders.CONTENT_TYPE, this.consumes);
// mediaTypes(httpHeaders, HttpHeaders.ACCEPT, this.produces);
this.headers.putAll(httpHeaders);
}
return this;
}
public void appendContextPathFromUrl(String contextPathFromUrl) {
if (contextPathFromUrl == null) {
return;
}
setPath(contextPathFromUrl + path);
}
public boolean methodAllowed(String method) {
return method != null && method.equals(this.method);
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof RequestMetadata)) {
return false;
}
RequestMetadata that = (RequestMetadata) o;
return Objects.equals(method, that.method)
&& Objects.equals(path, that.path)
&& Objects.equals(consumes, that.consumes)
&& Objects.equals(produces, that.produces)
&&
// Metadata should not compare the values
Objects.equals(getParamNames(), that.getParamNames())
&& Objects.equals(getHeaderNames(), that.getHeaderNames());
}
@Override
public int hashCode() {
// The values of metadata should not use for the hashCode() method
return Objects.hash(method, path, consumes, produces, getParamNames(), getHeaderNames());
}
@Override
public String toString() {
return "RequestMetadata{" + "method='" + method + '\'' + ", path='" + path + '\''
+ ", params=" + params + ", headers=" + headers + ", consumes=" + consumes
+ ", produces=" + produces + '}';
}
}