/* * Copyright 2016 Red Hat, Inc. and/or its affiliates * and other contributors as indicated by the @author tags. * * 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 * * 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.keycloak.authorization.client.util; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.StatusLine; import org.apache.http.client.HttpClient; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.RequestBuilder; import org.apache.http.entity.ByteArrayEntity; import org.apache.http.message.BasicNameValuePair; import org.apache.http.util.EntityUtils; import org.keycloak.authorization.client.ClientAuthenticator; import org.keycloak.authorization.client.Configuration; /** * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a> */ public class HttpMethod<R> { private final HttpClient httpClient; private final ClientAuthenticator authenticator; private final RequestBuilder builder; protected final Configuration configuration; protected final HashMap<String, String> headers; protected final HashMap<String, String> params; private HttpMethodResponse<R> response; public HttpMethod(Configuration configuration, ClientAuthenticator authenticator, RequestBuilder builder) { this(configuration, authenticator, builder, new HashMap<String, String>(), new HashMap<String, String>()); } public HttpMethod(Configuration configuration, ClientAuthenticator authenticator, RequestBuilder builder, HashMap<String, String> params, HashMap<String, String> headers) { this.configuration = configuration; this.httpClient = configuration.getHttpClient(); this.authenticator = authenticator; this.builder = builder; this.params = params; this.headers = headers; } public void execute() { execute(new HttpResponseProcessor<R>() { @Override public R process(byte[] entity) { return null; } }); } public R execute(HttpResponseProcessor<R> responseProcessor) { byte[] bytes = null; try { for (Map.Entry<String, String> header : this.headers.entrySet()) { this.builder.setHeader(header.getKey(), header.getValue()); } preExecute(this.builder); HttpResponse response = this.httpClient.execute(this.builder.build()); HttpEntity entity = response.getEntity(); if (entity != null) { bytes = EntityUtils.toByteArray(entity); } StatusLine statusLine = response.getStatusLine(); int statusCode = statusLine.getStatusCode(); if (statusCode < 200 || statusCode >= 300) { throw new HttpResponseException("Unexpected response from server: " + statusCode + " / " + statusLine.getReasonPhrase(), statusCode, statusLine.getReasonPhrase(), bytes); } if (bytes == null) { return null; } return responseProcessor.process(bytes); } catch (HttpResponseException e) { throw e; } catch (Exception e) { throw new RuntimeException("Error executing http method [" + builder + "]. Response : " + String.valueOf(bytes), e); } } protected void preExecute(RequestBuilder builder) { for (Map.Entry<String, String> param : params.entrySet()) { builder.addParameter(param.getKey(), param.getValue()); } } public HttpMethod<R> authorizationBearer(String bearer) { this.builder.addHeader("Authorization", "Bearer " + bearer); return this; } public HttpMethodResponse<R> response() { this.response = new HttpMethodResponse(this); return this.response; } public HttpMethodAuthenticator<R> authentication() { return new HttpMethodAuthenticator<R>(this, authenticator); } public HttpMethod<R> param(String name, String value) { this.params.put(name, value); return this; } public HttpMethod<R> json(byte[] entity) { this.builder.addHeader("Content-Type", "application/json"); this.builder.setEntity(new ByteArrayEntity(entity)); return this; } public HttpMethod<R> form() { return new HttpMethod<R>(this.configuration, authenticator, this.builder, this.params, this.headers) { @Override protected void preExecute(RequestBuilder builder) { if (params != null) { List<NameValuePair> formparams = new ArrayList<>(); for (Map.Entry<String, String> param : params.entrySet()) { formparams.add(new BasicNameValuePair(param.getKey(), param.getValue())); } try { builder.setEntity(new UrlEncodedFormEntity(formparams, "UTF-8")); } catch (UnsupportedEncodingException e) { throw new RuntimeException("Error creating form parameters"); } } } }; } }