2 * Copyright 2016 Huawei Technologies Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package org.onap.vfc.nfvo.vnfm.svnfm.vnfmadapter.common.restclient;
19 import java.io.ByteArrayInputStream;
20 import java.io.IOException;
21 import java.io.UnsupportedEncodingException;
22 import java.net.URLEncoder;
23 import java.text.SimpleDateFormat;
24 import java.util.Calendar;
25 import java.util.Date;
27 import java.util.concurrent.atomic.AtomicInteger;
29 import org.eclipse.jetty.client.Address;
30 import org.eclipse.jetty.client.HttpClient;
31 import org.eclipse.jetty.client.HttpExchange;
32 import org.eclipse.jetty.http.HttpMethods;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
42 * @version Aug 9, 2016
44 public abstract class HttpBaseRest implements Restful {
46 private static final Logger LOG = LoggerFactory.getLogger(HttpRest.class);
48 final AtomicInteger requestId = new AtomicInteger(0);
50 protected HttpClient client = null;
52 private static final String LOCAL_HOST = "127.0.0.1";
54 static final String HTTP_PATCH = "PATCH";
56 String defaultIP = LOCAL_HOST;
58 int defaultPort = -10000;
60 int defaultTimeout = 30000;
62 final String procenameRouteID = "RouteID-" + System.currentTimeMillis() + "-";
71 public HttpBaseRest() {
75 protected void createHttpClient() {
76 client = new HttpClient();
79 protected RestHttpContentExchange createRestHttpContentExchange(final RestfulAsyncCallback callback) {
80 final RestHttpContentExchange exchange = new RestHttpContentExchange(true, callback);
81 exchange.setScheme("http");
85 private String encodeParams(final RestfulParametes restParametes) throws ServiceException {
86 final Map<String, String> parm = restParametes.getParamMap();
88 boolean bHasParma = false;
89 final StringBuilder builder = new StringBuilder();
91 for(final String key : parm.keySet()) {
92 value = parm.get(key);
98 str = String.format("&%s=%s", URLEncoder.encode(key, RestfulClientConst.ENCODING),
99 URLEncoder.encode(value, RestfulClientConst.ENCODING));
102 str = String.format("%s=%s", URLEncoder.encode(key, RestfulClientConst.ENCODING),
103 URLEncoder.encode(value, RestfulClientConst.ENCODING));
107 } catch(final UnsupportedEncodingException ex) {
108 LOG.error("unsupported encoding: ", ex);
109 throw new ServiceException("Broken VM does not support UTF-8");
111 return builder.toString();
114 private void processHeader(final RestHttpContentExchange contentExchange, final Map<String, String> headerMap) {
115 for(final String key : headerMap.keySet()) {
116 final String value = headerMap.get(key);
117 contentExchange.addRequestHeader(key, value);
122 private void setContentExchangeParams(final RestHttpContentExchange contentExchange) {
123 final String contentType = contentExchange.getRequestFields().getStringField("Content-Type");
124 if(null == contentType || contentType.isEmpty()) {
125 // application/json;charset=utf-8
126 contentExchange.setRequestContentType(RestfulClientConst.APPLICATION_FORM_URLENCODED);
128 final String encoding = contentExchange.getRequestFields().getStringField("Accept-Encoding");
129 if(null == encoding || encoding.isEmpty()) {
131 contentExchange.setRequestHeader("Accept-Encoding", "*/*");
133 contentExchange.setVersion(11);
141 * @param restParametes
145 * @throws ServiceException
148 protected RestfulResponse sendHttpRequest(final String method, final String servicePath,
149 final RestfulParametes restParametes, final RestfulOptions options, final RestfulAsyncCallback callback)
150 throws ServiceException {
151 final RestHttpContentExchange contentExchange = createRestHttpContentExchange(callback);
152 if(null == restParametes) {
153 return new RestfulResponse();
155 final String requestTrace = this.getReuqestIdString();
156 restParametes.putHttpContextHeader(RestfulClientConst.REQUEST_ID, requestTrace);
158 RestfulResponse rsp = null;
160 contentExchange.setMethod(method);
161 final String str = encodeParams(restParametes);
162 final StringBuilder builder = new StringBuilder();
163 builder.append(servicePath);
164 if(str.length() > 0 && (method.equals(HttpMethods.GET) || method.equals(HttpMethods.DELETE)
165 || method.equals(HttpMethods.HEAD))) {
169 setDefaultUrl(contentExchange, options, builder);
170 processHeader(contentExchange, restParametes.getHeaderMap());
171 setContentExchangeParams(contentExchange);
173 setPostPutParam(method, restParametes, contentExchange, str);
174 setTimeout(options, contentExchange);
176 client.send(contentExchange);
177 rsp = callbackExecute(callback, contentExchange);
178 } catch(final Exception e) {
179 LOG.error("request reply message have exception:status is "
180 + RestHttpContentExchange.toState(contentExchange.getStatus()));
181 throw new ServiceException(e);
186 private void setDefaultUrl(final RestHttpContentExchange contentExchange, final RestfulOptions options,
187 final StringBuilder url) {
189 if(url.toString().startsWith("http")) {
190 contentExchange.setURL(url.toString());
192 String host = defaultIP;
193 int iPort = defaultPort;
194 if(options != null) {
195 host = options.getHost();
199 iPort = options.getPort();
204 // Integer.getInteger(".http.client.maxThread",30)
205 contentExchange.setAddress(new Address(host, iPort));
206 contentExchange.setRequestURI(url.toString());
210 private String getReuqestIdString() {
211 if(this.requestId.get() == 0x7FFFFFFF) {
212 this.requestId.set(1);
214 final int reqId = this.requestId.getAndIncrement();
215 final StringBuilder builder = new StringBuilder(this.procenameRouteID);
217 final SimpleDateFormat dateFormate = new SimpleDateFormat("yyMMdd");
218 final SimpleDateFormat timeFormate = new SimpleDateFormat("HHmmss");
219 final Date date = Calendar.getInstance().getTime();
220 builder.append(dateFormate.format(date) + timeFormate.format(date));
222 builder.append(reqId);
223 return builder.toString();
226 private void setPostPutParam(final String method, final RestfulParametes restParametes,
227 final RestHttpContentExchange contentExchange, final String str) throws UnsupportedEncodingException {
228 if(HttpMethods.POST.equals(method) || HttpMethods.PUT.equals(method) || HTTP_PATCH.equals(method)) {
229 ByteArrayInputStream buff;
230 final String tmpRaw = restParametes.getRawData();
232 buff = new ByteArrayInputStream(str.getBytes(RestfulClientConst.ENCODING));
234 buff = new ByteArrayInputStream(tmpRaw.getBytes(RestfulClientConst.ENCODING));
236 final int len = buff.available();
237 contentExchange.setRequestContentSource(buff);
238 contentExchange.setRequestHeader("content-length", String.valueOf(len));
242 private void setTimeout(final RestfulOptions options, final RestHttpContentExchange contentExchange) {
243 if(options != null) {
244 final long timeout = options.getRestTimeout();
246 contentExchange.setTimeout(timeout);
248 contentExchange.setTimeout(defaultTimeout);
251 contentExchange.setTimeout(defaultTimeout);
255 private RestfulResponse callbackExecute(final RestfulAsyncCallback callback,
256 final RestHttpContentExchange contentExchange) throws InterruptedException, IOException, ServiceException {
257 if(callback == null) {
258 final int exchangeState = contentExchange.waitForDone();
259 if(exchangeState == HttpExchange.STATUS_COMPLETED) {
260 return contentExchange.getResponse();
261 } else if(exchangeState == HttpExchange.STATUS_EXCEPTED) {
262 throw new ServiceException(
263 "request is exception: " + RestHttpContentExchange.toState(HttpExchange.STATUS_EXCEPTED));
264 } else if(exchangeState == HttpExchange.STATUS_EXPIRED) {
265 throw new ServiceException(
266 "request is expierd: " + RestHttpContentExchange.toState(HttpExchange.STATUS_EXPIRED));