[OLINGO-659] Introduced HttpHeader for ODataResponse/Request
This commit is contained in:
parent
b82294e1e8
commit
f2c7be2d12
|
@ -18,10 +18,15 @@
|
|||
******************************************************************************/
|
||||
package org.apache.olingo.commons.api.http;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* HTTP header constants.
|
||||
*/
|
||||
public interface HttpHeader {
|
||||
public class HttpHeader {
|
||||
|
||||
/**
|
||||
* See {@link <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1">HTTP/1.1 documentation</a>}.
|
||||
|
@ -176,4 +181,107 @@ public interface HttpHeader {
|
|||
public static final String ODATA_MAX_VERSION = "OData-MaxVersion";
|
||||
/** Custom Header defined in the OData standard. */
|
||||
public static final String ODATA_ENTITY_ID = "OData-EntityID";
|
||||
|
||||
private final String name;
|
||||
private final Collection<String> values;
|
||||
|
||||
/**
|
||||
* Create header for given name
|
||||
* @param name of header
|
||||
*/
|
||||
public HttpHeader(String name) {
|
||||
this.name = name;
|
||||
this.values = new ArrayList<String>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create header for given name and add given values
|
||||
* @param name of header
|
||||
* @param values values for header
|
||||
*/
|
||||
public HttpHeader(String name, Collection<String> values) {
|
||||
this(name);
|
||||
this.values.addAll(values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get name of header (not the canonical name)
|
||||
* @return name of header
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all values for this header
|
||||
* @return all header values
|
||||
*/
|
||||
public Collection<String> getValues() {
|
||||
return Collections.unmodifiableCollection(values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add header value
|
||||
*
|
||||
* @param value value to be added
|
||||
* @return this header object (fluent interface)
|
||||
*/
|
||||
public HttpHeader addValue(String value) {
|
||||
this.values.add(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add header values
|
||||
*
|
||||
* @param values values to be added
|
||||
* @return this header object (fluent interface)
|
||||
*/
|
||||
public HttpHeader addValues(Collection<String> values) {
|
||||
this.values.addAll(values);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the canonical name of header
|
||||
* @return canonical name of header
|
||||
*/
|
||||
public String getCanonicalName() {
|
||||
return createCanonicalName(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the canonical name based on given name parameter
|
||||
*
|
||||
* @param name name which is canonicalised
|
||||
* @return canonical name
|
||||
*/
|
||||
public static String createCanonicalName(String name) {
|
||||
return name.toLowerCase(Locale.ROOT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
HttpHeader that = (HttpHeader) o;
|
||||
|
||||
if (!name.equals(that.name)) {
|
||||
return false;
|
||||
}
|
||||
return values.equals(that.values);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = name.hashCode();
|
||||
result = 31 * result + values.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,134 @@
|
|||
/*******************************************************************************
|
||||
* 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.olingo.commons.api.http;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
/**
|
||||
* HttpHeader container
|
||||
*/
|
||||
public class HttpHeaders {
|
||||
private final Map<String, HttpHeader> headers = new TreeMap<String, HttpHeader>();
|
||||
|
||||
/**
|
||||
* Add a header with given name and value.
|
||||
* If header with name already exists the value is added to this header.
|
||||
*
|
||||
* @param name name of header
|
||||
* @param value value for header
|
||||
* @return this container (fluent interface)
|
||||
*/
|
||||
public HttpHeaders addHeader(String name, String value) {
|
||||
HttpHeader eh = grantHeader(name);
|
||||
eh.addValue(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a header with given name and values.
|
||||
* If header with name already exists the values are added to this header.
|
||||
*
|
||||
* @param name name of header
|
||||
* @param values values for header
|
||||
* @return this container (fluent interface)
|
||||
*/
|
||||
public HttpHeaders addHeader(String name, Collection<String> values) {
|
||||
HttpHeader eh = grantHeader(name);
|
||||
eh.addValues(values);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a header with given name and value.
|
||||
* If header with name already exists the old header is replaced with the new one.
|
||||
*
|
||||
* @param name name of header
|
||||
* @param value value for header
|
||||
* @return this container (fluent interface)
|
||||
*/
|
||||
public HttpHeaders setHeader(String name, String value) {
|
||||
removeHeader(name);
|
||||
|
||||
HttpHeader eh = grantHeader(name);
|
||||
eh.addValue(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get header for given name.
|
||||
*
|
||||
* @param name name of header requested
|
||||
* @return corresponding header
|
||||
*/
|
||||
public HttpHeader getHeader(String name) {
|
||||
return headers.get(HttpHeader.createCanonicalName(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove header for given name.
|
||||
*
|
||||
* @param name name of header to be removed
|
||||
* @return header which was removed or null if no header was known for this name
|
||||
*/
|
||||
public HttpHeader removeHeader(String name) {
|
||||
return headers.remove(HttpHeader.createCanonicalName(name));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get all headers.
|
||||
*
|
||||
* @return all headers
|
||||
*/
|
||||
public Collection<HttpHeader> getHeaders() {
|
||||
return Collections.unmodifiableCollection(headers.values());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all header names.
|
||||
*
|
||||
* @return all header names
|
||||
*/
|
||||
public Collection<String> getHeaderNames() {
|
||||
Collection<String> headerNames = new ArrayList<String>();
|
||||
for (HttpHeader header : headers.values()) {
|
||||
headerNames.add(header.getName());
|
||||
}
|
||||
return headerNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get or create a header for given name.
|
||||
*
|
||||
* @return new or known header
|
||||
*/
|
||||
private HttpHeader grantHeader(String name) {
|
||||
String key = HttpHeader.createCanonicalName(name);
|
||||
HttpHeader eh = headers.get(key);
|
||||
if(eh == null) {
|
||||
eh = new HttpHeader(name);
|
||||
headers.put(key, eh);
|
||||
}
|
||||
return eh;
|
||||
}
|
||||
}
|
|
@ -20,11 +20,14 @@ package org.apache.olingo.server.api;
|
|||
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.olingo.commons.api.http.HttpHeader;
|
||||
import org.apache.olingo.commons.api.http.HttpHeaders;
|
||||
import org.apache.olingo.commons.api.http.HttpMethod;
|
||||
|
||||
/**
|
||||
|
@ -32,7 +35,7 @@ import org.apache.olingo.commons.api.http.HttpMethod;
|
|||
*/
|
||||
public class ODataRequest {
|
||||
private HttpMethod method;
|
||||
private Map<String, List<String>> headers = new HashMap<String, List<String>>();
|
||||
private HttpHeaders headers = new HttpHeaders();
|
||||
private InputStream body;
|
||||
private String rawQueryPath;
|
||||
private String rawRequestUri;
|
||||
|
@ -66,18 +69,7 @@ public class ODataRequest {
|
|||
* @see <a href="http://ietf.org/rfc/rfc7230.txt">RFC 7230, section 3.2.2</a>
|
||||
*/
|
||||
public void addHeader(final String name, final List<String> values) {
|
||||
String key = name.toUpperCase();
|
||||
if (headers.containsKey(key)) {
|
||||
List<String> oldValues = headers.get(key);
|
||||
|
||||
List<String> newValues = new ArrayList<String>();
|
||||
newValues.addAll(oldValues);
|
||||
newValues.addAll(values);
|
||||
|
||||
headers.put(name.toUpperCase(), newValues);
|
||||
} else {
|
||||
headers.put(name.toUpperCase(), values);
|
||||
}
|
||||
headers.addHeader(name, values);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -86,7 +78,11 @@ public class ODataRequest {
|
|||
* @return the header value(s) or null if not found
|
||||
*/
|
||||
public List<String> getHeaders(final String name) {
|
||||
return headers.get(name.toUpperCase());
|
||||
HttpHeader h = headers.getHeader(name);
|
||||
if(h == null) {
|
||||
return null;//Collections.emptyList();
|
||||
}
|
||||
return new ArrayList<String>(h.getValues());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -104,7 +100,14 @@ public class ODataRequest {
|
|||
* @return an unmodifiable Map of header names/values
|
||||
*/
|
||||
public Map<String, List<String>> getAllHeaders() {
|
||||
return Collections.unmodifiableMap(headers);
|
||||
Collection<HttpHeader> allHeader = headers.getHeaders();
|
||||
Map<String, List<String>> result = new HashMap<String, List<String>>();
|
||||
|
||||
for (HttpHeader httpHeader : allHeader) {
|
||||
result.put(httpHeader.getName(), new ArrayList<String>(httpHeader.getValues()));
|
||||
}
|
||||
|
||||
return Collections.unmodifiableMap(result);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -19,10 +19,13 @@
|
|||
package org.apache.olingo.server.api;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.olingo.commons.api.http.HttpHeader;
|
||||
import org.apache.olingo.commons.api.http.HttpHeaders;
|
||||
import org.apache.olingo.commons.api.http.HttpStatusCode;
|
||||
|
||||
/**
|
||||
|
@ -31,7 +34,7 @@ import org.apache.olingo.commons.api.http.HttpStatusCode;
|
|||
public class ODataResponse {
|
||||
|
||||
private int statusCode = HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode();
|
||||
private final Map<String, String> headers = new HashMap<String, String>();
|
||||
private final HttpHeaders headers = new HttpHeaders();
|
||||
private InputStream content;
|
||||
|
||||
/**
|
||||
|
@ -56,7 +59,7 @@ public class ODataResponse {
|
|||
* @param value the value
|
||||
*/
|
||||
public void setHeader(final String name, final String value) {
|
||||
headers.put(name, value);
|
||||
headers.setHeader(name, value);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -64,7 +67,12 @@ public class ODataResponse {
|
|||
* @return an unmodifiable Map of header names/values
|
||||
*/
|
||||
public Map<String, String> getHeaders() {
|
||||
return Collections.unmodifiableMap(headers);
|
||||
Map<String, String> result = new HashMap<String, String>();
|
||||
Collection<HttpHeader> allHeaders = headers.getHeaders();
|
||||
for (HttpHeader header : allHeaders) {
|
||||
result.put(header.getName(), header.getValues().iterator().next());
|
||||
}
|
||||
return Collections.unmodifiableMap(result);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -86,7 +86,7 @@ public class DebugTabRequestTest extends AbstractDebugTabTest {
|
|||
@Test
|
||||
public void singleHeaderValue() throws Exception {
|
||||
String expectedJson =
|
||||
"{\"method\":\"GET\",\"uri\":\"def&\",\"protocol\":\"def&\",\"headers\":{\"HEADERNAME\":\"Value1\"}}";
|
||||
"{\"method\":\"GET\",\"uri\":\"def&\",\"protocol\":\"def&\",\"headers\":{\"HeaderName\":\"Value1\"}}";
|
||||
String expectedHtml = "<h2>Request Method</h2>\n"
|
||||
+ "<p>GET</p>\n"
|
||||
+ "<h2>Request URI</h2>\n"
|
||||
|
@ -99,7 +99,7 @@ public class DebugTabRequestTest extends AbstractDebugTabTest {
|
|||
+ "<tr><th class=\"name\">Name</th><th class=\"value\">Value</th></tr>\n"
|
||||
+ "</thead>\n"
|
||||
+ "<tbody>\n"
|
||||
+ "<tr><td class=\"name\">HEADERNAME</td><td class=\"value\">Value1</td></tr>\n"
|
||||
+ "<tr><td class=\"name\">HeaderName</td><td class=\"value\">Value1</td></tr>\n"
|
||||
+ "</tbody>\n"
|
||||
+ "</table>\n";
|
||||
|
||||
|
@ -120,7 +120,7 @@ public class DebugTabRequestTest extends AbstractDebugTabTest {
|
|||
@Test
|
||||
public void multiHeaderValueResultsInMap() throws Exception {
|
||||
String expectedJson = "{\"method\":\"GET\",\"uri\":\"def&\",\"protocol\":\"def&\","
|
||||
+ "\"headers\":{\"HEADERNAME\":[\"Value1\",\"Value2\"]}}";
|
||||
+ "\"headers\":{\"HeaderName\":[\"Value1\",\"Value2\"]}}";
|
||||
String expectedHtml = "<h2>Request Method</h2>\n"
|
||||
+ "<p>GET</p>\n"
|
||||
+ "<h2>Request URI</h2>\n"
|
||||
|
@ -133,8 +133,8 @@ public class DebugTabRequestTest extends AbstractDebugTabTest {
|
|||
+ "<tr><th class=\"name\">Name</th><th class=\"value\">Value</th></tr>\n"
|
||||
+ "</thead>\n"
|
||||
+ "<tbody>\n"
|
||||
+ "<tr><td class=\"name\">HEADERNAME</td><td class=\"value\">Value1</td></tr>\n"
|
||||
+ "<tr><td class=\"name\">HEADERNAME</td><td class=\"value\">Value2</td></tr>\n"
|
||||
+ "<tr><td class=\"name\">HeaderName</td><td class=\"value\">Value1</td></tr>\n"
|
||||
+ "<tr><td class=\"name\">HeaderName</td><td class=\"value\">Value2</td></tr>\n"
|
||||
+ "</tbody>\n"
|
||||
+ "</table>\n";
|
||||
|
||||
|
|
Loading…
Reference in New Issue