/* * Copyright 2016 The Simple File Server Authors * * 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.sfs.integration.java.func; import com.google.common.collect.ListMultimap; import io.vertx.core.buffer.Buffer; import io.vertx.core.http.HttpClient; import io.vertx.core.http.HttpClientRequest; import io.vertx.core.http.HttpClientResponse; import io.vertx.core.http.HttpMethod; import org.sfs.rx.Holder2; import org.sfs.rx.HttpClientResponseBodyBuffer; import org.sfs.rx.ObservableFuture; import org.sfs.rx.RxHelper; import rx.Observable; import java.util.Map; import static com.google.common.collect.ArrayListMultimap.create; import static io.vertx.core.http.HttpHeaders.CONTENT_LENGTH; import static java.lang.String.valueOf; import static rx.Observable.error; import static rx.Observable.just; public abstract class ExecuteRequest { private final HttpClient httpClient; private final HttpMethod method; private final ListMultimap<String, String> headers = create(); private boolean chunked; private long timeoutMs; private boolean signRequest; public ExecuteRequest(HttpClient httpClient, HttpMethod httpMethod) { this.httpClient = httpClient; this.method = httpMethod; } public ExecuteRequest withHeader(String name, String value) { headers.put(name, value); return this; } public boolean isChunked() { return chunked; } public ExecuteRequest setChunked(boolean chunked) { this.chunked = chunked; return this; } public long getTimeoutMs() { return timeoutMs; } public ExecuteRequest setTimeoutMs(long timeoutMs) { this.timeoutMs = timeoutMs; return this; } public boolean isSignRequest() { return signRequest; } public ExecuteRequest setSignRequest(boolean signRequest) { this.signRequest = signRequest; return this; } public abstract long contentLength(); public abstract byte[] contentSha512(); public abstract Observable<Void> writeEntity(HttpClientRequest httpClientRequest); public Observable<HttpClientResponse> execute(String url) { ObservableFuture<HttpClientResponse> handler = RxHelper.observableFuture(); HttpClientRequest httpClientRequest = httpClient.requestAbs(method, url, httpClientResponse -> { httpClientResponse.pause(); handler.complete(httpClientResponse); }).setChunked(chunked) .setTimeout(timeoutMs) .exceptionHandler(handler::fail); for (Map.Entry<String, String> entry : headers.entries()) { httpClientRequest.putHeader(entry.getKey(), entry.getValue()); } long contentLength = contentLength(); if (!chunked && contentLength >= 0 && !httpClientRequest.headers().contains(CONTENT_LENGTH)) { httpClientRequest.putHeader(CONTENT_LENGTH, valueOf(contentLength)); } return writeEntity(httpClientRequest) .doOnNext(aVoid -> httpClientRequest.end()) .flatMap(aVoid -> handler); } public Observable<Holder2<HttpClientResponse, Buffer>> executeAndBufferResponse(String url) { return execute(url) .flatMap(httpClientResponse -> just(httpClientResponse) .flatMap(new HttpClientResponseBodyBuffer()) .onErrorResumeNext(throwable -> { httpClientResponse.resume(); return error(throwable); }) .map(buffer -> new Holder2<>(httpClientResponse, buffer))); } }