001 002package io.vrap.rmf.base.client; 003 004import java.net.MalformedURLException; 005import java.net.URI; 006import java.net.URL; 007import java.nio.charset.StandardCharsets; 008import java.util.HashMap; 009import java.util.Map; 010import java.util.Optional; 011 012import org.apache.commons.lang3.builder.EqualsBuilder; 013import org.apache.commons.lang3.builder.HashCodeBuilder; 014import org.apache.commons.lang3.builder.ToStringBuilder; 015 016public class ApiHttpRequest extends Base implements ContextAware<ApiHttpRequest> { 017 018 private ApiHttpMethod method; 019 private URI uri; 020 private ApiHttpHeaders headers; 021 private byte[] body; 022 023 private Map<Object, Object> contextMap = new HashMap<>(); 024 025 public ApiHttpRequest() { 026 } 027 028 public ApiHttpRequest(final ApiHttpMethod method, final URI uri, final ApiHttpHeaders headers, final byte[] body, 029 final Map<Object, Object> contextMap) { 030 this.method = method; 031 this.uri = uri; 032 this.headers = headers; 033 this.body = body; 034 this.contextMap = contextMap; 035 } 036 037 public ApiHttpRequest(final ApiHttpMethod method, final URI uri, final ApiHttpHeaders headers, final byte[] body) { 038 this.method = method; 039 this.uri = uri; 040 this.headers = headers; 041 this.body = body; 042 } 043 044 public ApiHttpRequest(final ApiHttpRequest r) { 045 this.method = r.method; 046 this.uri = r.uri; 047 this.headers = r.headers; 048 this.body = r.body; 049 this.contextMap = r.contextMap; 050 } 051 052 public Map<Object, Object> getContextMap() { 053 return contextMap; 054 } 055 056 public ApiHttpRequest withContextMap(final Map<Object, Object> contextMap) { 057 final ApiHttpRequest request = copy(); 058 request.contextMap = new HashMap<>(contextMap); 059 060 return request; 061 } 062 063 @SuppressWarnings("unchecked") 064 public <T> T getContext(Class<T> key) { 065 return (T) contextMap.get(key); 066 } 067 068 public <T> ApiHttpRequest addContext(T value) { 069 final ApiHttpRequest request = copy(); 070 final Map<Object, Object> contextMap = new HashMap<>(request.contextMap); 071 contextMap.put(value.getClass(), value); 072 if (value instanceof ClassReferenceContext) { 073 contextMap.put(((ClassReferenceContext) value).classReference(), value); 074 } 075 076 request.contextMap = contextMap; 077 078 return request; 079 } 080 081 public Object getContext(Object key) { 082 return contextMap.get(key); 083 } 084 085 public ApiHttpRequest addContext(Object key, Object value) { 086 final ApiHttpRequest request = copy(); 087 final Map<Object, Object> contextMap = new HashMap<>(request.contextMap); 088 contextMap.put(key, value); 089 request.contextMap = contextMap; 090 091 return request; 092 } 093 094 public ApiHttpMethod getMethod() { 095 return method; 096 } 097 098 public ApiHttpRequest withMethod(final ApiHttpMethod method) { 099 ApiHttpRequest request = copy(); 100 request.method = method; 101 102 return request; 103 } 104 105 public ApiHttpHeaders getHeaders() { 106 if (headers == null) { 107 this.headers = new ApiHttpHeaders(); 108 } 109 return headers; 110 } 111 112 public ApiHttpRequest addHeader(final String key, final String value) { 113 ApiHttpRequest request = copy(); 114 request.headers = getHeaders().addHeader(key, value); 115 116 return request; 117 } 118 119 public ApiHttpRequest withHeaders(final ApiHttpHeaders headers) { 120 ApiHttpRequest request = copy(); 121 request.headers = headers; 122 return request; 123 } 124 125 public ApiHttpRequest withHeader(final String key, final String value) { 126 ApiHttpRequest request = copy(); 127 request.headers = getHeaders().withHeader(key, value); 128 129 return request; 130 } 131 132 public ApiHttpRequest withoutHeader(final String key) { 133 ApiHttpRequest request = copy(); 134 request.headers = getHeaders().withoutHeader(key); 135 136 return request; 137 } 138 139 public byte[] getBody() { 140 return body; 141 } 142 143 public ApiHttpRequest withBody(final byte[] body) { 144 ApiHttpRequest request = copy(); 145 request.body = body; 146 return request; 147 } 148 149 public ApiHttpRequest withBody(final String body) { 150 ApiHttpRequest request = copy(); 151 if (body == null) { 152 request.body = null; 153 } 154 else { 155 request.body = body.getBytes(StandardCharsets.UTF_8); 156 } 157 158 return request; 159 } 160 161 public URI getUri() { 162 return uri; 163 } 164 165 public URL getUrl() { 166 try { 167 return uri.toURL(); 168 } 169 catch (MalformedURLException e) { 170 throw new IllegalStateException("Malformed URI", e); 171 } 172 } 173 174 public ApiHttpRequest withUri(final String uri) { 175 ApiHttpRequest request = copy(); 176 request.uri = URI.create(uri); 177 return request; 178 } 179 180 public ApiHttpRequest withUri(final URI uri) { 181 ApiHttpRequest request = copy(); 182 request.uri = uri; 183 184 return request; 185 } 186 187 public ApiHttpRequest resolve(final URI baseUri) { 188 return withUri(baseUri.resolve(this.uri)); 189 } 190 191 @Override 192 public String toString() { 193 return new ToStringBuilder(this).append("method", method) 194 .append("uri", "\"" + uri + "\"") 195 .append("headers", headers) 196 .append("textInterpretedBody", getSecuredBody()) 197 .toString(); 198 } 199 200 public String getSecuredBody() { 201 return Optional.ofNullable(body) 202 .map(b -> tryToFilter(new String(b, StandardCharsets.UTF_8))) 203 .orElse("empty body"); 204 } 205 206 static String tryToFilter(final String input) { 207 return input.replaceAll("(\"\\w*([Pp]ass|access_token|refresh_token)\\w*\"):\"[^\"]*\"", 208 "$1:\"**removed from output**\""); 209 } 210 211 private ApiHttpRequest copy() { 212 return new ApiHttpRequest(this); 213 } 214 215 @Override 216 public boolean equals(Object o) { 217 if (this == o) 218 return true; 219 220 if (o == null || getClass() != o.getClass()) 221 return false; 222 223 ApiHttpRequest request = (ApiHttpRequest) o; 224 225 return new EqualsBuilder().append(method, request.method) 226 .append(uri, request.uri) 227 .append(headers, request.headers) 228 .append(body, request.body) 229 .append(contextMap, request.contextMap) 230 .isEquals(); 231 } 232 233 @Override 234 public int hashCode() { 235 return new HashCodeBuilder(17, 37).append(method) 236 .append(uri) 237 .append(headers) 238 .append(body) 239 .append(contextMap) 240 .toHashCode(); 241 } 242}