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        request.contextMap = contextMap;
073
074        return request;
075    }
076
077    public Object getContext(Object key) {
078        return contextMap.get(key);
079    }
080
081    public ApiHttpRequest addContext(Object key, Object value) {
082        final ApiHttpRequest request = copy();
083        final Map<Object, Object> contextMap = new HashMap<>(request.contextMap);
084        contextMap.put(key, value);
085        request.contextMap = contextMap;
086
087        return request;
088    }
089
090    public ApiHttpMethod getMethod() {
091        return method;
092    }
093
094    public ApiHttpRequest withMethod(final ApiHttpMethod method) {
095        ApiHttpRequest request = copy();
096        request.method = method;
097
098        return request;
099    }
100
101    public ApiHttpHeaders getHeaders() {
102        if (headers == null) {
103            this.headers = new ApiHttpHeaders();
104        }
105        return headers;
106    }
107
108    public ApiHttpRequest addHeader(final String key, final String value) {
109        ApiHttpRequest request = copy();
110        request.headers = getHeaders().addHeader(key, value);
111
112        return request;
113    }
114
115    public ApiHttpRequest withHeaders(final ApiHttpHeaders headers) {
116        ApiHttpRequest request = copy();
117        request.headers = headers;
118        return request;
119    }
120
121    public ApiHttpRequest withHeader(final String key, final String value) {
122        ApiHttpRequest request = copy();
123        request.headers = getHeaders().withHeader(key, value);
124
125        return request;
126    }
127
128    public ApiHttpRequest withoutHeader(final String key) {
129        ApiHttpRequest request = copy();
130        request.headers = getHeaders().withoutHeader(key);
131
132        return request;
133    }
134
135    public byte[] getBody() {
136        return body;
137    }
138
139    public ApiHttpRequest withBody(final byte[] body) {
140        ApiHttpRequest request = copy();
141        request.body = body;
142        return request;
143    }
144
145    public ApiHttpRequest withBody(final String body) {
146        ApiHttpRequest request = copy();
147        if (body == null) {
148            request.body = null;
149        }
150        else {
151            request.body = body.getBytes(StandardCharsets.UTF_8);
152        }
153
154        return request;
155    }
156
157    public URI getUri() {
158        return uri;
159    }
160
161    public URL getUrl() {
162        try {
163            return uri.toURL();
164        }
165        catch (MalformedURLException e) {
166            throw new IllegalStateException("Malformed URI", e);
167        }
168    }
169
170    public ApiHttpRequest withUri(final String uri) {
171        ApiHttpRequest request = copy();
172        request.uri = URI.create(uri);
173        return request;
174    }
175
176    public ApiHttpRequest withUri(final URI uri) {
177        ApiHttpRequest request = copy();
178        request.uri = uri;
179
180        return request;
181    }
182
183    public ApiHttpRequest resolve(final URI baseUri) {
184        return withUri(baseUri.resolve(this.uri));
185    }
186
187    @Override
188    public String toString() {
189        return new ToStringBuilder(this).append("method", method)
190                .append("uri", "\"" + uri + "\"")
191                .append("headers", headers)
192                .append("textInterpretedBody", getSecuredBody())
193                .toString();
194    }
195
196    public String getSecuredBody() {
197        return Optional.ofNullable(body)
198                .map(b -> tryToFilter(new String(b, StandardCharsets.UTF_8)))
199                .orElse("empty body");
200    }
201
202    static String tryToFilter(final String input) {
203        return input.replaceAll("(\"\\w*([Pp]ass|access_token|refresh_token)\\w*\"):\"[^\"]*\"",
204            "$1:\"**removed from output**\"");
205    }
206
207    private ApiHttpRequest copy() {
208        return new ApiHttpRequest(this);
209    }
210
211    @Override
212    public boolean equals(Object o) {
213        if (this == o)
214            return true;
215
216        if (o == null || getClass() != o.getClass())
217            return false;
218
219        ApiHttpRequest request = (ApiHttpRequest) o;
220
221        return new EqualsBuilder().append(method, request.method)
222                .append(uri, request.uri)
223                .append(headers, request.headers)
224                .append(body, request.body)
225                .append(contextMap, request.contextMap)
226                .isEquals();
227    }
228
229    @Override
230    public int hashCode() {
231        return new HashCodeBuilder(17, 37).append(method)
232                .append(uri)
233                .append(headers)
234                .append(body)
235                .append(contextMap)
236                .toHashCode();
237    }
238}