org.smartboot.http.client.HttpRest Maven / Gradle / Ivy
/*******************************************************************************
* Copyright (c) 2017-2021, org.smartboot. All rights reserved.
* project name: smart-http
* file name: HttpRest.java
* Date: 2021-02-07
* Author: sandao ([email protected])
******************************************************************************/
package org.smartboot.http.client;
import org.smartboot.http.client.impl.DefaultHttpResponseHandler;
import org.smartboot.http.client.impl.HttpRequestImpl;
import org.smartboot.http.client.impl.HttpResponseImpl;
import org.smartboot.http.common.enums.HeaderNameEnum;
import org.smartboot.socket.transport.AioSession;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.AbstractQueue;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Consumer;
/**
* @author 三刀([email protected])
* @version V1.0 , 2021/2/3
*/
public class HttpRest {
private final static String DEFAULT_USER_AGENT = "smart-http";
protected final HttpRequestImpl request;
protected final CompletableFuture completableFuture = new CompletableFuture<>();
private final AbstractQueue queue;
private Map queryParams = null;
private boolean commit = false;
private Body body;
/**
* http body 解码器
*/
private ResponseHandler responseHandler = new DefaultHttpResponseHandler();
private final HttpResponseImpl response;
HttpRest(AioSession session, AbstractQueue queue) {
this.request = new HttpRequestImpl(session);
this.queue = queue;
this.response = new HttpResponseImpl(session, completableFuture);
}
protected final void willSendRequest() {
if (commit) {
return;
}
commit = true;
resetUri();
Collection headers = request.getHeaderNames();
if (!headers.contains(HeaderNameEnum.USER_AGENT.getName())) {
request.addHeader(HeaderNameEnum.USER_AGENT.getName(), DEFAULT_USER_AGENT);
}
response.setResponseHandler(responseHandler);
AioSession session = response.getSession();
ResponseAttachment attachment = session.getAttachment();
synchronized (session) {
if (attachment.getResponse() == null) {
attachment.setResponse(response);
System.out.println("aaaa");
} else {
System.out.println("bbb");
queue.offer(response);
}
}
}
private void resetUri() {
if (queryParams == null) {
return;
}
StringBuilder stringBuilder = new StringBuilder(request.getUri());
int index = request.getUri().indexOf("#");
if (index > 0) {
stringBuilder.setLength(index);
}
index = request.getUri().indexOf("?");
if (index == -1) {
stringBuilder.append('?');
} else if (index < stringBuilder.length() - 1) {
stringBuilder.append('&');
}
queryParams.forEach((key, value) -> {
try {
stringBuilder.append(key).append('=').append(URLEncoder.encode(value, "utf8")).append('&');
} catch (UnsupportedEncodingException e) {
stringBuilder.append(key).append('=').append(value).append('&');
}
});
if (stringBuilder.length() > 0) {
stringBuilder.setLength(stringBuilder.length() - 1);
}
request.setUri(stringBuilder.toString());
}
public Body extends HttpRest> body() {
if (body == null) {
body = new Body() {
@Override
public Body write(byte[] bytes, int offset, int len) {
try {
willSendRequest();
request.getOutputStream().write(bytes, offset, len);
} catch (IOException e) {
System.out.println("body stream write error! " + e.getMessage());
completableFuture.completeExceptionally(e);
}
return this;
}
@Override
public Body flush() {
try {
request.getOutputStream().flush();
} catch (IOException e) {
System.out.println("body stream flush error! " + e.getMessage());
e.printStackTrace();
completableFuture.completeExceptionally(e);
}
return this;
}
@Override
public HttpRest done() {
return HttpRest.this;
}
};
}
return body;
}
public final Future done() {
try {
willSendRequest();
request.getOutputStream().close();
request.getOutputStream().flush();
} catch (Throwable e) {
completableFuture.completeExceptionally(e);
}
return new Future() {
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
return completableFuture.cancel(mayInterruptIfRunning);
}
@Override
public boolean isCancelled() {
return completableFuture.isCancelled();
}
@Override
public boolean isDone() {
return completableFuture.isDone();
}
@Override
public HttpResponse get() throws InterruptedException, ExecutionException {
return completableFuture.get();
}
@Override
public HttpResponse get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
return completableFuture.get(timeout, unit);
}
};
}
public HttpRest onSuccess(Consumer consumer) {
completableFuture.thenAccept(consumer);
return this;
}
public HttpRest onFailure(Consumer consumer) {
completableFuture.exceptionally(throwable -> {
consumer.accept(throwable);
return null;
});
return this;
}
public HttpRest setMethod(String method) {
request.setMethod(method);
return this;
}
public Header extends HttpRest> header() {
return new Header() {
@Override
public Header add(String headerName, String headerValue) {
request.addHeader(headerName, headerValue);
return this;
}
@Override
public Header set(String headerName, String headerValue) {
request.setHeader(headerName, headerValue);
return this;
}
@Override
public Header setContentType(String contentType) {
request.setContentType(contentType);
return this;
}
@Override
public Header setContentLength(int contentLength) {
request.setContentLength(contentLength);
return this;
}
@Override
public HttpRest done() {
return HttpRest.this;
}
};
}
/**
* 在 uri 后面添加请求参数
*
* @param name 参数名
* @param value 参数值
*/
public final HttpRest addQueryParam(String name, String value) {
if (queryParams == null) {
queryParams = new HashMap<>();
}
queryParams.put(name, value);
return this;
}
/**
* Http 响应事件
*/
public HttpRest onResponse(ResponseHandler responseHandler) {
this.responseHandler = Objects.requireNonNull(responseHandler);
return this;
}
}